Merge commit 'wd/master'
[platform/kernel/u-boot.git] / lib_arm / _umodsi3.S
1 /* # 1 "libgcc1.S" */
2 @ libgcc1 routines for ARM cpu.
3 @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
4 /* # 145 "libgcc1.S" */
5 dividend        .req    r0
6 divisor         .req    r1
7 overdone        .req    r2
8 curbit          .req    r3
9 /* ip           .req    r12     */
10 /* sp           .req    r13     */
11 /* lr           .req    r14     */
12 /* pc           .req    r15     */
13         .text
14         .globl   __umodsi3
15         .type  __umodsi3       ,function
16         .align 0
17  __umodsi3      :
18         cmp     divisor, #0
19         beq     Ldiv0
20         mov     curbit, #1
21         cmp     dividend, divisor
22         movcc   pc, lr
23 Loop1:
24         @ Unless the divisor is very big, shift it up in multiples of
25         @ four bits, since this is the amount of unwinding in the main
26         @ division loop.  Continue shifting until the divisor is
27         @ larger than the dividend.
28         cmp     divisor, #0x10000000
29         cmpcc   divisor, dividend
30         movcc   divisor, divisor, lsl #4
31         movcc   curbit, curbit, lsl #4
32         bcc     Loop1
33 Lbignum:
34         @ For very big divisors, we must shift it a bit at a time, or
35         @ we will be in danger of overflowing.
36         cmp     divisor, #0x80000000
37         cmpcc   divisor, dividend
38         movcc   divisor, divisor, lsl #1
39         movcc   curbit, curbit, lsl #1
40         bcc     Lbignum
41 Loop3:
42         @ Test for possible subtractions.  On the final pass, this may
43         @ subtract too much from the dividend, so keep track of which
44         @ subtractions are done, we can fix them up afterwards...
45         mov     overdone, #0
46         cmp     dividend, divisor
47         subcs   dividend, dividend, divisor
48         cmp     dividend, divisor, lsr #1
49         subcs   dividend, dividend, divisor, lsr #1
50         orrcs   overdone, overdone, curbit, ror #1
51         cmp     dividend, divisor, lsr #2
52         subcs   dividend, dividend, divisor, lsr #2
53         orrcs   overdone, overdone, curbit, ror #2
54         cmp     dividend, divisor, lsr #3
55         subcs   dividend, dividend, divisor, lsr #3
56         orrcs   overdone, overdone, curbit, ror #3
57         mov     ip, curbit
58         cmp     dividend, #0                    @ Early termination?
59         movnes  curbit, curbit, lsr #4          @ No, any more bits to do?
60         movne   divisor, divisor, lsr #4
61         bne     Loop3
62         @ Any subtractions that we should not have done will be recorded in
63         @ the top three bits of "overdone".  Exactly which were not needed
64         @ are governed by the position of the bit, stored in ip.
65         @ If we terminated early, because dividend became zero,
66         @ then none of the below will match, since the bit in ip will not be
67         @ in the bottom nibble.
68         ands    overdone, overdone, #0xe0000000
69         moveq   pc, lr                          @ No fixups needed
70         tst     overdone, ip, ror #3
71         addne   dividend, dividend, divisor, lsr #3
72         tst     overdone, ip, ror #2
73         addne   dividend, dividend, divisor, lsr #2
74         tst     overdone, ip, ror #1
75         addne   dividend, dividend, divisor, lsr #1
76         mov     pc, lr
77 Ldiv0:
78         str     lr, [sp, #-4]!
79         bl       __div0       (PLT)
80         mov     r0, #0                  @ about as wrong as it could be
81         ldmia   sp!, {pc}
82         .size  __umodsi3       , . -  __umodsi3
83 /* # 320 "libgcc1.S" */
84 /* # 421 "libgcc1.S" */
85 /* # 433 "libgcc1.S" */
86 /* # 456 "libgcc1.S" */
87 /* # 500 "libgcc1.S" */
88 /* # 580 "libgcc1.S" */