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/clzdi2.S
35292 views
1
//===-- clzdi2.c - Implement __clzdi2 -------------------------------------===//
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 64bit 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(__clzdi2)
21
#ifdef __ARM_FEATURE_CLZ
22
#ifdef __ARMEB__
23
cmp r0, 0
24
itee ne
25
clzne r0, r0
26
clzeq r0, r1
27
addeq r0, r0, 32
28
#else
29
cmp r1, 0
30
itee ne
31
clzne r0, r1
32
clzeq r0, r0
33
addeq r0, r0, 32
34
#endif
35
JMP(lr)
36
#else
37
// Assumption: n != 0
38
39
// r0: n
40
// r1: upper half of n, overwritten after check
41
// r1: count of leading zeros in n + 1
42
// r2: scratch register for shifted r0
43
#ifdef __ARMEB__
44
cmp r0, 0
45
moveq r0, r1
46
#else
47
cmp r1, 0
48
movne r0, r1
49
#endif
50
movne r1, 1
51
moveq r1, 33
52
53
// Basic block:
54
// if ((r0 >> SHIFT) == 0)
55
// r1 += SHIFT;
56
// else
57
// r0 >>= SHIFT;
58
// for descending powers of two as SHIFT.
59
#define BLOCK(shift) \
60
lsrs r2, r0, shift; \
61
movne r0, r2; \
62
addeq r1, shift \
63
64
BLOCK(16)
65
BLOCK(8)
66
BLOCK(4)
67
BLOCK(2)
68
69
// The basic block invariants at this point are (r0 >> 2) == 0 and
70
// r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1.
71
//
72
// r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)
73
// ---+----------------+----------------+------------+--------------
74
// 1 | 1 | 0 | 0 | 1
75
// 2 | 0 | 1 | -1 | 0
76
// 3 | 0 | 1 | -1 | 0
77
//
78
// The r1's initial value of 1 compensates for the 1 here.
79
sub r0, r1, r0, lsr #1
80
81
JMP(lr)
82
#endif // __ARM_FEATURE_CLZ
83
END_COMPILERRT_FUNCTION(__clzdi2)
84
85
NO_EXEC_STACK_DIRECTIVE
86
87
88