1*3cab2bb3Spatrick//===-- clzsi2.c - Implement __clzsi2 -------------------------------------===// 2*3cab2bb3Spatrick// 3*3cab2bb3Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*3cab2bb3Spatrick// See https://llvm.org/LICENSE.txt for license information. 5*3cab2bb3Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*3cab2bb3Spatrick// 7*3cab2bb3Spatrick//===----------------------------------------------------------------------===// 8*3cab2bb3Spatrick// 9*3cab2bb3Spatrick// This file implements count leading zeros for 32bit arguments. 10*3cab2bb3Spatrick// 11*3cab2bb3Spatrick//===----------------------------------------------------------------------===// 12*3cab2bb3Spatrick 13*3cab2bb3Spatrick#include "../assembly.h" 14*3cab2bb3Spatrick 15*3cab2bb3Spatrick .syntax unified 16*3cab2bb3Spatrick .text 17*3cab2bb3Spatrick DEFINE_CODE_STATE 18*3cab2bb3Spatrick 19*3cab2bb3Spatrick .p2align 2 20*3cab2bb3SpatrickDEFINE_COMPILERRT_FUNCTION(__clzsi2) 21*3cab2bb3Spatrick#ifdef __ARM_FEATURE_CLZ 22*3cab2bb3Spatrick clz r0, r0 23*3cab2bb3Spatrick JMP(lr) 24*3cab2bb3Spatrick#else 25*3cab2bb3Spatrick // Assumption: n != 0 26*3cab2bb3Spatrick 27*3cab2bb3Spatrick // r0: n 28*3cab2bb3Spatrick // r1: count of leading zeros in n + 1 29*3cab2bb3Spatrick // r2: scratch register for shifted r0 30*3cab2bb3Spatrick mov r1, 1 31*3cab2bb3Spatrick 32*3cab2bb3Spatrick // Basic block: 33*3cab2bb3Spatrick // if ((r0 >> SHIFT) == 0) 34*3cab2bb3Spatrick // r1 += SHIFT; 35*3cab2bb3Spatrick // else 36*3cab2bb3Spatrick // r0 >>= SHIFT; 37*3cab2bb3Spatrick // for descending powers of two as SHIFT. 38*3cab2bb3Spatrick 39*3cab2bb3Spatrick#define BLOCK(shift) \ 40*3cab2bb3Spatrick lsrs r2, r0, shift; \ 41*3cab2bb3Spatrick movne r0, r2; \ 42*3cab2bb3Spatrick addeq r1, shift \ 43*3cab2bb3Spatrick 44*3cab2bb3Spatrick BLOCK(16) 45*3cab2bb3Spatrick BLOCK(8) 46*3cab2bb3Spatrick BLOCK(4) 47*3cab2bb3Spatrick BLOCK(2) 48*3cab2bb3Spatrick 49*3cab2bb3Spatrick // The basic block invariants at this point are (r0 >> 2) == 0 and 50*3cab2bb3Spatrick // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. 51*3cab2bb3Spatrick // 52*3cab2bb3Spatrick // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) 53*3cab2bb3Spatrick // ---+----------------+----------------+------------+-------------- 54*3cab2bb3Spatrick // 1 | 1 | 0 | 0 | 1 55*3cab2bb3Spatrick // 2 | 0 | 1 | -1 | 0 56*3cab2bb3Spatrick // 3 | 0 | 1 | -1 | 0 57*3cab2bb3Spatrick // 58*3cab2bb3Spatrick // The r1's initial value of 1 compensates for the 1 here. 59*3cab2bb3Spatrick sub r0, r1, r0, lsr #1 60*3cab2bb3Spatrick 61*3cab2bb3Spatrick JMP(lr) 62*3cab2bb3Spatrick#endif // __ARM_FEATURE_CLZ 63*3cab2bb3SpatrickEND_COMPILERRT_FUNCTION(__clzsi2) 64*3cab2bb3Spatrick 65*3cab2bb3SpatrickNO_EXEC_STACK_DIRECTIVE 66*3cab2bb3Spatrick 67