Deleted Added
full compact
1/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */
2
3/*-
4 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14 * SUCH DAMAGE.
15 */
16
17#include <machine/asm.h>
18__FBSDID("$FreeBSD: head/sys/libkern/arm/divsi3.S 245548 2013-01-17 09:37:42Z andrew $");
18__FBSDID("$FreeBSD: head/sys/libkern/arm/divsi3.S 248367 2013-03-16 04:08:01Z andrew $");
19
20/*
21 * stack is aligned as there's a possibility of branching to L_overflow
22 * which makes a C call
23 */
24
25ENTRY_NP(__umodsi3)
26 stmfd sp!, {lr}
27 sub sp, sp, #4 /* align stack */
28 bl .L_udivide
29 add sp, sp, #4 /* unalign stack */
30 mov r0, r1
31 ldmfd sp!, {pc}
32END(__umodsi3)
33
34ENTRY_NP(__modsi3)
35 stmfd sp!, {lr}
36 sub sp, sp, #4 /* align stack */
37 bl .L_divide
38 add sp, sp, #4 /* unalign stack */
39 mov r0, r1
40 ldmfd sp!, {pc}
41
42.L_overflow:
43#if !defined(_KERNEL) && !defined(_STANDALONE)
44 mov r0, #8 /* SIGFPE */
45 bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */
46 mov r0, #0
47#else
48 /* XXX should cause a fatal error */
49 mvn r0, #0
50#endif
51 RET
52END(__modsi3)
53
54#ifdef __ARM_EABI__
55ENTRY_NP(__aeabi_uidiv)
56ENTRY_NP(__aeabi_uidivmod)
57#endif
58ENTRY_NP(__udivsi3)
59.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */
60 eor r0, r1, r0
61 eor r1, r0, r1
62 eor r0, r1, r0
63 /* r0 = r1 / r0; r1 = r1 % r0 */
64 cmp r0, #1
65 bcc .L_overflow
66 beq .L_divide_l0
67 mov ip, #0
68 movs r1, r1
69 bpl .L_divide_l1
70 orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */
71 movs r1, r1, lsr #1
72 orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */
73 b .L_divide_l1
74
75.L_divide_l0: /* r0 == 1 */
76 mov r0, r1
77 mov r1, #0
78 RET
79#ifdef __ARM_EABI__
80END(__aeabi_uidiv)
81END(__aeabi_uidivmod)
82#endif
83END(__udivsi3)
84
85#ifdef __ARM_EABI__
86ENTRY_NP(__aeabi_idiv)
87ENTRY_NP(__aeabi_idivmod)
88#endif
89ENTRY_NP(__divsi3)
90.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */
91 eor r0, r1, r0
92 eor r1, r0, r1
93 eor r0, r1, r0
94 /* r0 = r1 / r0; r1 = r1 % r0 */
95 cmp r0, #1
96 bcc .L_overflow
97 beq .L_divide_l0
98 ands ip, r0, #0x80000000
99 rsbmi r0, r0, #0
100 ands r2, r1, #0x80000000
101 eor ip, ip, r2
102 rsbmi r1, r1, #0
103 orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */
104 /* ip bit 0x80000000 = -ve remainder */
105
106.L_divide_l1:
107 mov r2, #1
108 mov r3, #0
109
110 /*
111 * If the highest bit of the dividend is set, we have to be
112 * careful when shifting the divisor. Test this.
113 */
114 movs r1,r1
115 bpl .L_old_code
116
117 /*
118 * At this point, the highest bit of r1 is known to be set.
119 * We abuse this below in the tst instructions.
120 */
121 tst r1, r0 /*, lsl #0 */
122 bmi .L_divide_b1
123 tst r1, r0, lsl #1
124 bmi .L_divide_b2
125 tst r1, r0, lsl #2
126 bmi .L_divide_b3
127 tst r1, r0, lsl #3
128 bmi .L_divide_b4
129 tst r1, r0, lsl #4
130 bmi .L_divide_b5
131 tst r1, r0, lsl #5
132 bmi .L_divide_b6
133 tst r1, r0, lsl #6
134 bmi .L_divide_b7
135 tst r1, r0, lsl #7
136 bmi .L_divide_b8
137 tst r1, r0, lsl #8
138 bmi .L_divide_b9
139 tst r1, r0, lsl #9
140 bmi .L_divide_b10
141 tst r1, r0, lsl #10
142 bmi .L_divide_b11
143 tst r1, r0, lsl #11
144 bmi .L_divide_b12
145 tst r1, r0, lsl #12
146 bmi .L_divide_b13
147 tst r1, r0, lsl #13
148 bmi .L_divide_b14
149 tst r1, r0, lsl #14
150 bmi .L_divide_b15
151 tst r1, r0, lsl #15
152 bmi .L_divide_b16
153 tst r1, r0, lsl #16
154 bmi .L_divide_b17
155 tst r1, r0, lsl #17
156 bmi .L_divide_b18
157 tst r1, r0, lsl #18
158 bmi .L_divide_b19
159 tst r1, r0, lsl #19
160 bmi .L_divide_b20
161 tst r1, r0, lsl #20
162 bmi .L_divide_b21
163 tst r1, r0, lsl #21
164 bmi .L_divide_b22
165 tst r1, r0, lsl #22
166 bmi .L_divide_b23
167 tst r1, r0, lsl #23
168 bmi .L_divide_b24
169 tst r1, r0, lsl #24
170 bmi .L_divide_b25
171 tst r1, r0, lsl #25
172 bmi .L_divide_b26
173 tst r1, r0, lsl #26
174 bmi .L_divide_b27
175 tst r1, r0, lsl #27
176 bmi .L_divide_b28
177 tst r1, r0, lsl #28
178 bmi .L_divide_b29
179 tst r1, r0, lsl #29
180 bmi .L_divide_b30
181 tst r1, r0, lsl #30
182 bmi .L_divide_b31
183/*
184 * instead of:
185 * tst r1, r0, lsl #31
186 * bmi .L_divide_b32
187 */
188 b .L_divide_b32
189
190.L_old_code:
191 cmp r1, r0
192 bcc .L_divide_b0
193 cmp r1, r0, lsl #1
194 bcc .L_divide_b1
195 cmp r1, r0, lsl #2
196 bcc .L_divide_b2
197 cmp r1, r0, lsl #3
198 bcc .L_divide_b3
199 cmp r1, r0, lsl #4
200 bcc .L_divide_b4
201 cmp r1, r0, lsl #5
202 bcc .L_divide_b5
203 cmp r1, r0, lsl #6
204 bcc .L_divide_b6
205 cmp r1, r0, lsl #7
206 bcc .L_divide_b7
207 cmp r1, r0, lsl #8
208 bcc .L_divide_b8
209 cmp r1, r0, lsl #9
210 bcc .L_divide_b9
211 cmp r1, r0, lsl #10
212 bcc .L_divide_b10
213 cmp r1, r0, lsl #11
214 bcc .L_divide_b11
215 cmp r1, r0, lsl #12
216 bcc .L_divide_b12
217 cmp r1, r0, lsl #13
218 bcc .L_divide_b13
219 cmp r1, r0, lsl #14
220 bcc .L_divide_b14
221 cmp r1, r0, lsl #15
222 bcc .L_divide_b15
223 cmp r1, r0, lsl #16
224 bcc .L_divide_b16
225 cmp r1, r0, lsl #17
226 bcc .L_divide_b17
227 cmp r1, r0, lsl #18
228 bcc .L_divide_b18
229 cmp r1, r0, lsl #19
230 bcc .L_divide_b19
231 cmp r1, r0, lsl #20
232 bcc .L_divide_b20
233 cmp r1, r0, lsl #21
234 bcc .L_divide_b21
235 cmp r1, r0, lsl #22
236 bcc .L_divide_b22
237 cmp r1, r0, lsl #23
238 bcc .L_divide_b23
239 cmp r1, r0, lsl #24
240 bcc .L_divide_b24
241 cmp r1, r0, lsl #25
242 bcc .L_divide_b25
243 cmp r1, r0, lsl #26
244 bcc .L_divide_b26
245 cmp r1, r0, lsl #27
246 bcc .L_divide_b27
247 cmp r1, r0, lsl #28
248 bcc .L_divide_b28
249 cmp r1, r0, lsl #29
250 bcc .L_divide_b29
251 cmp r1, r0, lsl #30
252 bcc .L_divide_b30
253.L_divide_b32:
254 cmp r1, r0, lsl #31
255 subhs r1, r1,r0, lsl #31
256 addhs r3, r3,r2, lsl #31
257.L_divide_b31:
258 cmp r1, r0, lsl #30
259 subhs r1, r1,r0, lsl #30
260 addhs r3, r3,r2, lsl #30
261.L_divide_b30:
262 cmp r1, r0, lsl #29
263 subhs r1, r1,r0, lsl #29
264 addhs r3, r3,r2, lsl #29
265.L_divide_b29:
266 cmp r1, r0, lsl #28
267 subhs r1, r1,r0, lsl #28
268 addhs r3, r3,r2, lsl #28
269.L_divide_b28:
270 cmp r1, r0, lsl #27
271 subhs r1, r1,r0, lsl #27
272 addhs r3, r3,r2, lsl #27
273.L_divide_b27:
274 cmp r1, r0, lsl #26
275 subhs r1, r1,r0, lsl #26
276 addhs r3, r3,r2, lsl #26
277.L_divide_b26:
278 cmp r1, r0, lsl #25
279 subhs r1, r1,r0, lsl #25
280 addhs r3, r3,r2, lsl #25
281.L_divide_b25:
282 cmp r1, r0, lsl #24
283 subhs r1, r1,r0, lsl #24
284 addhs r3, r3,r2, lsl #24
285.L_divide_b24:
286 cmp r1, r0, lsl #23
287 subhs r1, r1,r0, lsl #23
288 addhs r3, r3,r2, lsl #23
289.L_divide_b23:
290 cmp r1, r0, lsl #22
291 subhs r1, r1,r0, lsl #22
292 addhs r3, r3,r2, lsl #22
293.L_divide_b22:
294 cmp r1, r0, lsl #21
295 subhs r1, r1,r0, lsl #21
296 addhs r3, r3,r2, lsl #21
297.L_divide_b21:
298 cmp r1, r0, lsl #20
299 subhs r1, r1,r0, lsl #20
300 addhs r3, r3,r2, lsl #20
301.L_divide_b20:
302 cmp r1, r0, lsl #19
303 subhs r1, r1,r0, lsl #19
304 addhs r3, r3,r2, lsl #19
305.L_divide_b19:
306 cmp r1, r0, lsl #18
307 subhs r1, r1,r0, lsl #18
308 addhs r3, r3,r2, lsl #18
309.L_divide_b18:
310 cmp r1, r0, lsl #17
311 subhs r1, r1,r0, lsl #17
312 addhs r3, r3,r2, lsl #17
313.L_divide_b17:
314 cmp r1, r0, lsl #16
315 subhs r1, r1,r0, lsl #16
316 addhs r3, r3,r2, lsl #16
317.L_divide_b16:
318 cmp r1, r0, lsl #15
319 subhs r1, r1,r0, lsl #15
320 addhs r3, r3,r2, lsl #15
321.L_divide_b15:
322 cmp r1, r0, lsl #14
323 subhs r1, r1,r0, lsl #14
324 addhs r3, r3,r2, lsl #14
325.L_divide_b14:
326 cmp r1, r0, lsl #13
327 subhs r1, r1,r0, lsl #13
328 addhs r3, r3,r2, lsl #13
329.L_divide_b13:
330 cmp r1, r0, lsl #12
331 subhs r1, r1,r0, lsl #12
332 addhs r3, r3,r2, lsl #12
333.L_divide_b12:
334 cmp r1, r0, lsl #11
335 subhs r1, r1,r0, lsl #11
336 addhs r3, r3,r2, lsl #11
337.L_divide_b11:
338 cmp r1, r0, lsl #10
339 subhs r1, r1,r0, lsl #10
340 addhs r3, r3,r2, lsl #10
341.L_divide_b10:
342 cmp r1, r0, lsl #9
343 subhs r1, r1,r0, lsl #9
344 addhs r3, r3,r2, lsl #9
345.L_divide_b9:
346 cmp r1, r0, lsl #8
347 subhs r1, r1,r0, lsl #8
348 addhs r3, r3,r2, lsl #8
349.L_divide_b8:
350 cmp r1, r0, lsl #7
351 subhs r1, r1,r0, lsl #7
352 addhs r3, r3,r2, lsl #7
353.L_divide_b7:
354 cmp r1, r0, lsl #6
355 subhs r1, r1,r0, lsl #6
356 addhs r3, r3,r2, lsl #6
357.L_divide_b6:
358 cmp r1, r0, lsl #5
359 subhs r1, r1,r0, lsl #5
360 addhs r3, r3,r2, lsl #5
361.L_divide_b5:
362 cmp r1, r0, lsl #4
363 subhs r1, r1,r0, lsl #4
364 addhs r3, r3,r2, lsl #4
365.L_divide_b4:
366 cmp r1, r0, lsl #3
367 subhs r1, r1,r0, lsl #3
368 addhs r3, r3,r2, lsl #3
369.L_divide_b3:
370 cmp r1, r0, lsl #2
371 subhs r1, r1,r0, lsl #2
372 addhs r3, r3,r2, lsl #2
373.L_divide_b2:
374 cmp r1, r0, lsl #1
375 subhs r1, r1,r0, lsl #1
376 addhs r3, r3,r2, lsl #1
377.L_divide_b1:
378 cmp r1, r0
379 subhs r1, r1, r0
380 addhs r3, r3, r2
381.L_divide_b0:
382
383 tst ip, #0x20000000
384 bne .L_udivide_l1
385 mov r0, r3
386 cmp ip, #0
387 rsbmi r1, r1, #0
388 movs ip, ip, lsl #1
389 bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */
390 rsbmi r0, r0, #0
391 RET
392
393.L_udivide_l1:
394 tst ip, #0x10000000
395 mov r1, r1, lsl #1
396 orrne r1, r1, #1
397 mov r3, r3, lsl #1
398 cmp r1, r0
399 subhs r1, r1, r0
400 addhs r3, r3, r2
401 mov r0, r3
402 RET
403#ifdef __ARM_EABI__
404END(__aeabi_idiv)
405END(__aeabi_idivmod)
406#endif
407END(__divsi3)
408