1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <linux/linkage.h>
37 #include <asm/assembler.h>
38 #include <asm/unwind.h>
39
40 .macro ARM_DIV_BODY dividend, divisor, result, curbit
41
42 #if __LINUX_ARM_ARCH__ >= 5
43
44 clz \curbit, \divisor
45 clz \result, \dividend
46 sub \result, \curbit, \result
47 mov \curbit, #1
48 mov \divisor, \divisor, lsl \result
49 mov \curbit, \curbit, lsl \result
50 mov \result, #0
51
52 #else
53
54 @ Initially shift the divisor left 3 bits if possible,
55 @ set curbit accordingly. This allows for curbit to be located
56 @ at the left end of each 4 bit nibbles in the division loop
57 @ to save one loop in most cases.
58 tst \divisor, #0xe0000000
59 moveq \divisor, \divisor, lsl #3
60 moveq \curbit, #8
61 movne \curbit, #1
62
63 @ Unless the divisor is very big, shift it up in multiples of
64 @ four bits, since this is the amount of unwinding in the main
65 @ division loop. Continue shifting until the divisor is
66 @ larger than the dividend.
67 1: cmp \divisor, #0x10000000
68 cmplo \divisor, \dividend
69 movlo \divisor, \divisor, lsl #4
70 movlo \curbit, \curbit, lsl #4
71 blo 1b
72
73 @ For very big divisors, we must shift it a bit at a time, or
74 @ we will be in danger of overflowing.
75 1: cmp \divisor, #0x80000000
76 cmplo \divisor, \dividend
77 movlo \divisor, \divisor, lsl #1
78 movlo \curbit, \curbit, lsl #1
79 blo 1b
80
81 mov \result, #0
82
83 #endif
84
85 @ Division loop
86 1: cmp \dividend, \divisor
87 subhs \dividend, \dividend, \divisor
88 orrhs \result, \result, \curbit
89 cmp \dividend, \divisor, lsr #1
90 subhs \dividend, \dividend, \divisor, lsr #1
91 orrhs \result, \result, \curbit, lsr #1
92 cmp \dividend, \divisor, lsr #2
93 subhs \dividend, \dividend, \divisor, lsr #2
94 orrhs \result, \result, \curbit, lsr #2
95 cmp \dividend, \divisor, lsr #3
96 subhs \dividend, \dividend, \divisor, lsr #3
97 orrhs \result, \result, \curbit, lsr #3
98 cmp \dividend, #0 @ Early termination?
99 movsne \curbit, \curbit, lsr #4 @ No, any more bits to do?
100 movne \divisor, \divisor, lsr #4
101 bne 1b
102
103 .endm
104
105
106 .macro ARM_DIV2_ORDER divisor, order
107
108 #if __LINUX_ARM_ARCH__ >= 5
109
110 clz \order, \divisor
111 rsb \order, \order, #31
112
113 #else
114
115 cmp \divisor, #(1 << 16)
116 movhs \divisor, \divisor, lsr #16
117 movhs \order, #16
118 movlo \order, #0
119
120 cmp \divisor, #(1 << 8)
121 movhs \divisor, \divisor, lsr #8
122 addhs \order, \order, #8
123
124 cmp \divisor, #(1 << 4)
125 movhs \divisor, \divisor, lsr #4
126 addhs \order, \order, #4
127
128 cmp \divisor, #(1 << 2)
129 addhi \order, \order, #3
130 addls \order, \order, \divisor, lsr #1
131
132 #endif
133
134 .endm
135
136
137 .macro ARM_MOD_BODY dividend, divisor, order, spare
138
139 #if __LINUX_ARM_ARCH__ >= 5
140
141 clz \order, \divisor
142 clz \spare, \dividend
143 sub \order, \order, \spare
144 mov \divisor, \divisor, lsl \order
145
146 #else
147
148 mov \order, #0
149
150 @ Unless the divisor is very big, shift it up in multiples of
151 @ four bits, since this is the amount of unwinding in the main
152 @ division loop. Continue shifting until the divisor is
153 @ larger than the dividend.
154 1: cmp \divisor, #0x10000000
155 cmplo \divisor, \dividend
156 movlo \divisor, \divisor, lsl #4
157 addlo \order, \order, #4
158 blo 1b
159
160 @ For very big divisors, we must shift it a bit at a time, or
161 @ we will be in danger of overflowing.
162 1: cmp \divisor, #0x80000000
163 cmplo \divisor, \dividend
164 movlo \divisor, \divisor, lsl #1
165 addlo \order, \order, #1
166 blo 1b
167
168 #endif
169
170 @ Perform all needed subtractions to keep only the reminder.
171 @ Do comparisons in batch of 4 first.
172 subs \order, \order, #3 @ yes, 3 is intended here
173 blt 2f
174
175 1: cmp \dividend, \divisor
176 subhs \dividend, \dividend, \divisor
177 cmp \dividend, \divisor, lsr #1
178 subhs \dividend, \dividend, \divisor, lsr #1
179 cmp \dividend, \divisor, lsr #2
180 subhs \dividend, \dividend, \divisor, lsr #2
181 cmp \dividend, \divisor, lsr #3
182 subhs \dividend, \dividend, \divisor, lsr #3
183 cmp \dividend, #1
184 mov \divisor, \divisor, lsr #4
185 subsge \order, \order, #4
186 bge 1b
187
188 tst \order, #3
189 teqne \dividend, #0
190 beq 5f
191
192 @ Either 1, 2 or 3 comparison/subtractions are left.
193 2: cmn \order, #2
194 blt 4f
195 beq 3f
196 cmp \dividend, \divisor
197 subhs \dividend, \dividend, \divisor
198 mov \divisor, \divisor, lsr #1
199 3: cmp \dividend, \divisor
200 subhs \dividend, \dividend, \divisor
201 mov \divisor, \divisor, lsr #1
202 4: cmp \dividend, \divisor
203 subhs \dividend, \dividend, \divisor
204 5:
205 .endm
206
207
208 #ifdef CONFIG_ARM_PATCH_IDIV
209 .align 3
210 #endif
211
212 ENTRY(__udivsi3)
213 ENTRY(__aeabi_uidiv)
214 UNWIND(.fnstart)
215
216 subs r2, r1, #1
217 reteq lr
218 bcc Ldiv0
219 cmp r0, r1
220 bls 11f
221 tst r1, r2
222 beq 12f
223
224 ARM_DIV_BODY r0, r1, r2, r3
225
226 mov r0, r2
227 ret lr
228
229 11: moveq r0, #1
230 movne r0, #0
231 ret lr
232
233 12: ARM_DIV2_ORDER r1, r2
234
235 mov r0, r0, lsr r2
236 ret lr
237
238 UNWIND(.fnend)
239 ENDPROC(__udivsi3)
240 ENDPROC(__aeabi_uidiv)
241
242 ENTRY(__umodsi3)
243 UNWIND(.fnstart)
244
245 subs r2, r1, #1 @ compare divisor with 1
246 bcc Ldiv0
247 cmpne r0, r1 @ compare dividend with divisor
248 moveq r0, #0
249 tsthi r1, r2 @ see if divisor is power of 2
250 andeq r0, r0, r2
251 retls lr
252
253 ARM_MOD_BODY r0, r1, r2, r3
254
255 ret lr
256
257 UNWIND(.fnend)
258 ENDPROC(__umodsi3)
259
260 #ifdef CONFIG_ARM_PATCH_IDIV
261 .align 3
262 #endif
263
264 ENTRY(__divsi3)
265 ENTRY(__aeabi_idiv)
266 UNWIND(.fnstart)
267
268 cmp r1, #0
269 eor ip, r0, r1 @ save the sign of the result.
270 beq Ldiv0
271 rsbmi r1, r1, #0 @ loops below use unsigned.
272 subs r2, r1, #1 @ division by 1 or -1 ?
273 beq 10f
274 movs r3, r0
275 rsbmi r3, r0, #0 @ positive dividend value
276 cmp r3, r1
277 bls 11f
278 tst r1, r2 @ divisor is power of 2 ?
279 beq 12f
280
281 ARM_DIV_BODY r3, r1, r0, r2
282
283 cmp ip, #0
284 rsbmi r0, r0, #0
285 ret lr
286
287 10: teq ip, r0 @ same sign ?
288 rsbmi r0, r0, #0
289 ret lr
290
291 11: movlo r0, #0
292 moveq r0, ip, asr #31
293 orreq r0, r0, #1
294 ret lr
295
296 12: ARM_DIV2_ORDER r1, r2
297
298 cmp ip, #0
299 mov r0, r3, lsr r2
300 rsbmi r0, r0, #0
301 ret lr
302
303 UNWIND(.fnend)
304 ENDPROC(__divsi3)
305 ENDPROC(__aeabi_idiv)
306
307 ENTRY(__modsi3)
308 UNWIND(.fnstart)
309
310 cmp r1, #0
311 beq Ldiv0
312 rsbmi r1, r1, #0 @ loops below use unsigned.
313 movs ip, r0 @ preserve sign of dividend
314 rsbmi r0, r0, #0 @ if negative make positive
315 subs r2, r1, #1 @ compare divisor with 1
316 cmpne r0, r1 @ compare dividend with divisor
317 moveq r0, #0
318 tsthi r1, r2 @ see if divisor is power of 2
319 andeq r0, r0, r2
320 bls 10f
321
322 ARM_MOD_BODY r0, r1, r2, r3
323
324 10: cmp ip, #0
325 rsbmi r0, r0, #0
326 ret lr
327
328 UNWIND(.fnend)
329 ENDPROC(__modsi3)
330
331 #ifdef CONFIG_AEABI
332
333 ENTRY(__aeabi_uidivmod)
334 UNWIND(.fnstart)
335 UNWIND(.save {r0, r1, ip, lr} )
336
337 stmfd sp!, {r0, r1, ip, lr}
338 bl __aeabi_uidiv
339 ldmfd sp!, {r1, r2, ip, lr}
340 mul r3, r0, r2
341 sub r1, r1, r3
342 ret lr
343
344 UNWIND(.fnend)
345 ENDPROC(__aeabi_uidivmod)
346
347 ENTRY(__aeabi_idivmod)
348 UNWIND(.fnstart)
349 UNWIND(.save {r0, r1, ip, lr} )
350 stmfd sp!, {r0, r1, ip, lr}
351 bl __aeabi_idiv
352 ldmfd sp!, {r1, r2, ip, lr}
353 mul r3, r0, r2
354 sub r1, r1, r3
355 ret lr
356
357 UNWIND(.fnend)
358 ENDPROC(__aeabi_idivmod)
359
360 #endif
361
362 Ldiv0:
363 UNWIND(.fnstart)
364 UNWIND(.pad #4)
365 UNWIND(.save {lr})
366 str lr, [sp, #-8]!
367 bl __div0
368 mov r0, #0 @ About as wrong as it could be.
369 ldr pc, [sp], #8
370 UNWIND(.fnend)
371 ENDPROC(Ldiv0)