diff options
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/builtins/arm/clzsi2.S')
-rw-r--r-- | contrib/llvm-project/compiler-rt/lib/builtins/arm/clzsi2.S | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/builtins/arm/clzsi2.S b/contrib/llvm-project/compiler-rt/lib/builtins/arm/clzsi2.S new file mode 100644 index 000000000000..5d86fe486edd --- /dev/null +++ b/contrib/llvm-project/compiler-rt/lib/builtins/arm/clzsi2.S @@ -0,0 +1,66 @@ +//===-- clzsi2.c - Implement __clzsi2 -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements count leading zeros for 32bit arguments. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + + .syntax unified + .text + DEFINE_CODE_STATE + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__clzsi2) +#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) + +NO_EXEC_STACK_DIRECTIVE + |