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