]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/lib/_modsi3.S
arm: remove bogus cp_delay() function
[karo-tx-uboot.git] / arch / arm / lib / _modsi3.S
1 #include <linux/linkage.h>
2
3 .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.
20 1:      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.
28 1:      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
41 1:      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.
59 2:      cmn     \order, #2
60         blt     4f
61         beq     3f
62         cmp     \dividend, \divisor
63         subhs   \dividend, \dividend, \divisor
64         mov     \divisor,  \divisor,  lsr #1
65 3:      cmp     \dividend, \divisor
66         subhs   \dividend, \dividend, \divisor
67         mov     \divisor,  \divisor,  lsr #1
68 4:      cmp     \dividend, \divisor
69         subhs   \dividend, \dividend, \divisor
70 5:
71 .endm
72
73         .align  5
74 ENTRY(__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
89 10:     cmp     ip, #0
90         rsbmi   r0, r0, #0
91         mov     pc, lr
92 ENDPROC(__modsi3)
93
94 Ldiv0:
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