1156cd587Sjoerg/* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------=== 2156cd587Sjoerg * 3156cd587Sjoerg * The LLVM Compiler Infrastructure 4156cd587Sjoerg * 5156cd587Sjoerg * This file is dual licensed under the MIT and the University of Illinois Open 6156cd587Sjoerg * Source Licenses. See LICENSE.TXT for details. 7156cd587Sjoerg * 8156cd587Sjoerg * ===----------------------------------------------------------------------=== 9156cd587Sjoerg * 10156cd587Sjoerg * This file implements count leading zeros for 32bit arguments. 11156cd587Sjoerg * 12156cd587Sjoerg * ===----------------------------------------------------------------------=== 13156cd587Sjoerg */ 14156cd587Sjoerg#include "../assembly.h" 15156cd587Sjoerg 16156cd587Sjoerg .syntax unified 17156cd587Sjoerg .text 18190e92d8Sjoerg#if __ARM_ARCH_ISA_THUMB == 2 19190e92d8Sjoerg .thumb 20190e92d8Sjoerg#endif 21190e92d8Sjoerg 2261f2f256Sjoerg .p2align 2 23*ef84fd3bSjoerg#if __ARM_ARCH_ISA_THUMB == 2 24*ef84fd3bSjoergDEFINE_COMPILERRT_THUMB_FUNCTION(__clzsi2) 25*ef84fd3bSjoerg#else 26156cd587SjoergDEFINE_COMPILERRT_FUNCTION(__clzsi2) 27*ef84fd3bSjoerg#endif 28156cd587Sjoerg#ifdef __ARM_FEATURE_CLZ 29156cd587Sjoerg clz r0, r0 30156cd587Sjoerg JMP(lr) 31156cd587Sjoerg#else 32156cd587Sjoerg /* Assumption: n != 0 */ 33156cd587Sjoerg 34156cd587Sjoerg /* 35156cd587Sjoerg * r0: n 36156cd587Sjoerg * r1: count of leading zeros in n + 1 37156cd587Sjoerg * r2: scratch register for shifted r0 38156cd587Sjoerg */ 39156cd587Sjoerg mov r1, 1 40156cd587Sjoerg 41156cd587Sjoerg /* 42156cd587Sjoerg * Basic block: 43156cd587Sjoerg * if ((r0 >> SHIFT) == 0) 44156cd587Sjoerg * r1 += SHIFT; 45156cd587Sjoerg * else 46156cd587Sjoerg * r0 >>= SHIFT; 47156cd587Sjoerg * for descending powers of two as SHIFT. 48156cd587Sjoerg */ 49156cd587Sjoerg 50156cd587Sjoerg#define BLOCK(shift) \ 51156cd587Sjoerg lsrs r2, r0, shift; \ 52156cd587Sjoerg movne r0, r2; \ 53156cd587Sjoerg addeq r1, shift \ 54156cd587Sjoerg 55156cd587Sjoerg BLOCK(16) 56156cd587Sjoerg BLOCK(8) 57156cd587Sjoerg BLOCK(4) 58156cd587Sjoerg BLOCK(2) 59156cd587Sjoerg 60156cd587Sjoerg /* 61156cd587Sjoerg * The basic block invariants at this point are (r0 >> 2) == 0 and 62156cd587Sjoerg * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. 63156cd587Sjoerg * 64156cd587Sjoerg * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) 65156cd587Sjoerg * ---+----------------+----------------+------------+-------------- 66156cd587Sjoerg * 1 | 1 | 0 | 0 | 1 67156cd587Sjoerg * 2 | 0 | 1 | -1 | 0 68156cd587Sjoerg * 3 | 0 | 1 | -1 | 0 69156cd587Sjoerg * 70156cd587Sjoerg * The r1's initial value of 1 compensates for the 1 here. 71156cd587Sjoerg */ 72156cd587Sjoerg sub r0, r1, r0, lsr #1 73156cd587Sjoerg 74156cd587Sjoerg JMP(lr) 75156cd587Sjoerg#endif // __ARM_FEATURE_CLZ 76156cd587SjoergEND_COMPILERRT_FUNCTION(__clzsi2) 77