blob: 3d31a559f84e36be442729b5e49ab5b64324ef28 [file] [log] [blame]
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02001.macro ARM_MOD_BODY dividend, divisor, order, spare
2
3#if __LINUX_ARM_ARCH__ >= 5
4
5 clz \order, \divisor
6 clz \spare, \dividend
7 sub \order, \order, \spare
8 mov \divisor, \divisor, lsl \order
9
10#else
11
12 mov \order, #0
13
14 @ Unless the divisor is very big, shift it up in multiples of
15 @ four bits, since this is the amount of unwinding in the main
16 @ division loop. Continue shifting until the divisor is
17 @ larger than the dividend.
181: cmp \divisor, #0x10000000
19 cmplo \divisor, \dividend
20 movlo \divisor, \divisor, lsl #4
21 addlo \order, \order, #4
22 blo 1b
23
24 @ For very big divisors, we must shift it a bit at a time, or
25 @ we will be in danger of overflowing.
261: cmp \divisor, #0x80000000
27 cmplo \divisor, \dividend
28 movlo \divisor, \divisor, lsl #1
29 addlo \order, \order, #1
30 blo 1b
31
32#endif
33
34 @ Perform all needed substractions to keep only the reminder.
35 @ Do comparisons in batch of 4 first.
36 subs \order, \order, #3 @ yes, 3 is intended here
37 blt 2f
38
391: cmp \dividend, \divisor
40 subhs \dividend, \dividend, \divisor
41 cmp \dividend, \divisor, lsr #1
42 subhs \dividend, \dividend, \divisor, lsr #1
43 cmp \dividend, \divisor, lsr #2
44 subhs \dividend, \dividend, \divisor, lsr #2
45 cmp \dividend, \divisor, lsr #3
46 subhs \dividend, \dividend, \divisor, lsr #3
47 cmp \dividend, #1
48 mov \divisor, \divisor, lsr #4
49 subges \order, \order, #4
50 bge 1b
51
52 tst \order, #3
53 teqne \dividend, #0
54 beq 5f
55
56 @ Either 1, 2 or 3 comparison/substractions are left.
572: cmn \order, #2
58 blt 4f
59 beq 3f
60 cmp \dividend, \divisor
61 subhs \dividend, \dividend, \divisor
62 mov \divisor, \divisor, lsr #1
633: cmp \dividend, \divisor
64 subhs \dividend, \dividend, \divisor
65 mov \divisor, \divisor, lsr #1
664: cmp \dividend, \divisor
67 subhs \dividend, \dividend, \divisor
685:
69.endm
70
71 .align 5
72.globl __modsi3
73__modsi3:
74 cmp r1, #0
75 beq Ldiv0
76 rsbmi r1, r1, #0 @ loops below use unsigned.
77 movs ip, r0 @ preserve sign of dividend
78 rsbmi r0, r0, #0 @ if negative make positive
79 subs r2, r1, #1 @ compare divisor with 1
80 cmpne r0, r1 @ compare dividend with divisor
81 moveq r0, #0
82 tsthi r1, r2 @ see if divisor is power of 2
83 andeq r0, r0, r2
84 bls 10f
85
86 ARM_MOD_BODY r0, r1, r2, r3
87
8810: cmp ip, #0
89 rsbmi r0, r0, #0
90 mov pc, lr
91
92
93Ldiv0:
94
95 str lr, [sp, #-4]!
96 bl __div0
97 mov r0, #0 @ About as wrong as it could be.
98 ldr pc, [sp], #4