Path: blob/main/contrib/llvm-project/compiler-rt/lib/builtins/arm/clzsi2.S
35292 views
//===-- clzsi2.c - Implement __clzsi2 -------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements count leading zeros for 32bit arguments.9//10//===----------------------------------------------------------------------===//1112#include "../assembly.h"1314.syntax unified15.text16DEFINE_CODE_STATE1718.p2align 219DEFINE_COMPILERRT_FUNCTION(__clzsi2)20#ifdef __ARM_FEATURE_CLZ21clz r0, r022JMP(lr)23#else24// Assumption: n != 02526// r0: n27// r1: count of leading zeros in n + 128// r2: scratch register for shifted r029mov r1, 13031// Basic block:32// if ((r0 >> SHIFT) == 0)33// r1 += SHIFT;34// else35// r0 >>= SHIFT;36// for descending powers of two as SHIFT.3738#define BLOCK(shift) \39lsrs r2, r0, shift; \40movne r0, r2; \41addeq r1, shift \4243BLOCK(16)44BLOCK(8)45BLOCK(4)46BLOCK(2)4748// The basic block invariants at this point are (r0 >> 2) == 0 and49// r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1.50//51// r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)52// ---+----------------+----------------+------------+--------------53// 1 | 1 | 0 | 0 | 154// 2 | 0 | 1 | -1 | 055// 3 | 0 | 1 | -1 | 056//57// The r1's initial value of 1 compensates for the 1 here.58sub r0, r1, r0, lsr #15960JMP(lr)61#endif // __ARM_FEATURE_CLZ62END_COMPILERRT_FUNCTION(__clzsi2)6364NO_EXEC_STACK_DIRECTIVE65666768