add memset asm code
[ti-x.git] / src / arch / arm / lib / libgcc.S
blob1087b224f75adcc2368ca656709320e94fe864a0
1 /*
2  * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
3  *
4  * Author: Nicolas Pitre <nico@cam.org>
5  *   - contributed to gcc-3.4 on Sep 30, 2003
6  *   - adapted for the Linux kernel on Oct 2, 2003
7  */
9 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
11 This file is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
14 later version.
16 In addition to the permissions in the GNU General Public License, the
17 Free Software Foundation gives you unlimited permission to link the
18 compiled version of this file into combinations with other programs,
19 and to distribute those combinations without any restriction coming
20 from the use of this file.  (The General Public License restrictions
21 do apply in other respects; for example, they cover modification of
22 the file, and distribution when not linked into a combine
23 executable.)
25 This file is distributed in the hope that it will be useful, but
26 WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28 General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program; see the file COPYING.  If not, write to
32 the Free Software Foundation, 59 Temple Place - Suite 330,
33 Boston, MA 02111-1307, USA.  */
36 #include "prefix.s.h"
38 .macro ARM_DIV_BODY dividend, divisor, result, curbit
40 #if TI_CONFIG_ARM_VERSION >= 5
42         clz     \curbit, \divisor
43         clz     \result, \dividend
44         sub     \result, \curbit, \result
45         mov     \curbit, #1
46         mov     \divisor, \divisor, lsl \result
47         mov     \curbit, \curbit, lsl \result
48         mov     \result, #0
49         
50 #else
52         @ Initially shift the divisor left 3 bits if possible,
53         @ set curbit accordingly.  This allows for curbit to be located
54         @ at the left end of each 4 bit nibbles in the division loop
55         @ to save one loop in most cases.
56         tst     \divisor, #0xe0000000
57         moveq   \divisor, \divisor, lsl #3
58         moveq   \curbit, #8
59         movne   \curbit, #1
61         @ Unless the divisor is very big, shift it up in multiples of
62         @ four bits, since this is the amount of unwinding in the main
63         @ division loop.  Continue shifting until the divisor is 
64         @ larger than the dividend.
65 1:      cmp     \divisor, #0x10000000
66         cmplo   \divisor, \dividend
67         movlo   \divisor, \divisor, lsl #4
68         movlo   \curbit, \curbit, lsl #4
69         blo     1b
71         @ For very big divisors, we must shift it a bit at a time, or
72         @ we will be in danger of overflowing.
73 1:      cmp     \divisor, #0x80000000
74         cmplo   \divisor, \dividend
75         movlo   \divisor, \divisor, lsl #1
76         movlo   \curbit, \curbit, lsl #1
77         blo     1b
79         mov     \result, #0
81 #endif
83         @ Division loop
84 1:      cmp     \dividend, \divisor
85         subhs   \dividend, \dividend, \divisor
86         orrhs   \result,   \result,   \curbit
87         cmp     \dividend, \divisor,  lsr #1
88         subhs   \dividend, \dividend, \divisor, lsr #1
89         orrhs   \result,   \result,   \curbit,  lsr #1
90         cmp     \dividend, \divisor,  lsr #2
91         subhs   \dividend, \dividend, \divisor, lsr #2
92         orrhs   \result,   \result,   \curbit,  lsr #2
93         cmp     \dividend, \divisor,  lsr #3
94         subhs   \dividend, \dividend, \divisor, lsr #3
95         orrhs   \result,   \result,   \curbit,  lsr #3
96         cmp     \dividend, #0                   @ Early termination?
97         movnes  \curbit,   \curbit,  lsr #4     @ No, any more bits to do?
98         movne   \divisor,  \divisor, lsr #4
99         bne     1b
101 .endm
104 .macro ARM_DIV2_ORDER divisor, order
106 #if TI_CONFIG_ARM_VERSION >= 5
108         clz     \order, \divisor
109         rsb     \order, \order, #31
111 #else
113         cmp     \divisor, #(1 << 16)
114         movhs   \divisor, \divisor, lsr #16
115         movhs   \order, #16
116         movlo   \order, #0
118         cmp     \divisor, #(1 << 8)
119         movhs   \divisor, \divisor, lsr #8
120         addhs   \order, \order, #8
122         cmp     \divisor, #(1 << 4)
123         movhs   \divisor, \divisor, lsr #4
124         addhs   \order, \order, #4
126         cmp     \divisor, #(1 << 2)
127         addhi   \order, \order, #3
128         addls   \order, \order, \divisor, lsr #1
130 #endif
132 .endm
135 .macro ARM_MOD_BODY dividend, divisor, order, spare
137 #if TI_CONFIG_ARM_VERSION >= 5
139         clz     \order, \divisor
140         clz     \spare, \dividend
141         sub     \order, \order, \spare
142         mov     \divisor, \divisor, lsl \order
144 #else
146         mov     \order, #0
148         @ Unless the divisor is very big, shift it up in multiples of
149         @ four bits, since this is the amount of unwinding in the main
150         @ division loop.  Continue shifting until the divisor is 
151         @ larger than the dividend.
152 1:      cmp     \divisor, #0x10000000
153         cmplo   \divisor, \dividend
154         movlo   \divisor, \divisor, lsl #4
155         addlo   \order, \order, #4
156         blo     1b
158         @ For very big divisors, we must shift it a bit at a time, or
159         @ we will be in danger of overflowing.
160 1:      cmp     \divisor, #0x80000000
161         cmplo   \divisor, \dividend
162         movlo   \divisor, \divisor, lsl #1
163         addlo   \order, \order, #1
164         blo     1b
166 #endif
168         @ Perform all needed substractions to keep only the reminder.
169         @ Do comparisons in batch of 4 first.
170         subs    \order, \order, #3              @ yes, 3 is intended here
171         blt     2f
173 1:      cmp     \dividend, \divisor
174         subhs   \dividend, \dividend, \divisor
175         cmp     \dividend, \divisor,  lsr #1
176         subhs   \dividend, \dividend, \divisor, lsr #1
177         cmp     \dividend, \divisor,  lsr #2
178         subhs   \dividend, \dividend, \divisor, lsr #2
179         cmp     \dividend, \divisor,  lsr #3
180         subhs   \dividend, \dividend, \divisor, lsr #3
181         cmp     \dividend, #1
182         mov     \divisor, \divisor, lsr #4
183         subges  \order, \order, #4
184         bge     1b
186         tst     \order, #3
187         teqne   \dividend, #0
188         beq     5f
190         @ Either 1, 2 or 3 comparison/substractions are left.
191 2:      cmn     \order, #2
192         blt     4f
193         beq     3f
194         cmp     \dividend, \divisor
195         subhs   \dividend, \dividend, \divisor
196         mov     \divisor,  \divisor,  lsr #1
197 3:      cmp     \dividend, \divisor
198         subhs   \dividend, \dividend, \divisor
199         mov     \divisor,  \divisor,  lsr #1
200 4:      cmp     \dividend, \divisor
201         subhs   \dividend, \dividend, \divisor
203 .endm
206 TI_ASM_EXPORT(__udivsi3)
207 TI_ASM_EXPORT(__aeabi_uidiv)
209         subs    r2, r1, #1
210         moveq   pc, lr
211         bcc     Ldiv0
212         cmp     r0, r1
213         bls     11f
214         tst     r1, r2
215         beq     12f
217         ARM_DIV_BODY r0, r1, r2, r3
219         mov     r0, r2
220         mov     pc, lr
222 11:     moveq   r0, #1
223         movne   r0, #0
224         mov     pc, lr
226 12:     ARM_DIV2_ORDER r1, r2
228         mov     r0, r0, lsr r2
229         mov     pc, lr
232 TI_ASM_EXPORT(__umodsi3)
234         subs    r2, r1, #1                      @ compare divisor with 1
235         bcc     Ldiv0
236         cmpne   r0, r1                          @ compare dividend with divisor
237         moveq   r0, #0
238         tsthi   r1, r2                          @ see if divisor is power of 2
239         andeq   r0, r0, r2
240         movls   pc, lr
242         ARM_MOD_BODY r0, r1, r2, r3
244         mov     pc, lr
246 TI_ASM_EXPORT(__divsi3)
247 TI_ASM_EXPORT(__aeabi_idiv)
249         cmp     r1, #0
250         eor     ip, r0, r1                      @ save the sign of the result.
251         beq     Ldiv0
252         rsbmi   r1, r1, #0                      @ loops below use unsigned.
253         subs    r2, r1, #1                      @ division by 1 or -1 ?
254         beq     10f
255         movs    r3, r0
256         rsbmi   r3, r0, #0                      @ positive dividend value
257         cmp     r3, r1
258         bls     11f
259         tst     r1, r2                          @ divisor is power of 2 ?
260         beq     12f
262         ARM_DIV_BODY r3, r1, r0, r2
264         cmp     ip, #0
265         rsbmi   r0, r0, #0
266         mov     pc, lr
268 10:     teq     ip, r0                          @ same sign ?
269         rsbmi   r0, r0, #0
270         mov     pc, lr
272 11:     movlo   r0, #0
273         moveq   r0, ip, asr #31
274         orreq   r0, r0, #1
275         mov     pc, lr
277 12:     ARM_DIV2_ORDER r1, r2
279         cmp     ip, #0
280         mov     r0, r3, lsr r2
281         rsbmi   r0, r0, #0
282         mov     pc, lr
285 TI_ASM_EXPORT(__modsi3)
287         cmp     r1, #0
288         beq     Ldiv0
289         rsbmi   r1, r1, #0                      @ loops below use unsigned.
290         movs    ip, r0                          @ preserve sign of dividend
291         rsbmi   r0, r0, #0                      @ if negative make positive
292         subs    r2, r1, #1                      @ compare divisor with 1
293         cmpne   r0, r1                          @ compare dividend with divisor
294         moveq   r0, #0
295         tsthi   r1, r2                          @ see if divisor is power of 2
296         andeq   r0, r0, r2
297         bls     10f
299         ARM_MOD_BODY r0, r1, r2, r3
301 10:     cmp     ip, #0
302         rsbmi   r0, r0, #0
303         mov     pc, lr
306 #ifdef TI_CONFIG_AEABI
308 TI_ASM_EXPORT(__aeabi_uidivmod)
310         stmfd   sp!, {r0, r1, ip, lr}
311         bl      __aeabi_uidiv
312         ldmfd   sp!, {r1, r2, ip, lr}
313         mul     r3, r0, r2
314         sub     r1, r1, r3
315         mov     pc, lr
318 TI_ASM_EXPORT(__aeabi_idivmod)
320         stmfd   sp!, {r0, r1, ip, lr}
321         bl      __aeabi_idiv
322         ldmfd   sp!, {r1, r2, ip, lr}
323         mul     r3, r0, r2
324         sub     r1, r1, r3
325         mov     pc, lr
328 #endif
330 Ldiv0:
332         str     lr, [sp, #-8]!
333 #bl     __div0
334         mov     r0, #0                  @ About as wrong as it could be.
335         ldr     pc, [sp], #8