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