blob: 601549304e00d177b02ec9c491a1deb9dd0c5893 [file] [log] [blame]
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001.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.
281: 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.
361: 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
471: 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
Wolfgang Denk8a5ddb12009-08-06 21:29:59 +020098.globl __aeabi_idiv
Wolfgang Denk4646d2a2006-05-30 15:56:48 +020099__divsi3:
Wolfgang Denk8a5ddb12009-08-06 21:29:59 +0200100__aeabi_idiv:
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200101 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
12010: teq ip, r0 @ same sign ?
121 rsbmi r0, r0, #0
122 mov pc, lr
123
12411: movlo r0, #0
125 moveq r0, ip, asr #31
126 orreq r0, r0, #1
127 mov pc, lr
128
12912: 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
136Ldiv0:
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