diff --git a/libc/arch-arm/bionic/ffs.S b/libc/arch-arm/bionic/ffs.S index c59091fb6..701af8ccc 100644 --- a/libc/arch-arm/bionic/ffs.S +++ b/libc/arch-arm/bionic/ffs.S @@ -31,55 +31,11 @@ #include #include -/* - * 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) /* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */ rsb r1, r0, #0 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 rsbne r0, r0, #32 bx lr END(ffs) -#endif /* !defined(__ARM_HAVE_CLZ) */ - diff --git a/tests/Android.mk b/tests/Android.mk index eb97e6cc1..da9d676d1 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -71,6 +71,7 @@ test_src_files = \ stdio_test.cpp \ stdlib_test.cpp \ string_test.cpp \ + strings_test.cpp \ stubs_test.cpp \ unistd_test.cpp \ diff --git a/tests/strings_test.cpp b/tests/strings_test.cpp new file mode 100644 index 000000000..5200859fb --- /dev/null +++ b/tests/strings_test.cpp @@ -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 + +#include +#include + +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)); +}