Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/compiler-rt/lib/builtins/arm/udivmodsi4.S
4396 views
1
/*===-- udivmodsi4.S - 32-bit unsigned integer divide and modulus ---------===//
2
*
3
* The LLVM Compiler Infrastructure
4
*
5
* This file is dual licensed under the MIT and the University of Illinois Open
6
* Source Licenses. See LICENSE.TXT for details.
7
*
8
*===----------------------------------------------------------------------===//
9
*
10
* This file implements the __udivmodsi4 (32-bit unsigned integer divide and
11
* modulus) function for the ARM 32-bit architecture.
12
*
13
*===----------------------------------------------------------------------===*/
14
15
#include "../assembly.h"
16
17
.syntax unified
18
.text
19
DEFINE_CODE_STATE
20
21
@ unsigned int __udivmodsi4(unsigned int divident, unsigned int divisor,
22
@ unsigned int *remainder)
23
@ Calculate the quotient and remainder of the (unsigned) division. The return
24
@ value is the quotient, the remainder is placed in the variable.
25
26
.p2align 2
27
DEFINE_COMPILERRT_FUNCTION(__udivmodsi4)
28
#if __ARM_ARCH_EXT_IDIV__
29
tst r1, r1
30
beq LOCAL_LABEL(divby0)
31
mov r3, r0
32
udiv r0, r3, r1
33
mls r1, r0, r1, r3
34
str r1, [r2]
35
bx lr
36
#else
37
cmp r1, #1
38
bcc LOCAL_LABEL(divby0)
39
beq LOCAL_LABEL(divby1)
40
cmp r0, r1
41
bcc LOCAL_LABEL(quotient0)
42
/*
43
* Implement division using binary long division algorithm.
44
*
45
* r0 is the numerator, r1 the denominator.
46
*
47
* The code before JMP computes the correct shift I, so that
48
* r0 and (r1 << I) have the highest bit set in the same position.
49
* At the time of JMP, ip := .Ldiv0block - 12 * I.
50
* This depends on the fixed instruction size of block.
51
* For ARM mode, this is 12 Bytes, for THUMB mode 14 Bytes.
52
*
53
* block(shift) implements the test-and-update-quotient core.
54
* It assumes (r0 << shift) can be computed without overflow and
55
* that (r0 << shift) < 2 * r1. The quotient is stored in r3.
56
*/
57
58
# ifdef __ARM_FEATURE_CLZ
59
clz ip, r0
60
clz r3, r1
61
/* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */
62
sub r3, r3, ip
63
# if defined(USE_THUMB_2)
64
adr ip, LOCAL_LABEL(div0block) + 1
65
sub ip, ip, r3, lsl #1
66
# else
67
adr ip, LOCAL_LABEL(div0block)
68
# endif
69
sub ip, ip, r3, lsl #2
70
sub ip, ip, r3, lsl #3
71
mov r3, #0
72
bx ip
73
# else
74
# if defined(USE_THUMB_2)
75
# error THUMB mode requires CLZ or UDIV
76
# endif
77
str r4, [sp, #-8]!
78
79
mov r4, r0
80
adr ip, LOCAL_LABEL(div0block)
81
82
lsr r3, r4, #16
83
cmp r3, r1
84
movhs r4, r3
85
subhs ip, ip, #(16 * 12)
86
87
lsr r3, r4, #8
88
cmp r3, r1
89
movhs r4, r3
90
subhs ip, ip, #(8 * 12)
91
92
lsr r3, r4, #4
93
cmp r3, r1
94
movhs r4, r3
95
subhs ip, #(4 * 12)
96
97
lsr r3, r4, #2
98
cmp r3, r1
99
movhs r4, r3
100
subhs ip, ip, #(2 * 12)
101
102
/* Last block, no need to update r3 or r4. */
103
cmp r1, r4, lsr #1
104
subls ip, ip, #(1 * 12)
105
106
ldr r4, [sp], #8 /* restore r4, we are done with it. */
107
mov r3, #0
108
109
JMP(ip)
110
# endif
111
112
#define IMM #
113
114
#define block(shift) \
115
cmp r0, r1, lsl IMM shift; \
116
ITT(hs); \
117
WIDE(addhs) r3, r3, IMM (1 << shift); \
118
WIDE(subhs) r0, r0, r1, lsl IMM shift
119
120
block(31)
121
block(30)
122
block(29)
123
block(28)
124
block(27)
125
block(26)
126
block(25)
127
block(24)
128
block(23)
129
block(22)
130
block(21)
131
block(20)
132
block(19)
133
block(18)
134
block(17)
135
block(16)
136
block(15)
137
block(14)
138
block(13)
139
block(12)
140
block(11)
141
block(10)
142
block(9)
143
block(8)
144
block(7)
145
block(6)
146
block(5)
147
block(4)
148
block(3)
149
block(2)
150
block(1)
151
LOCAL_LABEL(div0block):
152
block(0)
153
154
str r0, [r2]
155
mov r0, r3
156
JMP(lr)
157
158
LOCAL_LABEL(quotient0):
159
str r0, [r2]
160
mov r0, #0
161
JMP(lr)
162
163
LOCAL_LABEL(divby1):
164
mov r3, #0
165
str r3, [r2]
166
JMP(lr)
167
#endif /* __ARM_ARCH_EXT_IDIV__ */
168
169
LOCAL_LABEL(divby0):
170
mov r0, #0
171
#ifdef __ARM_EABI__
172
b __aeabi_idiv0
173
#else
174
JMP(lr)
175
#endif
176
177
END_COMPILERRT_FUNCTION(__udivmodsi4)
178
179
NO_EXEC_STACK_DIRECTIVE
180
181