]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/lib/_modsi3.S
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / arch / arm / lib / _modsi3.S
1 .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.
18 1:      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.
26 1:      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
39 1:      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.
57 2:      cmn     \order, #2
58         blt     4f
59         beq     3f
60         cmp     \dividend, \divisor
61         subhs   \dividend, \dividend, \divisor
62         mov     \divisor,  \divisor,  lsr #1
63 3:      cmp     \dividend, \divisor
64         subhs   \dividend, \dividend, \divisor
65         mov     \divisor,  \divisor,  lsr #1
66 4:      cmp     \dividend, \divisor
67         subhs   \dividend, \dividend, \divisor
68 5:
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
88 10:     cmp     ip, #0
89         rsbmi   r0, r0, #0
90         mov     pc, lr
91
92
93 Ldiv0:
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