]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/libkern/arm/divsi3.S
unbound: Vendor import 1.16.1
[FreeBSD/FreeBSD.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 EENTRY_NP(__aeabi_uidiv)
56 EENTRY_NP(__aeabi_uidivmod)
57 .L_udivide:                             /* r0 = r0 / r1; r1 = r0 % r1 */
58         eor     r0, r1, r0 
59         eor     r1, r0, r1 
60         eor     r0, r1, r0 
61                                         /* r0 = r1 / r0; r1 = r1 % r0 */
62         cmp     r0, #1
63         bcc     .L_overflow
64         beq     .L_divide_l0
65         mov     ip, #0
66         movs    r1, r1
67         bpl     .L_divide_l1
68         orr     ip, ip, #0x20000000     /* ip bit 0x20000000 = -ve r1 */
69         movs    r1, r1, lsr #1
70         orrcs   ip, ip, #0x10000000     /* ip bit 0x10000000 = bit 0 of r1 */
71         b       .L_divide_l1
72
73 .L_divide_l0:                           /* r0 == 1 */
74         mov     r0, r1
75         mov     r1, #0
76         RET
77 EEND(__aeabi_uidiv)
78 EEND(__aeabi_uidivmod)
79 END(__udivsi3)
80
81 ENTRY_NP(__divsi3)
82 EENTRY_NP(__aeabi_idiv)
83 EENTRY_NP(__aeabi_idivmod)
84 .L_divide:                              /* r0 = r0 / r1; r1 = r0 % r1 */
85         eor     r0, r1, r0 
86         eor     r1, r0, r1 
87         eor     r0, r1, r0 
88                                         /* r0 = r1 / r0; r1 = r1 % r0 */
89         cmp     r0, #1
90         bcc     .L_overflow
91         beq     .L_divide_l0
92         ands    ip, r0, #0x80000000
93         rsbmi   r0, r0, #0
94         ands    r2, r1, #0x80000000
95         eor     ip, ip, r2
96         rsbmi   r1, r1, #0
97         orr     ip, r2, ip, lsr #1      /* ip bit 0x40000000 = -ve division */
98                                         /* ip bit 0x80000000 = -ve remainder */
99
100 .L_divide_l1:
101         mov     r2, #1
102         mov     r3, #0
103
104         /*
105          * If the highest bit of the dividend is set, we have to be
106          * careful when shifting the divisor. Test this. 
107          */
108         movs    r1,r1
109         bpl     .L_old_code
110
111         /*
112          * At this point, the highest bit of r1 is known to be set.
113          * We abuse this below in the tst instructions.
114          */
115         tst     r1, r0 /*, lsl #0 */
116         bmi     .L_divide_b1
117         tst     r1, r0, lsl #1
118         bmi     .L_divide_b2
119         tst     r1, r0, lsl #2
120         bmi     .L_divide_b3
121         tst     r1, r0, lsl #3
122         bmi     .L_divide_b4
123         tst     r1, r0, lsl #4
124         bmi     .L_divide_b5
125         tst     r1, r0, lsl #5
126         bmi     .L_divide_b6
127         tst     r1, r0, lsl #6
128         bmi     .L_divide_b7
129         tst     r1, r0, lsl #7
130         bmi     .L_divide_b8
131         tst     r1, r0, lsl #8
132         bmi     .L_divide_b9
133         tst     r1, r0, lsl #9
134         bmi     .L_divide_b10
135         tst     r1, r0, lsl #10
136         bmi     .L_divide_b11
137         tst     r1, r0, lsl #11
138         bmi     .L_divide_b12
139         tst     r1, r0, lsl #12
140         bmi     .L_divide_b13
141         tst     r1, r0, lsl #13
142         bmi     .L_divide_b14
143         tst     r1, r0, lsl #14
144         bmi     .L_divide_b15
145         tst     r1, r0, lsl #15
146         bmi     .L_divide_b16
147         tst     r1, r0, lsl #16
148         bmi     .L_divide_b17
149         tst     r1, r0, lsl #17
150         bmi     .L_divide_b18
151         tst     r1, r0, lsl #18
152         bmi     .L_divide_b19
153         tst     r1, r0, lsl #19
154         bmi     .L_divide_b20
155         tst     r1, r0, lsl #20
156         bmi     .L_divide_b21
157         tst     r1, r0, lsl #21
158         bmi     .L_divide_b22
159         tst     r1, r0, lsl #22
160         bmi     .L_divide_b23
161         tst     r1, r0, lsl #23
162         bmi     .L_divide_b24
163         tst     r1, r0, lsl #24
164         bmi     .L_divide_b25
165         tst     r1, r0, lsl #25
166         bmi     .L_divide_b26
167         tst     r1, r0, lsl #26
168         bmi     .L_divide_b27
169         tst     r1, r0, lsl #27
170         bmi     .L_divide_b28
171         tst     r1, r0, lsl #28
172         bmi     .L_divide_b29
173         tst     r1, r0, lsl #29
174         bmi     .L_divide_b30
175         tst     r1, r0, lsl #30
176         bmi     .L_divide_b31
177 /*
178  * instead of:
179  *      tst     r1, r0, lsl #31
180  *      bmi     .L_divide_b32
181  */
182         b       .L_divide_b32
183
184 .L_old_code:
185         cmp     r1, r0
186         bcc     .L_divide_b0
187         cmp     r1, r0, lsl #1
188         bcc     .L_divide_b1
189         cmp     r1, r0, lsl #2
190         bcc     .L_divide_b2
191         cmp     r1, r0, lsl #3
192         bcc     .L_divide_b3
193         cmp     r1, r0, lsl #4
194         bcc     .L_divide_b4
195         cmp     r1, r0, lsl #5
196         bcc     .L_divide_b5
197         cmp     r1, r0, lsl #6
198         bcc     .L_divide_b6
199         cmp     r1, r0, lsl #7
200         bcc     .L_divide_b7
201         cmp     r1, r0, lsl #8
202         bcc     .L_divide_b8
203         cmp     r1, r0, lsl #9
204         bcc     .L_divide_b9
205         cmp     r1, r0, lsl #10
206         bcc     .L_divide_b10
207         cmp     r1, r0, lsl #11
208         bcc     .L_divide_b11
209         cmp     r1, r0, lsl #12
210         bcc     .L_divide_b12
211         cmp     r1, r0, lsl #13
212         bcc     .L_divide_b13
213         cmp     r1, r0, lsl #14
214         bcc     .L_divide_b14
215         cmp     r1, r0, lsl #15
216         bcc     .L_divide_b15
217         cmp     r1, r0, lsl #16
218         bcc     .L_divide_b16
219         cmp     r1, r0, lsl #17
220         bcc     .L_divide_b17
221         cmp     r1, r0, lsl #18
222         bcc     .L_divide_b18
223         cmp     r1, r0, lsl #19
224         bcc     .L_divide_b19
225         cmp     r1, r0, lsl #20
226         bcc     .L_divide_b20
227         cmp     r1, r0, lsl #21
228         bcc     .L_divide_b21
229         cmp     r1, r0, lsl #22
230         bcc     .L_divide_b22
231         cmp     r1, r0, lsl #23
232         bcc     .L_divide_b23
233         cmp     r1, r0, lsl #24
234         bcc     .L_divide_b24
235         cmp     r1, r0, lsl #25
236         bcc     .L_divide_b25
237         cmp     r1, r0, lsl #26
238         bcc     .L_divide_b26
239         cmp     r1, r0, lsl #27
240         bcc     .L_divide_b27
241         cmp     r1, r0, lsl #28
242         bcc     .L_divide_b28
243         cmp     r1, r0, lsl #29
244         bcc     .L_divide_b29
245         cmp     r1, r0, lsl #30
246         bcc     .L_divide_b30
247 .L_divide_b32:
248         cmp     r1, r0, lsl #31
249         subhs   r1, r1,r0, lsl #31
250         addhs   r3, r3,r2, lsl #31
251 .L_divide_b31:
252         cmp     r1, r0, lsl #30
253         subhs   r1, r1,r0, lsl #30
254         addhs   r3, r3,r2, lsl #30
255 .L_divide_b30:
256         cmp     r1, r0, lsl #29
257         subhs   r1, r1,r0, lsl #29
258         addhs   r3, r3,r2, lsl #29
259 .L_divide_b29:
260         cmp     r1, r0, lsl #28
261         subhs   r1, r1,r0, lsl #28
262         addhs   r3, r3,r2, lsl #28
263 .L_divide_b28:
264         cmp     r1, r0, lsl #27
265         subhs   r1, r1,r0, lsl #27
266         addhs   r3, r3,r2, lsl #27
267 .L_divide_b27:
268         cmp     r1, r0, lsl #26
269         subhs   r1, r1,r0, lsl #26
270         addhs   r3, r3,r2, lsl #26
271 .L_divide_b26:
272         cmp     r1, r0, lsl #25
273         subhs   r1, r1,r0, lsl #25
274         addhs   r3, r3,r2, lsl #25
275 .L_divide_b25:
276         cmp     r1, r0, lsl #24
277         subhs   r1, r1,r0, lsl #24
278         addhs   r3, r3,r2, lsl #24
279 .L_divide_b24:
280         cmp     r1, r0, lsl #23
281         subhs   r1, r1,r0, lsl #23
282         addhs   r3, r3,r2, lsl #23
283 .L_divide_b23:
284         cmp     r1, r0, lsl #22
285         subhs   r1, r1,r0, lsl #22
286         addhs   r3, r3,r2, lsl #22
287 .L_divide_b22:
288         cmp     r1, r0, lsl #21
289         subhs   r1, r1,r0, lsl #21
290         addhs   r3, r3,r2, lsl #21
291 .L_divide_b21:
292         cmp     r1, r0, lsl #20
293         subhs   r1, r1,r0, lsl #20
294         addhs   r3, r3,r2, lsl #20
295 .L_divide_b20:
296         cmp     r1, r0, lsl #19
297         subhs   r1, r1,r0, lsl #19
298         addhs   r3, r3,r2, lsl #19
299 .L_divide_b19:
300         cmp     r1, r0, lsl #18
301         subhs   r1, r1,r0, lsl #18
302         addhs   r3, r3,r2, lsl #18
303 .L_divide_b18:
304         cmp     r1, r0, lsl #17
305         subhs   r1, r1,r0, lsl #17
306         addhs   r3, r3,r2, lsl #17
307 .L_divide_b17:
308         cmp     r1, r0, lsl #16
309         subhs   r1, r1,r0, lsl #16
310         addhs   r3, r3,r2, lsl #16
311 .L_divide_b16:
312         cmp     r1, r0, lsl #15
313         subhs   r1, r1,r0, lsl #15
314         addhs   r3, r3,r2, lsl #15
315 .L_divide_b15:
316         cmp     r1, r0, lsl #14
317         subhs   r1, r1,r0, lsl #14
318         addhs   r3, r3,r2, lsl #14
319 .L_divide_b14:
320         cmp     r1, r0, lsl #13
321         subhs   r1, r1,r0, lsl #13
322         addhs   r3, r3,r2, lsl #13
323 .L_divide_b13:
324         cmp     r1, r0, lsl #12
325         subhs   r1, r1,r0, lsl #12
326         addhs   r3, r3,r2, lsl #12
327 .L_divide_b12:
328         cmp     r1, r0, lsl #11
329         subhs   r1, r1,r0, lsl #11
330         addhs   r3, r3,r2, lsl #11
331 .L_divide_b11:
332         cmp     r1, r0, lsl #10
333         subhs   r1, r1,r0, lsl #10
334         addhs   r3, r3,r2, lsl #10
335 .L_divide_b10:
336         cmp     r1, r0, lsl #9
337         subhs   r1, r1,r0, lsl #9
338         addhs   r3, r3,r2, lsl #9
339 .L_divide_b9:
340         cmp     r1, r0, lsl #8
341         subhs   r1, r1,r0, lsl #8
342         addhs   r3, r3,r2, lsl #8
343 .L_divide_b8:
344         cmp     r1, r0, lsl #7
345         subhs   r1, r1,r0, lsl #7
346         addhs   r3, r3,r2, lsl #7
347 .L_divide_b7:
348         cmp     r1, r0, lsl #6
349         subhs   r1, r1,r0, lsl #6
350         addhs   r3, r3,r2, lsl #6
351 .L_divide_b6:
352         cmp     r1, r0, lsl #5
353         subhs   r1, r1,r0, lsl #5
354         addhs   r3, r3,r2, lsl #5
355 .L_divide_b5:
356         cmp     r1, r0, lsl #4
357         subhs   r1, r1,r0, lsl #4
358         addhs   r3, r3,r2, lsl #4
359 .L_divide_b4:
360         cmp     r1, r0, lsl #3
361         subhs   r1, r1,r0, lsl #3
362         addhs   r3, r3,r2, lsl #3
363 .L_divide_b3:
364         cmp     r1, r0, lsl #2
365         subhs   r1, r1,r0, lsl #2
366         addhs   r3, r3,r2, lsl #2
367 .L_divide_b2:
368         cmp     r1, r0, lsl #1
369         subhs   r1, r1,r0, lsl #1
370         addhs   r3, r3,r2, lsl #1
371 .L_divide_b1:
372         cmp     r1, r0
373         subhs   r1, r1, r0
374         addhs   r3, r3, r2
375 .L_divide_b0:
376
377         tst     ip, #0x20000000
378         bne     .L_udivide_l1
379         mov     r0, r3
380         cmp     ip, #0
381         rsbmi   r1, r1, #0
382         movs    ip, ip, lsl #1
383         bicmi   r0, r0, #0x80000000     /* Fix incase we divided 0x80000000 */
384         rsbmi   r0, r0, #0
385         RET
386
387 .L_udivide_l1:
388         tst     ip, #0x10000000
389         mov     r1, r1, lsl #1
390         orrne   r1, r1, #1
391         mov     r3, r3, lsl #1
392         cmp     r1, r0
393         subhs   r1, r1, r0
394         addhs   r3, r3, r2
395         mov     r0, r3
396         RET
397 EEND(__aeabi_idiv)
398 EEND(__aeabi_idivmod)
399 END(__divsi3)
400