Merge with git://www.denx.de/git/u-boot.git
[platform/kernel/u-boot.git] / lib_arm / _divsi3.S
1
2 .macro ARM_DIV_BODY dividend, divisor, result, curbit
3
4 #if __LINUX_ARM_ARCH__ >= 5
5
6         clz     \curbit, \divisor
7         clz     \result, \dividend
8         sub     \result, \curbit, \result
9         mov     \curbit, #1
10         mov     \divisor, \divisor, lsl \result
11         mov     \curbit, \curbit, lsl \result
12         mov     \result, #0
13
14 #else
15
16         @ Initially shift the divisor left 3 bits if possible,
17         @ set curbit accordingly.  This allows for curbit to be located
18         @ at the left end of each 4 bit nibbles in the division loop
19         @ to save one loop in most cases.
20         tst     \divisor, #0xe0000000
21         moveq   \divisor, \divisor, lsl #3
22         moveq   \curbit, #8
23         movne   \curbit, #1
24
25         @ Unless the divisor is very big, shift it up in multiples of
26         @ four bits, since this is the amount of unwinding in the main
27         @ division loop.  Continue shifting until the divisor is
28         @ larger than the dividend.
29 1:      cmp     \divisor, #0x10000000
30         cmplo   \divisor, \dividend
31         movlo   \divisor, \divisor, lsl #4
32         movlo   \curbit, \curbit, lsl #4
33         blo     1b
34
35         @ For very big divisors, we must shift it a bit at a time, or
36         @ we will be in danger of overflowing.
37 1:      cmp     \divisor, #0x80000000
38         cmplo   \divisor, \dividend
39         movlo   \divisor, \divisor, lsl #1
40         movlo   \curbit, \curbit, lsl #1
41         blo     1b
42
43         mov     \result, #0
44
45 #endif
46
47         @ Division loop
48 1:      cmp     \dividend, \divisor
49         subhs   \dividend, \dividend, \divisor
50         orrhs   \result,   \result,   \curbit
51         cmp     \dividend, \divisor,  lsr #1
52         subhs   \dividend, \dividend, \divisor, lsr #1
53         orrhs   \result,   \result,   \curbit,  lsr #1
54         cmp     \dividend, \divisor,  lsr #2
55         subhs   \dividend, \dividend, \divisor, lsr #2
56         orrhs   \result,   \result,   \curbit,  lsr #2
57         cmp     \dividend, \divisor,  lsr #3
58         subhs   \dividend, \dividend, \divisor, lsr #3
59         orrhs   \result,   \result,   \curbit,  lsr #3
60         cmp     \dividend, #0                   @ Early termination?
61         movnes  \curbit,   \curbit,  lsr #4     @ No, any more bits to do?
62         movne   \divisor,  \divisor, lsr #4
63         bne     1b
64
65 .endm
66
67 .macro ARM_DIV2_ORDER divisor, order
68
69 #if __LINUX_ARM_ARCH__ >= 5
70
71         clz     \order, \divisor
72         rsb     \order, \order, #31
73
74 #else
75
76         cmp     \divisor, #(1 << 16)
77         movhs   \divisor, \divisor, lsr #16
78         movhs   \order, #16
79         movlo   \order, #0
80
81         cmp     \divisor, #(1 << 8)
82         movhs   \divisor, \divisor, lsr #8
83         addhs   \order, \order, #8
84
85         cmp     \divisor, #(1 << 4)
86         movhs   \divisor, \divisor, lsr #4
87         addhs   \order, \order, #4
88
89         cmp     \divisor, #(1 << 2)
90         addhi   \order, \order, #3
91         addls   \order, \order, \divisor, lsr #1
92
93 #endif
94
95 .endm
96
97         .align  5
98 .globl __divsi3
99 __divsi3:
100         cmp     r1, #0
101         eor     ip, r0, r1                      @ save the sign of the result.
102         beq     Ldiv0
103         rsbmi   r1, r1, #0                      @ loops below use unsigned.
104         subs    r2, r1, #1                      @ division by 1 or -1 ?
105         beq     10f
106         movs    r3, r0
107         rsbmi   r3, r0, #0                      @ positive dividend value
108         cmp     r3, r1
109         bls     11f
110         tst     r1, r2                          @ divisor is power of 2 ?
111         beq     12f
112
113         ARM_DIV_BODY r3, r1, r0, r2
114
115         cmp     ip, #0
116         rsbmi   r0, r0, #0
117         mov     pc, lr
118
119 10:     teq     ip, r0                          @ same sign ?
120         rsbmi   r0, r0, #0
121         mov     pc, lr
122
123 11:     movlo   r0, #0
124         moveq   r0, ip, asr #31
125         orreq   r0, r0, #1
126         mov     pc, lr
127
128 12:     ARM_DIV2_ORDER r1, r2
129
130         cmp     ip, #0
131         mov     r0, r3, lsr r2
132         rsbmi   r0, r0, #0
133         mov     pc, lr
134
135 Ldiv0:
136
137         str     lr, [sp, #-4]!
138         bl      __div0
139         mov     r0, #0                  @ About as wrong as it could be.
140         ldr     pc, [sp], #4