1156cd587Sjoerg/* ===-- clzdi2.c - Implement __clzdi2 -------------------------------------=== 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 64bit 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 22190e92d8Sjoerg 2361f2f256Sjoerg .p2align 2 24*ef84fd3bSjoerg#if __ARM_ARCH_ISA_THUMB == 2 25*ef84fd3bSjoergDEFINE_COMPILERRT_THUMB_FUNCTION(__clzdi2) 26*ef84fd3bSjoerg#else 27156cd587SjoergDEFINE_COMPILERRT_FUNCTION(__clzdi2) 28*ef84fd3bSjoerg#endif 29156cd587Sjoerg#ifdef __ARM_FEATURE_CLZ 30156cd587Sjoerg#ifdef __ARMEB__ 31156cd587Sjoerg cmp r0, 0 32156cd587Sjoerg itee ne 33156cd587Sjoerg clzne r0, r0 34156cd587Sjoerg clzeq r0, r1 35156cd587Sjoerg addeq r0, r0, 32 36156cd587Sjoerg#else 37156cd587Sjoerg cmp r1, 0 38156cd587Sjoerg itee ne 39156cd587Sjoerg clzne r0, r1 40156cd587Sjoerg clzeq r0, r0 41156cd587Sjoerg addeq r0, r0, 32 42156cd587Sjoerg#endif 43156cd587Sjoerg JMP(lr) 44156cd587Sjoerg#else 45156cd587Sjoerg /* Assumption: n != 0 */ 46156cd587Sjoerg 47156cd587Sjoerg /* 48156cd587Sjoerg * r0: n 49156cd587Sjoerg * r1: upper half of n, overwritten after check 50156cd587Sjoerg * r1: count of leading zeros in n + 1 51156cd587Sjoerg * r2: scratch register for shifted r0 52156cd587Sjoerg */ 53156cd587Sjoerg#ifdef __ARMEB__ 54156cd587Sjoerg cmp r0, 0 55156cd587Sjoerg moveq r0, r1 56156cd587Sjoerg#else 57156cd587Sjoerg cmp r1, 0 58156cd587Sjoerg movne r0, r1 59156cd587Sjoerg#endif 60156cd587Sjoerg movne r1, 1 61156cd587Sjoerg moveq r1, 33 62156cd587Sjoerg 63156cd587Sjoerg /* 64156cd587Sjoerg * Basic block: 65156cd587Sjoerg * if ((r0 >> SHIFT) == 0) 66156cd587Sjoerg * r1 += SHIFT; 67156cd587Sjoerg * else 68156cd587Sjoerg * r0 >>= SHIFT; 69156cd587Sjoerg * for descending powers of two as SHIFT. 70156cd587Sjoerg */ 71156cd587Sjoerg#define BLOCK(shift) \ 72156cd587Sjoerg lsrs r2, r0, shift; \ 73156cd587Sjoerg movne r0, r2; \ 74156cd587Sjoerg addeq r1, shift \ 75156cd587Sjoerg 76156cd587Sjoerg BLOCK(16) 77156cd587Sjoerg BLOCK(8) 78156cd587Sjoerg BLOCK(4) 79156cd587Sjoerg BLOCK(2) 80156cd587Sjoerg 81156cd587Sjoerg /* 82156cd587Sjoerg * The basic block invariants at this point are (r0 >> 2) == 0 and 83156cd587Sjoerg * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. 84156cd587Sjoerg * 85156cd587Sjoerg * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) 86156cd587Sjoerg * ---+----------------+----------------+------------+-------------- 87156cd587Sjoerg * 1 | 1 | 0 | 0 | 1 88156cd587Sjoerg * 2 | 0 | 1 | -1 | 0 89156cd587Sjoerg * 3 | 0 | 1 | -1 | 0 90156cd587Sjoerg * 91156cd587Sjoerg * The r1's initial value of 1 compensates for the 1 here. 92156cd587Sjoerg */ 93156cd587Sjoerg sub r0, r1, r0, lsr #1 94156cd587Sjoerg 95156cd587Sjoerg JMP(lr) 96156cd587Sjoerg#endif // __ARM_FEATURE_CLZ 97156cd587SjoergEND_COMPILERRT_FUNCTION(__clzdi2) 98