blob: c5e1c229dfb25c3d4b676c94bb727fe8a7705415 [file] [log] [blame]
Simon Glass1251d512015-06-02 11:08:20 -06001#include <linux/linkage.h>
2
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02003.macro ARM_MOD_BODY dividend, divisor, order, spare
4
5#if __LINUX_ARM_ARCH__ >= 5
6
7 clz \order, \divisor
8 clz \spare, \dividend
9 sub \order, \order, \spare
10 mov \divisor, \divisor, lsl \order
11
12#else
13
14 mov \order, #0
15
16 @ Unless the divisor is very big, shift it up in multiples of
17 @ four bits, since this is the amount of unwinding in the main
18 @ division loop. Continue shifting until the divisor is
19 @ larger than the dividend.
201: cmp \divisor, #0x10000000
21 cmplo \divisor, \dividend
22 movlo \divisor, \divisor, lsl #4
23 addlo \order, \order, #4
24 blo 1b
25
26 @ For very big divisors, we must shift it a bit at a time, or
27 @ we will be in danger of overflowing.
281: cmp \divisor, #0x80000000
29 cmplo \divisor, \dividend
30 movlo \divisor, \divisor, lsl #1
31 addlo \order, \order, #1
32 blo 1b
33
34#endif
35
36 @ Perform all needed substractions to keep only the reminder.
37 @ Do comparisons in batch of 4 first.
38 subs \order, \order, #3 @ yes, 3 is intended here
39 blt 2f
40
411: cmp \dividend, \divisor
42 subhs \dividend, \dividend, \divisor
43 cmp \dividend, \divisor, lsr #1
44 subhs \dividend, \dividend, \divisor, lsr #1
45 cmp \dividend, \divisor, lsr #2
46 subhs \dividend, \dividend, \divisor, lsr #2
47 cmp \dividend, \divisor, lsr #3
48 subhs \dividend, \dividend, \divisor, lsr #3
49 cmp \dividend, #1
50 mov \divisor, \divisor, lsr #4
51 subges \order, \order, #4
52 bge 1b
53
54 tst \order, #3
55 teqne \dividend, #0
56 beq 5f
57
58 @ Either 1, 2 or 3 comparison/substractions are left.
592: cmn \order, #2
60 blt 4f
61 beq 3f
62 cmp \dividend, \divisor
63 subhs \dividend, \dividend, \divisor
64 mov \divisor, \divisor, lsr #1
653: cmp \dividend, \divisor
66 subhs \dividend, \dividend, \divisor
67 mov \divisor, \divisor, lsr #1
684: cmp \dividend, \divisor
69 subhs \dividend, \dividend, \divisor
705:
71.endm
72
73 .align 5
Simon Glass1251d512015-06-02 11:08:20 -060074ENTRY(__modsi3)
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020075 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
Simon Glass1251d512015-06-02 11:08:20 -060092ENDPROC(__modsi3)
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020093
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