am 2fee0340: Merge "Everyone has CLZ."

# Via Elliott Hughes (1) and Gerrit Code Review (1)
* commit '2fee0340a93637507de6a860914dc3e14d44ee94':
  Everyone has CLZ.
This commit is contained in:
Elliott Hughes 2013-02-13 15:27:10 -08:00 committed by Android Git Automerger
commit a7603ff87a
3 changed files with 33 additions and 44 deletions

View File

@ -31,55 +31,11 @@
#include <machine/asm.h> #include <machine/asm.h>
#include <machine/cpu-features.h> #include <machine/cpu-features.h>
/*
* ffs - find first set bit, this algorithm isolates the first set
* bit, then multiplies the number by 0x0450fbaf which leaves the top
* 6 bits as an index into the table. This algorithm should be a win
* over the checking each bit in turn as per the C compiled version.
*
* Some newer ARM architectures have an instruction named
* CLZ (count leading Zero's) that is used
*
* This is the ffs algorithm devised by d.seal and posted to comp.sys.arm on
* 16 Feb 1994.
*/
ENTRY(ffs) ENTRY(ffs)
/* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */ /* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */
rsb r1, r0, #0 rsb r1, r0, #0
ands r0, r0, r1 ands r0, r0, r1
#ifndef __ARM_HAVE_CLZ
/*
* now r0 has at most one set bit, call this X
* if X = 0, all further instructions are skipped
*/
adrne r2, .L_ffs_table
orrne r0, r0, r0, lsl #4 /* r0 = X * 0x11 */
orrne r0, r0, r0, lsl #6 /* r0 = X * 0x451 */
rsbne r0, r0, r0, lsl #16 /* r0 = X * 0x0450fbaf */
/* now lookup in table indexed on top 6 bits of r0 */
ldrneb r0, [ r2, r0, lsr #26 ]
bx lr
END(ffs)
.text;
.type .L_ffs_table, _ASM_TYPE_OBJECT;
.L_ffs_table:
/* 0 1 2 3 4 5 6 7 */
.byte 0, 1, 2, 13, 3, 7, 0, 14 /* 0- 7 */
.byte 4, 0, 8, 0, 0, 0, 0, 15 /* 8-15 */
.byte 11, 5, 0, 0, 9, 0, 0, 26 /* 16-23 */
.byte 0, 0, 0, 0, 0, 22, 28, 16 /* 24-31 */
.byte 32, 12, 6, 0, 0, 0, 0, 0 /* 32-39 */
.byte 10, 0, 0, 25, 0, 0, 21, 27 /* 40-47 */
.byte 31, 0, 0, 0, 0, 24, 0, 20 /* 48-55 */
.byte 30, 0, 23, 19, 29, 18, 17, 0 /* 56-63 */
#else /* !defined(__ARM_HAVE_CLZ) */
clzne r0, r0 clzne r0, r0
rsbne r0, r0, #32 rsbne r0, r0, #32
bx lr bx lr
END(ffs) END(ffs)
#endif /* !defined(__ARM_HAVE_CLZ) */

View File

@ -71,6 +71,7 @@ test_src_files = \
stdio_test.cpp \ stdio_test.cpp \
stdlib_test.cpp \ stdlib_test.cpp \
string_test.cpp \ string_test.cpp \
strings_test.cpp \
stubs_test.cpp \ stubs_test.cpp \
unistd_test.cpp \ unistd_test.cpp \

32
tests/strings_test.cpp Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <errno.h>
#include <strings.h>
TEST(strings, ffs) {
ASSERT_EQ( 0, ffs(0x00000000));
ASSERT_EQ( 1, ffs(0x00000001));
ASSERT_EQ( 6, ffs(0x00000020));
ASSERT_EQ(11, ffs(0x00000400));
ASSERT_EQ(16, ffs(0x00008000));
ASSERT_EQ(17, ffs(0x00010000));
ASSERT_EQ(22, ffs(0x00200000));
ASSERT_EQ(27, ffs(0x04000000));
ASSERT_EQ(32, ffs(0x80000000));
}