blob: b1667376c58a2bdcae9a5ac093320c7c33a104dd [file] [log] [blame]
Simon Glass1251d512015-06-02 11:08:20 -06001#include <linux/linkage.h>
2
wdenkc6097192002-11-03 00:24:07 +00003/* # 1 "libgcc1.S" */
4@ libgcc1 routines for ARM cpu.
5@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
6/* # 145 "libgcc1.S" */
7dividend .req r0
8divisor .req r1
9overdone .req r2
10curbit .req r3
wdenkac6dbb82003-03-26 11:42:53 +000011/* ip .req r12 */
12/* sp .req r13 */
13/* lr .req r14 */
14/* pc .req r15 */
wdenkc6097192002-11-03 00:24:07 +000015 .text
wdenkc6097192002-11-03 00:24:07 +000016 .type __umodsi3 ,function
17 .align 0
Simon Glass1251d512015-06-02 11:08:20 -060018 ENTRY(__umodsi3)
wdenkc6097192002-11-03 00:24:07 +000019 cmp divisor, #0
20 beq Ldiv0
21 mov curbit, #1
22 cmp dividend, divisor
Wolfgang Denk53677ef2008-05-20 16:00:29 +020023 movcc pc, lr
wdenkc6097192002-11-03 00:24:07 +000024Loop1:
25 @ Unless the divisor is very big, shift it up in multiples of
26 @ four bits, since this is the amount of unwinding in the main
27 @ division loop. Continue shifting until the divisor is
28 @ larger than the dividend.
29 cmp divisor, #0x10000000
30 cmpcc divisor, dividend
31 movcc divisor, divisor, lsl #4
32 movcc curbit, curbit, lsl #4
33 bcc Loop1
34Lbignum:
35 @ For very big divisors, we must shift it a bit at a time, or
36 @ we will be in danger of overflowing.
37 cmp divisor, #0x80000000
38 cmpcc divisor, dividend
39 movcc divisor, divisor, lsl #1
40 movcc curbit, curbit, lsl #1
41 bcc Lbignum
42Loop3:
43 @ Test for possible subtractions. On the final pass, this may
44 @ subtract too much from the dividend, so keep track of which
45 @ subtractions are done, we can fix them up afterwards...
46 mov overdone, #0
47 cmp dividend, divisor
48 subcs dividend, dividend, divisor
49 cmp dividend, divisor, lsr #1
50 subcs dividend, dividend, divisor, lsr #1
51 orrcs overdone, overdone, curbit, ror #1
52 cmp dividend, divisor, lsr #2
53 subcs dividend, dividend, divisor, lsr #2
54 orrcs overdone, overdone, curbit, ror #2
55 cmp dividend, divisor, lsr #3
56 subcs dividend, dividend, divisor, lsr #3
57 orrcs overdone, overdone, curbit, ror #3
58 mov ip, curbit
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 Loop3
63 @ Any subtractions that we should not have done will be recorded in
64 @ the top three bits of "overdone". Exactly which were not needed
65 @ are governed by the position of the bit, stored in ip.
66 @ If we terminated early, because dividend became zero,
67 @ then none of the below will match, since the bit in ip will not be
68 @ in the bottom nibble.
69 ands overdone, overdone, #0xe0000000
Wolfgang Denk53677ef2008-05-20 16:00:29 +020070 moveq pc, lr @ No fixups needed
wdenkc6097192002-11-03 00:24:07 +000071 tst overdone, ip, ror #3
72 addne dividend, dividend, divisor, lsr #3
73 tst overdone, ip, ror #2
74 addne dividend, dividend, divisor, lsr #2
75 tst overdone, ip, ror #1
76 addne dividend, dividend, divisor, lsr #1
Wolfgang Denk53677ef2008-05-20 16:00:29 +020077 mov pc, lr
wdenkc6097192002-11-03 00:24:07 +000078Ldiv0:
79 str lr, [sp, #-4]!
80 bl __div0 (PLT)
81 mov r0, #0 @ about as wrong as it could be
82 ldmia sp!, {pc}
83 .size __umodsi3 , . - __umodsi3
84/* # 320 "libgcc1.S" */
85/* # 421 "libgcc1.S" */
86/* # 433 "libgcc1.S" */
87/* # 456 "libgcc1.S" */
88/* # 500 "libgcc1.S" */
89/* # 580 "libgcc1.S" */
Simon Glass1251d512015-06-02 11:08:20 -060090ENDPROC(__umodsi3)