diff options
Diffstat (limited to 'lib/builtins/arm/clzsi2.S')
| -rw-r--r-- | lib/builtins/arm/clzsi2.S | 76 | 
1 files changed, 76 insertions, 0 deletions
| diff --git a/lib/builtins/arm/clzsi2.S b/lib/builtins/arm/clzsi2.S new file mode 100644 index 000000000000..1cd379bfb0a9 --- /dev/null +++ b/lib/builtins/arm/clzsi2.S @@ -0,0 +1,76 @@ +/* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------=== + * + *               The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements count leading zeros for 32bit arguments. + * + * ===----------------------------------------------------------------------=== + */ +#include "../assembly.h" + +	.syntax unified +	.text +#if __ARM_ARCH_ISA_THUMB == 2 +	.thumb +#endif + +	.p2align	2 +#if __ARM_ARCH_ISA_THUMB == 2 +DEFINE_COMPILERRT_THUMB_FUNCTION(__clzsi2) +#else +DEFINE_COMPILERRT_FUNCTION(__clzsi2) +#endif +#ifdef __ARM_FEATURE_CLZ +	clz	r0, r0 +	JMP(lr) +#else +	/* Assumption: n != 0 */ + +	/* +	 * r0: n +	 * r1: count of leading zeros in n + 1 +	 * r2: scratch register for shifted r0 +	 */ +	mov	r1, 1 + +	/* +	 * Basic block: +	 * if ((r0 >> SHIFT) == 0) +	 *   r1 += SHIFT; +	 * else +	 *   r0 >>= SHIFT; +	 * for descending powers of two as SHIFT. +	 */ + +#define BLOCK(shift) \ +	lsrs	r2, r0, shift; \ +	movne	r0, r2; \ +	addeq	r1, shift \ + +	BLOCK(16) +	BLOCK(8) +	BLOCK(4) +	BLOCK(2) + +	/* +	 * The basic block invariants at this point are (r0 >> 2) == 0 and +	 * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. +	 * +	 * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) +	 * ---+----------------+----------------+------------+-------------- +	 * 1  | 1              | 0              | 0          | 1 +	 * 2  | 0              | 1              | -1         | 0 +	 * 3  | 0              | 1              | -1         | 0 +	 * +	 * The r1's initial value of 1 compensates for the 1 here. +	 */ +	sub	r0, r1, r0, lsr #1 + +	JMP(lr) +#endif // __ARM_FEATURE_CLZ +END_COMPILERRT_FUNCTION(__clzsi2) | 
