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