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