blob: c463c68f85e8b9e974d908dfec1b379aa68c5bb5 [file] [log] [blame]
Simon Glass1251d512015-06-02 11:08:20 -06001#include <linux/linkage.h>
2
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02003.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.
301: 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.
381: 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
491: 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:
Simon Glass1251d512015-06-02 11:08:20 -0600101ENTRY(__aeabi_idiv)
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200102 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
12110: teq ip, r0 @ same sign ?
122 rsbmi r0, r0, #0
123 mov pc, lr
124
12511: movlo r0, #0
126 moveq r0, ip, asr #31
127 orreq r0, r0, #1
128 mov pc, lr
129
13012: 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
137Ldiv0:
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
Simon Glass1251d512015-06-02 11:08:20 -0600143ENDPROC(__aeabi_idiv)