]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/libkern/arm/divsi3.S
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / libkern / arm / divsi3.S
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$");
19
20 /* 
21  * stack is aligned as there's a possibility of branching to L_overflow
22  * which makes a C call
23  */
24
25 ENTRY_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}
32 END(__umodsi3)
33
34 ENTRY_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
52 END(__modsi3)
53
54 ENTRY_NP(__udivsi3)
55 #ifdef __ARM_EABI__
56 EENTRY_NP(__aeabi_uidiv)
57 EENTRY_NP(__aeabi_uidivmod)
58 #endif
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__
80 EEND(__aeabi_uidiv)
81 EEND(__aeabi_uidivmod)
82 #endif
83 END(__udivsi3)
84
85 ENTRY_NP(__divsi3)
86 #ifdef __ARM_EABI__
87 EENTRY_NP(__aeabi_idiv)
88 EENTRY_NP(__aeabi_idivmod)
89 #endif
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__
404 EEND(__aeabi_idiv)
405 EEND(__aeabi_idivmod)
406 #endif
407 END(__divsi3)
408