Path: blob/main/contrib/llvm-project/compiler-rt/lib/builtins/arm/clzdi2.S
35292 views
//===-- clzdi2.c - Implement __clzdi2 -------------------------------------===//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 64bit arguments.9//10//===----------------------------------------------------------------------===//1112#include "../assembly.h"1314.syntax unified15.text16DEFINE_CODE_STATE1718.p2align 219DEFINE_COMPILERRT_FUNCTION(__clzdi2)20#ifdef __ARM_FEATURE_CLZ21#ifdef __ARMEB__22cmp r0, 023itee ne24clzne r0, r025clzeq r0, r126addeq r0, r0, 3227#else28cmp r1, 029itee ne30clzne r0, r131clzeq r0, r032addeq r0, r0, 3233#endif34JMP(lr)35#else36// Assumption: n != 03738// r0: n39// r1: upper half of n, overwritten after check40// r1: count of leading zeros in n + 141// r2: scratch register for shifted r042#ifdef __ARMEB__43cmp r0, 044moveq r0, r145#else46cmp r1, 047movne r0, r148#endif49movne r1, 150moveq r1, 335152// Basic block:53// if ((r0 >> SHIFT) == 0)54// r1 += SHIFT;55// else56// r0 >>= SHIFT;57// for descending powers of two as SHIFT.58#define BLOCK(shift) \59lsrs r2, r0, shift; \60movne r0, r2; \61addeq r1, shift \6263BLOCK(16)64BLOCK(8)65BLOCK(4)66BLOCK(2)6768// The basic block invariants at this point are (r0 >> 2) == 0 and69// r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1.70//71// r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)72// ---+----------------+----------------+------------+--------------73// 1 | 1 | 0 | 0 | 174// 2 | 0 | 1 | -1 | 075// 3 | 0 | 1 | -1 | 076//77// The r1's initial value of 1 compensates for the 1 here.78sub r0, r1, r0, lsr #17980JMP(lr)81#endif // __ARM_FEATURE_CLZ82END_COMPILERRT_FUNCTION(__clzdi2)8384NO_EXEC_STACK_DIRECTIVE85868788