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