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:
commit
a7603ff87a
@ -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) */
|
|
||||||
|
|
||||||
|
@ -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
32
tests/strings_test.cpp
Normal 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));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user