1
2
3
4
5
6
7
8
9
10
11
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14#include <asm/unwind.h>
15
16#ifdef __ARMEB__
17#define xh r0
18#define xl r1
19#define yh r2
20#define yl r3
21#else
22#define xl r0
23#define xh r1
24#define yl r2
25#define yh r3
26#endif
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45ENTRY(__do_div64)
46UNWIND(.fnstart)
47
48 @ Test for easy paths first.
49 subs ip, r4,
50 bls 9f @ divisor is 0 or 1
51 tst ip, r4
52 beq 8f @ divisor is power of 2
53
54 @ See if we need to handle upper 32-bit result.
55 cmp xh, r4
56 mov yh,
57 blo 3f
58
59 @ Align divisor with upper part of dividend.
60 @ The aligned divisor is stored in yl preserving the original.
61 @ The bit position is stored in ip.
62
63
64
65 clz yl, r4
66 clz ip, xh
67 sub yl, yl, ip
68 mov ip,
69 mov ip, ip, lsl yl
70 mov yl, r4, lsl yl
71
72#else
73
74 mov yl, r4
75 mov ip,
761: cmp yl,
77 cmpcc yl, xh
78 movcc yl, yl, lsl
79 movcc ip, ip, lsl
80 bcc 1b
81
82#endif
83
84 @ The division loop for needed upper bit positions.
85 @ Break out early if dividend reaches 0.
862: cmp xh, yl
87 orrcs yh, yh, ip
88 subscs xh, xh, yl
89 movsne ip, ip, lsr
90 mov yl, yl, lsr
91 bne 2b
92
93 @ See if we need to handle lower 32-bit result.
943: cmp xh,
95 mov yl,
96 cmpeq xl, r4
97 movlo xh, xl
98 retlo lr
99
100 @ The division loop for lower bit positions.
101 @ Here we shift remainer bits leftwards rather than moving the
102 @ divisor for comparisons, considering the carry-out bit as well.
103 mov ip,
1044: movs xl, xl, lsl
105 adcs xh, xh, xh
106 beq 6f
107 cmpcc xh, r4
1085: orrcs yl, yl, ip
109 subcs xh, xh, r4
110 movs ip, ip, lsr
111 bne 4b
112 ret lr
113
114 @ The top part of remainder became zero. If carry is set
115 @ (the 33th bit) this is a false positive so resume the loop.
116 @ Otherwise, if lower part is also null then we are done.
1176: bcs 5b
118 cmp xl,
119 reteq lr
120
121 @ We still have remainer bits in the low part. Bring them up.
122
123
124
125 clz xh, xl @ we know xh is zero here so...
126 add xh, xh,
127 mov xl, xl, lsl xh
128 mov ip, ip, lsr xh
129
130#else
131
1327: movs xl, xl, lsl
133 mov ip, ip, lsr
134 bcc 7b
135
136#endif
137
138 @ Current remainder is now 1. It is worthless to compare with
139 @ divisor at this point since divisor can not be smaller than 3 here.
140 @ If possible, branch for another shift in the division loop.
141 @ If no bit position left then we are done.
142 movs ip, ip, lsr
143 mov xh,
144 bne 4b
145 ret lr
146
1478: @ Division by a power of 2: determine what that divisor order is
148 @ then simply shift values around
149
150
151
152 clz ip, r4
153 rsb ip, ip,
154
155#else
156
157 mov yl, r4
158 cmp r4,
159 mov ip,
160 movhs yl, yl, lsr
161 movhs ip,
162
163 cmp yl,
164 movhs yl, yl, lsr
165 addhs ip, ip,
166
167 cmp yl,
168 movhs yl, yl, lsr
169 addhs ip, ip,
170
171 cmp yl,
172 addhi ip, ip,
173 addls ip, ip, yl, lsr
174
175#endif
176
177 mov yh, xh, lsr ip
178 mov yl, xl, lsr ip
179 rsb ip, ip,
180 ARM( orr yl, yl, xh, lsl ip )
181 THUMB( lsl xh, xh, ip )
182 THUMB( orr yl, yl, xh )
183 mov xh, xl, lsl ip
184 mov xh, xh, lsr ip
185 ret lr
186
187 @ eq -> division by 1: obvious enough...
1889: moveq yl, xl
189 moveq yh, xh
190 moveq xh,
191 reteq lr
192UNWIND(.fnend)
193
194UNWIND(.fnstart)
195UNWIND(.pad
196UNWIND(.save {lr})
197Ldiv0_64:
198 @ Division by 0:
199 str lr, [sp,
200 bl __div0
201
202 @ as wrong as it could be...
203 mov yl,
204 mov yh,
205 mov xh,
206 ldr pc, [sp],
207
208UNWIND(.fnend)
209ENDPROC(__do_div64)
210