1*7c3d14c8STreehugger Robot/* ===-- clzdi2.c - Implement __clzdi2 -------------------------------------=== 2*7c3d14c8STreehugger Robot * 3*7c3d14c8STreehugger Robot * The LLVM Compiler Infrastructure 4*7c3d14c8STreehugger Robot * 5*7c3d14c8STreehugger Robot * This file is dual licensed under the MIT and the University of Illinois Open 6*7c3d14c8STreehugger Robot * Source Licenses. See LICENSE.TXT for details. 7*7c3d14c8STreehugger Robot * 8*7c3d14c8STreehugger Robot * ===----------------------------------------------------------------------=== 9*7c3d14c8STreehugger Robot * 10*7c3d14c8STreehugger Robot * This file implements count leading zeros for 64bit arguments. 11*7c3d14c8STreehugger Robot * 12*7c3d14c8STreehugger Robot * ===----------------------------------------------------------------------=== 13*7c3d14c8STreehugger Robot */ 14*7c3d14c8STreehugger Robot#include "../assembly.h" 15*7c3d14c8STreehugger Robot 16*7c3d14c8STreehugger Robot .syntax unified 17*7c3d14c8STreehugger Robot .text 18*7c3d14c8STreehugger Robot#if __ARM_ARCH_ISA_THUMB == 2 19*7c3d14c8STreehugger Robot .thumb 20*7c3d14c8STreehugger Robot#endif 21*7c3d14c8STreehugger Robot 22*7c3d14c8STreehugger Robot 23*7c3d14c8STreehugger Robot .p2align 2 24*7c3d14c8STreehugger Robot#if __ARM_ARCH_ISA_THUMB == 2 25*7c3d14c8STreehugger RobotDEFINE_COMPILERRT_THUMB_FUNCTION(__clzdi2) 26*7c3d14c8STreehugger Robot#else 27*7c3d14c8STreehugger RobotDEFINE_COMPILERRT_FUNCTION(__clzdi2) 28*7c3d14c8STreehugger Robot#endif 29*7c3d14c8STreehugger Robot#ifdef __ARM_FEATURE_CLZ 30*7c3d14c8STreehugger Robot#ifdef __ARMEB__ 31*7c3d14c8STreehugger Robot cmp r0, 0 32*7c3d14c8STreehugger Robot itee ne 33*7c3d14c8STreehugger Robot clzne r0, r0 34*7c3d14c8STreehugger Robot clzeq r0, r1 35*7c3d14c8STreehugger Robot addeq r0, r0, 32 36*7c3d14c8STreehugger Robot#else 37*7c3d14c8STreehugger Robot cmp r1, 0 38*7c3d14c8STreehugger Robot itee ne 39*7c3d14c8STreehugger Robot clzne r0, r1 40*7c3d14c8STreehugger Robot clzeq r0, r0 41*7c3d14c8STreehugger Robot addeq r0, r0, 32 42*7c3d14c8STreehugger Robot#endif 43*7c3d14c8STreehugger Robot JMP(lr) 44*7c3d14c8STreehugger Robot#else 45*7c3d14c8STreehugger Robot /* Assumption: n != 0 */ 46*7c3d14c8STreehugger Robot 47*7c3d14c8STreehugger Robot /* 48*7c3d14c8STreehugger Robot * r0: n 49*7c3d14c8STreehugger Robot * r1: upper half of n, overwritten after check 50*7c3d14c8STreehugger Robot * r1: count of leading zeros in n + 1 51*7c3d14c8STreehugger Robot * r2: scratch register for shifted r0 52*7c3d14c8STreehugger Robot */ 53*7c3d14c8STreehugger Robot#ifdef __ARMEB__ 54*7c3d14c8STreehugger Robot cmp r0, 0 55*7c3d14c8STreehugger Robot moveq r0, r1 56*7c3d14c8STreehugger Robot#else 57*7c3d14c8STreehugger Robot cmp r1, 0 58*7c3d14c8STreehugger Robot movne r0, r1 59*7c3d14c8STreehugger Robot#endif 60*7c3d14c8STreehugger Robot movne r1, 1 61*7c3d14c8STreehugger Robot moveq r1, 33 62*7c3d14c8STreehugger Robot 63*7c3d14c8STreehugger Robot /* 64*7c3d14c8STreehugger Robot * Basic block: 65*7c3d14c8STreehugger Robot * if ((r0 >> SHIFT) == 0) 66*7c3d14c8STreehugger Robot * r1 += SHIFT; 67*7c3d14c8STreehugger Robot * else 68*7c3d14c8STreehugger Robot * r0 >>= SHIFT; 69*7c3d14c8STreehugger Robot * for descending powers of two as SHIFT. 70*7c3d14c8STreehugger Robot */ 71*7c3d14c8STreehugger Robot#define BLOCK(shift) \ 72*7c3d14c8STreehugger Robot lsrs r2, r0, shift; \ 73*7c3d14c8STreehugger Robot movne r0, r2; \ 74*7c3d14c8STreehugger Robot addeq r1, shift \ 75*7c3d14c8STreehugger Robot 76*7c3d14c8STreehugger Robot BLOCK(16) 77*7c3d14c8STreehugger Robot BLOCK(8) 78*7c3d14c8STreehugger Robot BLOCK(4) 79*7c3d14c8STreehugger Robot BLOCK(2) 80*7c3d14c8STreehugger Robot 81*7c3d14c8STreehugger Robot /* 82*7c3d14c8STreehugger Robot * The basic block invariants at this point are (r0 >> 2) == 0 and 83*7c3d14c8STreehugger Robot * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. 84*7c3d14c8STreehugger Robot * 85*7c3d14c8STreehugger Robot * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) 86*7c3d14c8STreehugger Robot * ---+----------------+----------------+------------+-------------- 87*7c3d14c8STreehugger Robot * 1 | 1 | 0 | 0 | 1 88*7c3d14c8STreehugger Robot * 2 | 0 | 1 | -1 | 0 89*7c3d14c8STreehugger Robot * 3 | 0 | 1 | -1 | 0 90*7c3d14c8STreehugger Robot * 91*7c3d14c8STreehugger Robot * The r1's initial value of 1 compensates for the 1 here. 92*7c3d14c8STreehugger Robot */ 93*7c3d14c8STreehugger Robot sub r0, r1, r0, lsr #1 94*7c3d14c8STreehugger Robot 95*7c3d14c8STreehugger Robot JMP(lr) 96*7c3d14c8STreehugger Robot#endif // __ARM_FEATURE_CLZ 97*7c3d14c8STreehugger RobotEND_COMPILERRT_FUNCTION(__clzdi2) 98*7c3d14c8STreehugger Robot 99*7c3d14c8STreehugger RobotNO_EXEC_STACK_DIRECTIVE 100*7c3d14c8STreehugger Robot 101