1*3cab2bb3Spatrick//===-- clzdi2.c - Implement __clzdi2 -------------------------------------===// 2*3cab2bb3Spatrick// 3*3cab2bb3Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*3cab2bb3Spatrick// See https://llvm.org/LICENSE.txt for license information. 5*3cab2bb3Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*3cab2bb3Spatrick// 7*3cab2bb3Spatrick//===----------------------------------------------------------------------===// 8*3cab2bb3Spatrick// 9*3cab2bb3Spatrick// This file implements count leading zeros for 64bit arguments. 10*3cab2bb3Spatrick// 11*3cab2bb3Spatrick//===----------------------------------------------------------------------===// 12*3cab2bb3Spatrick 13*3cab2bb3Spatrick#include "../assembly.h" 14*3cab2bb3Spatrick 15*3cab2bb3Spatrick .syntax unified 16*3cab2bb3Spatrick .text 17*3cab2bb3Spatrick DEFINE_CODE_STATE 18*3cab2bb3Spatrick 19*3cab2bb3Spatrick .p2align 2 20*3cab2bb3SpatrickDEFINE_COMPILERRT_FUNCTION(__clzdi2) 21*3cab2bb3Spatrick#ifdef __ARM_FEATURE_CLZ 22*3cab2bb3Spatrick#ifdef __ARMEB__ 23*3cab2bb3Spatrick cmp r0, 0 24*3cab2bb3Spatrick itee ne 25*3cab2bb3Spatrick clzne r0, r0 26*3cab2bb3Spatrick clzeq r0, r1 27*3cab2bb3Spatrick addeq r0, r0, 32 28*3cab2bb3Spatrick#else 29*3cab2bb3Spatrick cmp r1, 0 30*3cab2bb3Spatrick itee ne 31*3cab2bb3Spatrick clzne r0, r1 32*3cab2bb3Spatrick clzeq r0, r0 33*3cab2bb3Spatrick addeq r0, r0, 32 34*3cab2bb3Spatrick#endif 35*3cab2bb3Spatrick JMP(lr) 36*3cab2bb3Spatrick#else 37*3cab2bb3Spatrick // Assumption: n != 0 38*3cab2bb3Spatrick 39*3cab2bb3Spatrick // r0: n 40*3cab2bb3Spatrick // r1: upper half of n, overwritten after check 41*3cab2bb3Spatrick // r1: count of leading zeros in n + 1 42*3cab2bb3Spatrick // r2: scratch register for shifted r0 43*3cab2bb3Spatrick#ifdef __ARMEB__ 44*3cab2bb3Spatrick cmp r0, 0 45*3cab2bb3Spatrick moveq r0, r1 46*3cab2bb3Spatrick#else 47*3cab2bb3Spatrick cmp r1, 0 48*3cab2bb3Spatrick movne r0, r1 49*3cab2bb3Spatrick#endif 50*3cab2bb3Spatrick movne r1, 1 51*3cab2bb3Spatrick moveq r1, 33 52*3cab2bb3Spatrick 53*3cab2bb3Spatrick // Basic block: 54*3cab2bb3Spatrick // if ((r0 >> SHIFT) == 0) 55*3cab2bb3Spatrick // r1 += SHIFT; 56*3cab2bb3Spatrick // else 57*3cab2bb3Spatrick // r0 >>= SHIFT; 58*3cab2bb3Spatrick // for descending powers of two as SHIFT. 59*3cab2bb3Spatrick#define BLOCK(shift) \ 60*3cab2bb3Spatrick lsrs r2, r0, shift; \ 61*3cab2bb3Spatrick movne r0, r2; \ 62*3cab2bb3Spatrick addeq r1, shift \ 63*3cab2bb3Spatrick 64*3cab2bb3Spatrick BLOCK(16) 65*3cab2bb3Spatrick BLOCK(8) 66*3cab2bb3Spatrick BLOCK(4) 67*3cab2bb3Spatrick BLOCK(2) 68*3cab2bb3Spatrick 69*3cab2bb3Spatrick // The basic block invariants at this point are (r0 >> 2) == 0 and 70*3cab2bb3Spatrick // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. 71*3cab2bb3Spatrick // 72*3cab2bb3Spatrick // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) 73*3cab2bb3Spatrick // ---+----------------+----------------+------------+-------------- 74*3cab2bb3Spatrick // 1 | 1 | 0 | 0 | 1 75*3cab2bb3Spatrick // 2 | 0 | 1 | -1 | 0 76*3cab2bb3Spatrick // 3 | 0 | 1 | -1 | 0 77*3cab2bb3Spatrick // 78*3cab2bb3Spatrick // The r1's initial value of 1 compensates for the 1 here. 79*3cab2bb3Spatrick sub r0, r1, r0, lsr #1 80*3cab2bb3Spatrick 81*3cab2bb3Spatrick JMP(lr) 82*3cab2bb3Spatrick#endif // __ARM_FEATURE_CLZ 83*3cab2bb3SpatrickEND_COMPILERRT_FUNCTION(__clzdi2) 84*3cab2bb3Spatrick 85*3cab2bb3SpatrickNO_EXEC_STACK_DIRECTIVE 86*3cab2bb3Spatrick 87