67 lines · plain
1//===-- clzsi2.c - Implement __clzsi2 -------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements count leading zeros for 32bit arguments.10//11//===----------------------------------------------------------------------===//12 13#include "../assembly.h"14 15 .syntax unified16 .text17 DEFINE_CODE_STATE18 19 .p2align 220DEFINE_COMPILERRT_FUNCTION(__clzsi2)21#ifdef __ARM_FEATURE_CLZ22 clz r0, r023 JMP(lr)24#else25 // Assumption: n != 026 27 // r0: n28 // r1: count of leading zeros in n + 129 // r2: scratch register for shifted r030 mov r1, 131 32 // Basic block:33 // if ((r0 >> SHIFT) == 0)34 // r1 += SHIFT;35 // else36 // r0 >>= SHIFT;37 // for descending powers of two as SHIFT.38 39#define BLOCK(shift) \40 lsrs r2, r0, shift; \41 movne r0, r2; \42 addeq r1, shift \43 44 BLOCK(16)45 BLOCK(8)46 BLOCK(4)47 BLOCK(2)48 49 // The basic block invariants at this point are (r0 >> 2) == 0 and50 // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1.51 //52 // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)53 // ---+----------------+----------------+------------+--------------54 // 1 | 1 | 0 | 0 | 155 // 2 | 0 | 1 | -1 | 056 // 3 | 0 | 1 | -1 | 057 //58 // The r1's initial value of 1 compensates for the 1 here.59 sub r0, r1, r0, lsr #160 61 JMP(lr)62#endif // __ARM_FEATURE_CLZ63END_COMPILERRT_FUNCTION(__clzsi2)64 65NO_EXEC_STACK_DIRECTIVE66 67