1 /* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */
2
3 /*-
4 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14 * SUCH DAMAGE.
15 */
16
17 #include <machine/asm.h>
18 __FBSDID("$FreeBSD: releng/11.2/sys/libkern/arm/divsi3.S 285338 2015-07-09 21:02:40Z andrew $");
19
20 /*
21 * stack is aligned as there's a possibility of branching to L_overflow
22 * which makes a C call
23 */
24
25 ENTRY_NP(__umodsi3)
26 stmfd sp!, {lr}
27 sub sp, sp, #4 /* align stack */
28 bl .L_udivide
29 add sp, sp, #4 /* unalign stack */
30 mov r0, r1
31 ldmfd sp!, {pc}
32 END(__umodsi3)
33
34 ENTRY_NP(__modsi3)
35 stmfd sp!, {lr}
36 sub sp, sp, #4 /* align stack */
37 bl .L_divide
38 add sp, sp, #4 /* unalign stack */
39 mov r0, r1
40 ldmfd sp!, {pc}
41
42 .L_overflow:
43 #if !defined(_KERNEL) && !defined(_STANDALONE)
44 mov r0, #8 /* SIGFPE */
45 bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */
46 mov r0, #0
47 #else
48 /* XXX should cause a fatal error */
49 mvn r0, #0
50 #endif
51 RET
52 END(__modsi3)
53
54 ENTRY_NP(__udivsi3)
55 EENTRY_NP(__aeabi_uidiv)
56 EENTRY_NP(__aeabi_uidivmod)
57 .L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */
58 eor r0, r1, r0
59 eor r1, r0, r1
60 eor r0, r1, r0
61 /* r0 = r1 / r0; r1 = r1 % r0 */
62 cmp r0, #1
63 bcc .L_overflow
64 beq .L_divide_l0
65 mov ip, #0
66 movs r1, r1
67 bpl .L_divide_l1
68 orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */
69 movs r1, r1, lsr #1
70 orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */
71 b .L_divide_l1
72
73 .L_divide_l0: /* r0 == 1 */
74 mov r0, r1
75 mov r1, #0
76 RET
77 EEND(__aeabi_uidiv)
78 EEND(__aeabi_uidivmod)
79 END(__udivsi3)
80
81 ENTRY_NP(__divsi3)
82 EENTRY_NP(__aeabi_idiv)
83 EENTRY_NP(__aeabi_idivmod)
84 .L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */
85 eor r0, r1, r0
86 eor r1, r0, r1
87 eor r0, r1, r0
88 /* r0 = r1 / r0; r1 = r1 % r0 */
89 cmp r0, #1
90 bcc .L_overflow
91 beq .L_divide_l0
92 ands ip, r0, #0x80000000
93 rsbmi r0, r0, #0
94 ands r2, r1, #0x80000000
95 eor ip, ip, r2
96 rsbmi r1, r1, #0
97 orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */
98 /* ip bit 0x80000000 = -ve remainder */
99
100 .L_divide_l1:
101 mov r2, #1
102 mov r3, #0
103
104 /*
105 * If the highest bit of the dividend is set, we have to be
106 * careful when shifting the divisor. Test this.
107 */
108 movs r1,r1
109 bpl .L_old_code
110
111 /*
112 * At this point, the highest bit of r1 is known to be set.
113 * We abuse this below in the tst instructions.
114 */
115 tst r1, r0 /*, lsl #0 */
116 bmi .L_divide_b1
117 tst r1, r0, lsl #1
118 bmi .L_divide_b2
119 tst r1, r0, lsl #2
120 bmi .L_divide_b3
121 tst r1, r0, lsl #3
122 bmi .L_divide_b4
123 tst r1, r0, lsl #4
124 bmi .L_divide_b5
125 tst r1, r0, lsl #5
126 bmi .L_divide_b6
127 tst r1, r0, lsl #6
128 bmi .L_divide_b7
129 tst r1, r0, lsl #7
130 bmi .L_divide_b8
131 tst r1, r0, lsl #8
132 bmi .L_divide_b9
133 tst r1, r0, lsl #9
134 bmi .L_divide_b10
135 tst r1, r0, lsl #10
136 bmi .L_divide_b11
137 tst r1, r0, lsl #11
138 bmi .L_divide_b12
139 tst r1, r0, lsl #12
140 bmi .L_divide_b13
141 tst r1, r0, lsl #13
142 bmi .L_divide_b14
143 tst r1, r0, lsl #14
144 bmi .L_divide_b15
145 tst r1, r0, lsl #15
146 bmi .L_divide_b16
147 tst r1, r0, lsl #16
148 bmi .L_divide_b17
149 tst r1, r0, lsl #17
150 bmi .L_divide_b18
151 tst r1, r0, lsl #18
152 bmi .L_divide_b19
153 tst r1, r0, lsl #19
154 bmi .L_divide_b20
155 tst r1, r0, lsl #20
156 bmi .L_divide_b21
157 tst r1, r0, lsl #21
158 bmi .L_divide_b22
159 tst r1, r0, lsl #22
160 bmi .L_divide_b23
161 tst r1, r0, lsl #23
162 bmi .L_divide_b24
163 tst r1, r0, lsl #24
164 bmi .L_divide_b25
165 tst r1, r0, lsl #25
166 bmi .L_divide_b26
167 tst r1, r0, lsl #26
168 bmi .L_divide_b27
169 tst r1, r0, lsl #27
170 bmi .L_divide_b28
171 tst r1, r0, lsl #28
172 bmi .L_divide_b29
173 tst r1, r0, lsl #29
174 bmi .L_divide_b30
175 tst r1, r0, lsl #30
176 bmi .L_divide_b31
177 /*
178 * instead of:
179 * tst r1, r0, lsl #31
180 * bmi .L_divide_b32
181 */
182 b .L_divide_b32
183
184 .L_old_code:
185 cmp r1, r0
186 bcc .L_divide_b0
187 cmp r1, r0, lsl #1
188 bcc .L_divide_b1
189 cmp r1, r0, lsl #2
190 bcc .L_divide_b2
191 cmp r1, r0, lsl #3
192 bcc .L_divide_b3
193 cmp r1, r0, lsl #4
194 bcc .L_divide_b4
195 cmp r1, r0, lsl #5
196 bcc .L_divide_b5
197 cmp r1, r0, lsl #6
198 bcc .L_divide_b6
199 cmp r1, r0, lsl #7
200 bcc .L_divide_b7
201 cmp r1, r0, lsl #8
202 bcc .L_divide_b8
203 cmp r1, r0, lsl #9
204 bcc .L_divide_b9
205 cmp r1, r0, lsl #10
206 bcc .L_divide_b10
207 cmp r1, r0, lsl #11
208 bcc .L_divide_b11
209 cmp r1, r0, lsl #12
210 bcc .L_divide_b12
211 cmp r1, r0, lsl #13
212 bcc .L_divide_b13
213 cmp r1, r0, lsl #14
214 bcc .L_divide_b14
215 cmp r1, r0, lsl #15
216 bcc .L_divide_b15
217 cmp r1, r0, lsl #16
218 bcc .L_divide_b16
219 cmp r1, r0, lsl #17
220 bcc .L_divide_b17
221 cmp r1, r0, lsl #18
222 bcc .L_divide_b18
223 cmp r1, r0, lsl #19
224 bcc .L_divide_b19
225 cmp r1, r0, lsl #20
226 bcc .L_divide_b20
227 cmp r1, r0, lsl #21
228 bcc .L_divide_b21
229 cmp r1, r0, lsl #22
230 bcc .L_divide_b22
231 cmp r1, r0, lsl #23
232 bcc .L_divide_b23
233 cmp r1, r0, lsl #24
234 bcc .L_divide_b24
235 cmp r1, r0, lsl #25
236 bcc .L_divide_b25
237 cmp r1, r0, lsl #26
238 bcc .L_divide_b26
239 cmp r1, r0, lsl #27
240 bcc .L_divide_b27
241 cmp r1, r0, lsl #28
242 bcc .L_divide_b28
243 cmp r1, r0, lsl #29
244 bcc .L_divide_b29
245 cmp r1, r0, lsl #30
246 bcc .L_divide_b30
247 .L_divide_b32:
248 cmp r1, r0, lsl #31
249 subhs r1, r1,r0, lsl #31
250 addhs r3, r3,r2, lsl #31
251 .L_divide_b31:
252 cmp r1, r0, lsl #30
253 subhs r1, r1,r0, lsl #30
254 addhs r3, r3,r2, lsl #30
255 .L_divide_b30:
256 cmp r1, r0, lsl #29
257 subhs r1, r1,r0, lsl #29
258 addhs r3, r3,r2, lsl #29
259 .L_divide_b29:
260 cmp r1, r0, lsl #28
261 subhs r1, r1,r0, lsl #28
262 addhs r3, r3,r2, lsl #28
263 .L_divide_b28:
264 cmp r1, r0, lsl #27
265 subhs r1, r1,r0, lsl #27
266 addhs r3, r3,r2, lsl #27
267 .L_divide_b27:
268 cmp r1, r0, lsl #26
269 subhs r1, r1,r0, lsl #26
270 addhs r3, r3,r2, lsl #26
271 .L_divide_b26:
272 cmp r1, r0, lsl #25
273 subhs r1, r1,r0, lsl #25
274 addhs r3, r3,r2, lsl #25
275 .L_divide_b25:
276 cmp r1, r0, lsl #24
277 subhs r1, r1,r0, lsl #24
278 addhs r3, r3,r2, lsl #24
279 .L_divide_b24:
280 cmp r1, r0, lsl #23
281 subhs r1, r1,r0, lsl #23
282 addhs r3, r3,r2, lsl #23
283 .L_divide_b23:
284 cmp r1, r0, lsl #22
285 subhs r1, r1,r0, lsl #22
286 addhs r3, r3,r2, lsl #22
287 .L_divide_b22:
288 cmp r1, r0, lsl #21
289 subhs r1, r1,r0, lsl #21
290 addhs r3, r3,r2, lsl #21
291 .L_divide_b21:
292 cmp r1, r0, lsl #20
293 subhs r1, r1,r0, lsl #20
294 addhs r3, r3,r2, lsl #20
295 .L_divide_b20:
296 cmp r1, r0, lsl #19
297 subhs r1, r1,r0, lsl #19
298 addhs r3, r3,r2, lsl #19
299 .L_divide_b19:
300 cmp r1, r0, lsl #18
301 subhs r1, r1,r0, lsl #18
302 addhs r3, r3,r2, lsl #18
303 .L_divide_b18:
304 cmp r1, r0, lsl #17
305 subhs r1, r1,r0, lsl #17
306 addhs r3, r3,r2, lsl #17
307 .L_divide_b17:
308 cmp r1, r0, lsl #16
309 subhs r1, r1,r0, lsl #16
310 addhs r3, r3,r2, lsl #16
311 .L_divide_b16:
312 cmp r1, r0, lsl #15
313 subhs r1, r1,r0, lsl #15
314 addhs r3, r3,r2, lsl #15
315 .L_divide_b15:
316 cmp r1, r0, lsl #14
317 subhs r1, r1,r0, lsl #14
318 addhs r3, r3,r2, lsl #14
319 .L_divide_b14:
320 cmp r1, r0, lsl #13
321 subhs r1, r1,r0, lsl #13
322 addhs r3, r3,r2, lsl #13
323 .L_divide_b13:
324 cmp r1, r0, lsl #12
325 subhs r1, r1,r0, lsl #12
326 addhs r3, r3,r2, lsl #12
327 .L_divide_b12:
328 cmp r1, r0, lsl #11
329 subhs r1, r1,r0, lsl #11
330 addhs r3, r3,r2, lsl #11
331 .L_divide_b11:
332 cmp r1, r0, lsl #10
333 subhs r1, r1,r0, lsl #10
334 addhs r3, r3,r2, lsl #10
335 .L_divide_b10:
336 cmp r1, r0, lsl #9
337 subhs r1, r1,r0, lsl #9
338 addhs r3, r3,r2, lsl #9
339 .L_divide_b9:
340 cmp r1, r0, lsl #8
341 subhs r1, r1,r0, lsl #8
342 addhs r3, r3,r2, lsl #8
343 .L_divide_b8:
344 cmp r1, r0, lsl #7
345 subhs r1, r1,r0, lsl #7
346 addhs r3, r3,r2, lsl #7
347 .L_divide_b7:
348 cmp r1, r0, lsl #6
349 subhs r1, r1,r0, lsl #6
350 addhs r3, r3,r2, lsl #6
351 .L_divide_b6:
352 cmp r1, r0, lsl #5
353 subhs r1, r1,r0, lsl #5
354 addhs r3, r3,r2, lsl #5
355 .L_divide_b5:
356 cmp r1, r0, lsl #4
357 subhs r1, r1,r0, lsl #4
358 addhs r3, r3,r2, lsl #4
359 .L_divide_b4:
360 cmp r1, r0, lsl #3
361 subhs r1, r1,r0, lsl #3
362 addhs r3, r3,r2, lsl #3
363 .L_divide_b3:
364 cmp r1, r0, lsl #2
365 subhs r1, r1,r0, lsl #2
366 addhs r3, r3,r2, lsl #2
367 .L_divide_b2:
368 cmp r1, r0, lsl #1
369 subhs r1, r1,r0, lsl #1
370 addhs r3, r3,r2, lsl #1
371 .L_divide_b1:
372 cmp r1, r0
373 subhs r1, r1, r0
374 addhs r3, r3, r2
375 .L_divide_b0:
376
377 tst ip, #0x20000000
378 bne .L_udivide_l1
379 mov r0, r3
380 cmp ip, #0
381 rsbmi r1, r1, #0
382 movs ip, ip, lsl #1
383 bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */
384 rsbmi r0, r0, #0
385 RET
386
387 .L_udivide_l1:
388 tst ip, #0x10000000
389 mov r1, r1, lsl #1
390 orrne r1, r1, #1
391 mov r3, r3, lsl #1
392 cmp r1, r0
393 subhs r1, r1, r0
394 addhs r3, r3, r2
395 mov r0, r3
396 RET
397 EEND(__aeabi_idiv)
398 EEND(__aeabi_idivmod)
399 END(__divsi3)
400
Cache object: d38e6d5f46b437bbc698900db5728636
|