1*7c3d14c8STreehugger Robot/* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------=== 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 32bit 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 .p2align 2 23*7c3d14c8STreehugger Robot#if __ARM_ARCH_ISA_THUMB == 2 24*7c3d14c8STreehugger RobotDEFINE_COMPILERRT_THUMB_FUNCTION(__clzsi2) 25*7c3d14c8STreehugger Robot#else 26*7c3d14c8STreehugger RobotDEFINE_COMPILERRT_FUNCTION(__clzsi2) 27*7c3d14c8STreehugger Robot#endif 28*7c3d14c8STreehugger Robot#ifdef __ARM_FEATURE_CLZ 29*7c3d14c8STreehugger Robot clz r0, r0 30*7c3d14c8STreehugger Robot JMP(lr) 31*7c3d14c8STreehugger Robot#else 32*7c3d14c8STreehugger Robot /* Assumption: n != 0 */ 33*7c3d14c8STreehugger Robot 34*7c3d14c8STreehugger Robot /* 35*7c3d14c8STreehugger Robot * r0: n 36*7c3d14c8STreehugger Robot * r1: count of leading zeros in n + 1 37*7c3d14c8STreehugger Robot * r2: scratch register for shifted r0 38*7c3d14c8STreehugger Robot */ 39*7c3d14c8STreehugger Robot mov r1, 1 40*7c3d14c8STreehugger Robot 41*7c3d14c8STreehugger Robot /* 42*7c3d14c8STreehugger Robot * Basic block: 43*7c3d14c8STreehugger Robot * if ((r0 >> SHIFT) == 0) 44*7c3d14c8STreehugger Robot * r1 += SHIFT; 45*7c3d14c8STreehugger Robot * else 46*7c3d14c8STreehugger Robot * r0 >>= SHIFT; 47*7c3d14c8STreehugger Robot * for descending powers of two as SHIFT. 48*7c3d14c8STreehugger Robot */ 49*7c3d14c8STreehugger Robot 50*7c3d14c8STreehugger Robot#define BLOCK(shift) \ 51*7c3d14c8STreehugger Robot lsrs r2, r0, shift; \ 52*7c3d14c8STreehugger Robot movne r0, r2; \ 53*7c3d14c8STreehugger Robot addeq r1, shift \ 54*7c3d14c8STreehugger Robot 55*7c3d14c8STreehugger Robot BLOCK(16) 56*7c3d14c8STreehugger Robot BLOCK(8) 57*7c3d14c8STreehugger Robot BLOCK(4) 58*7c3d14c8STreehugger Robot BLOCK(2) 59*7c3d14c8STreehugger Robot 60*7c3d14c8STreehugger Robot /* 61*7c3d14c8STreehugger Robot * The basic block invariants at this point are (r0 >> 2) == 0 and 62*7c3d14c8STreehugger Robot * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. 63*7c3d14c8STreehugger Robot * 64*7c3d14c8STreehugger Robot * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) 65*7c3d14c8STreehugger Robot * ---+----------------+----------------+------------+-------------- 66*7c3d14c8STreehugger Robot * 1 | 1 | 0 | 0 | 1 67*7c3d14c8STreehugger Robot * 2 | 0 | 1 | -1 | 0 68*7c3d14c8STreehugger Robot * 3 | 0 | 1 | -1 | 0 69*7c3d14c8STreehugger Robot * 70*7c3d14c8STreehugger Robot * The r1's initial value of 1 compensates for the 1 here. 71*7c3d14c8STreehugger Robot */ 72*7c3d14c8STreehugger Robot sub r0, r1, r0, lsr #1 73*7c3d14c8STreehugger Robot 74*7c3d14c8STreehugger Robot JMP(lr) 75*7c3d14c8STreehugger Robot#endif // __ARM_FEATURE_CLZ 76*7c3d14c8STreehugger RobotEND_COMPILERRT_FUNCTION(__clzsi2) 77*7c3d14c8STreehugger Robot 78*7c3d14c8STreehugger RobotNO_EXEC_STACK_DIRECTIVE 79*7c3d14c8STreehugger Robot 80