Merge remote-tracking branch 'lightnvm/for-next'
[deliverable/linux.git] / arch / arm / lib / lib1funcs.S
1 /*
2 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
3 *
4 * Author: Nicolas Pitre <nico@fluxnic.net>
5 * - contributed to gcc-3.4 on Sep 30, 2003
6 * - adapted for the Linux kernel on Oct 2, 2003
7 */
8
9 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
10
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.
15
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.)
24
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.
29
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. */
34
35
36 #include <linux/linkage.h>
37 #include <asm/assembler.h>
38 #include <asm/unwind.h>
39 #include <asm/export.h>
40
41 .macro ARM_DIV_BODY dividend, divisor, result, curbit
42
43 #if __LINUX_ARM_ARCH__ >= 5
44
45 clz \curbit, \divisor
46 clz \result, \dividend
47 sub \result, \curbit, \result
48 mov \curbit, #1
49 mov \divisor, \divisor, lsl \result
50 mov \curbit, \curbit, lsl \result
51 mov \result, #0
52
53 #else
54
55 @ Initially shift the divisor left 3 bits if possible,
56 @ set curbit accordingly. This allows for curbit to be located
57 @ at the left end of each 4 bit nibbles in the division loop
58 @ to save one loop in most cases.
59 tst \divisor, #0xe0000000
60 moveq \divisor, \divisor, lsl #3
61 moveq \curbit, #8
62 movne \curbit, #1
63
64 @ Unless the divisor is very big, shift it up in multiples of
65 @ four bits, since this is the amount of unwinding in the main
66 @ division loop. Continue shifting until the divisor is
67 @ larger than the dividend.
68 1: cmp \divisor, #0x10000000
69 cmplo \divisor, \dividend
70 movlo \divisor, \divisor, lsl #4
71 movlo \curbit, \curbit, lsl #4
72 blo 1b
73
74 @ For very big divisors, we must shift it a bit at a time, or
75 @ we will be in danger of overflowing.
76 1: cmp \divisor, #0x80000000
77 cmplo \divisor, \dividend
78 movlo \divisor, \divisor, lsl #1
79 movlo \curbit, \curbit, lsl #1
80 blo 1b
81
82 mov \result, #0
83
84 #endif
85
86 @ Division loop
87 1: cmp \dividend, \divisor
88 subhs \dividend, \dividend, \divisor
89 orrhs \result, \result, \curbit
90 cmp \dividend, \divisor, lsr #1
91 subhs \dividend, \dividend, \divisor, lsr #1
92 orrhs \result, \result, \curbit, lsr #1
93 cmp \dividend, \divisor, lsr #2
94 subhs \dividend, \dividend, \divisor, lsr #2
95 orrhs \result, \result, \curbit, lsr #2
96 cmp \dividend, \divisor, lsr #3
97 subhs \dividend, \dividend, \divisor, lsr #3
98 orrhs \result, \result, \curbit, lsr #3
99 cmp \dividend, #0 @ Early termination?
100 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
101 movne \divisor, \divisor, lsr #4
102 bne 1b
103
104 .endm
105
106
107 .macro ARM_DIV2_ORDER divisor, order
108
109 #if __LINUX_ARM_ARCH__ >= 5
110
111 clz \order, \divisor
112 rsb \order, \order, #31
113
114 #else
115
116 cmp \divisor, #(1 << 16)
117 movhs \divisor, \divisor, lsr #16
118 movhs \order, #16
119 movlo \order, #0
120
121 cmp \divisor, #(1 << 8)
122 movhs \divisor, \divisor, lsr #8
123 addhs \order, \order, #8
124
125 cmp \divisor, #(1 << 4)
126 movhs \divisor, \divisor, lsr #4
127 addhs \order, \order, #4
128
129 cmp \divisor, #(1 << 2)
130 addhi \order, \order, #3
131 addls \order, \order, \divisor, lsr #1
132
133 #endif
134
135 .endm
136
137
138 .macro ARM_MOD_BODY dividend, divisor, order, spare
139
140 #if __LINUX_ARM_ARCH__ >= 5
141
142 clz \order, \divisor
143 clz \spare, \dividend
144 sub \order, \order, \spare
145 mov \divisor, \divisor, lsl \order
146
147 #else
148
149 mov \order, #0
150
151 @ Unless the divisor is very big, shift it up in multiples of
152 @ four bits, since this is the amount of unwinding in the main
153 @ division loop. Continue shifting until the divisor is
154 @ larger than the dividend.
155 1: cmp \divisor, #0x10000000
156 cmplo \divisor, \dividend
157 movlo \divisor, \divisor, lsl #4
158 addlo \order, \order, #4
159 blo 1b
160
161 @ For very big divisors, we must shift it a bit at a time, or
162 @ we will be in danger of overflowing.
163 1: cmp \divisor, #0x80000000
164 cmplo \divisor, \dividend
165 movlo \divisor, \divisor, lsl #1
166 addlo \order, \order, #1
167 blo 1b
168
169 #endif
170
171 @ Perform all needed subtractions to keep only the reminder.
172 @ Do comparisons in batch of 4 first.
173 subs \order, \order, #3 @ yes, 3 is intended here
174 blt 2f
175
176 1: cmp \dividend, \divisor
177 subhs \dividend, \dividend, \divisor
178 cmp \dividend, \divisor, lsr #1
179 subhs \dividend, \dividend, \divisor, lsr #1
180 cmp \dividend, \divisor, lsr #2
181 subhs \dividend, \dividend, \divisor, lsr #2
182 cmp \dividend, \divisor, lsr #3
183 subhs \dividend, \dividend, \divisor, lsr #3
184 cmp \dividend, #1
185 mov \divisor, \divisor, lsr #4
186 subges \order, \order, #4
187 bge 1b
188
189 tst \order, #3
190 teqne \dividend, #0
191 beq 5f
192
193 @ Either 1, 2 or 3 comparison/subtractions are left.
194 2: cmn \order, #2
195 blt 4f
196 beq 3f
197 cmp \dividend, \divisor
198 subhs \dividend, \dividend, \divisor
199 mov \divisor, \divisor, lsr #1
200 3: cmp \dividend, \divisor
201 subhs \dividend, \dividend, \divisor
202 mov \divisor, \divisor, lsr #1
203 4: cmp \dividend, \divisor
204 subhs \dividend, \dividend, \divisor
205 5:
206 .endm
207
208
209 #ifdef CONFIG_ARM_PATCH_IDIV
210 .align 3
211 #endif
212
213 ENTRY(__udivsi3)
214 ENTRY(__aeabi_uidiv)
215 UNWIND(.fnstart)
216
217 subs r2, r1, #1
218 reteq lr
219 bcc Ldiv0
220 cmp r0, r1
221 bls 11f
222 tst r1, r2
223 beq 12f
224
225 ARM_DIV_BODY r0, r1, r2, r3
226
227 mov r0, r2
228 ret lr
229
230 11: moveq r0, #1
231 movne r0, #0
232 ret lr
233
234 12: ARM_DIV2_ORDER r1, r2
235
236 mov r0, r0, lsr r2
237 ret lr
238
239 UNWIND(.fnend)
240 ENDPROC(__udivsi3)
241 ENDPROC(__aeabi_uidiv)
242 EXPORT_SYMBOL(__udivsi3)
243 EXPORT_SYMBOL(__aeabi_uidiv)
244
245 ENTRY(__umodsi3)
246 UNWIND(.fnstart)
247
248 subs r2, r1, #1 @ compare divisor with 1
249 bcc Ldiv0
250 cmpne r0, r1 @ compare dividend with divisor
251 moveq r0, #0
252 tsthi r1, r2 @ see if divisor is power of 2
253 andeq r0, r0, r2
254 retls lr
255
256 ARM_MOD_BODY r0, r1, r2, r3
257
258 ret lr
259
260 UNWIND(.fnend)
261 ENDPROC(__umodsi3)
262 EXPORT_SYMBOL(__umodsi3)
263
264 #ifdef CONFIG_ARM_PATCH_IDIV
265 .align 3
266 #endif
267
268 ENTRY(__divsi3)
269 ENTRY(__aeabi_idiv)
270 UNWIND(.fnstart)
271
272 cmp r1, #0
273 eor ip, r0, r1 @ save the sign of the result.
274 beq Ldiv0
275 rsbmi r1, r1, #0 @ loops below use unsigned.
276 subs r2, r1, #1 @ division by 1 or -1 ?
277 beq 10f
278 movs r3, r0
279 rsbmi r3, r0, #0 @ positive dividend value
280 cmp r3, r1
281 bls 11f
282 tst r1, r2 @ divisor is power of 2 ?
283 beq 12f
284
285 ARM_DIV_BODY r3, r1, r0, r2
286
287 cmp ip, #0
288 rsbmi r0, r0, #0
289 ret lr
290
291 10: teq ip, r0 @ same sign ?
292 rsbmi r0, r0, #0
293 ret lr
294
295 11: movlo r0, #0
296 moveq r0, ip, asr #31
297 orreq r0, r0, #1
298 ret lr
299
300 12: ARM_DIV2_ORDER r1, r2
301
302 cmp ip, #0
303 mov r0, r3, lsr r2
304 rsbmi r0, r0, #0
305 ret lr
306
307 UNWIND(.fnend)
308 ENDPROC(__divsi3)
309 ENDPROC(__aeabi_idiv)
310 EXPORT_SYMBOL(__divsi3)
311 EXPORT_SYMBOL(__aeabi_idiv)
312
313 ENTRY(__modsi3)
314 UNWIND(.fnstart)
315
316 cmp r1, #0
317 beq Ldiv0
318 rsbmi r1, r1, #0 @ loops below use unsigned.
319 movs ip, r0 @ preserve sign of dividend
320 rsbmi r0, r0, #0 @ if negative make positive
321 subs r2, r1, #1 @ compare divisor with 1
322 cmpne r0, r1 @ compare dividend with divisor
323 moveq r0, #0
324 tsthi r1, r2 @ see if divisor is power of 2
325 andeq r0, r0, r2
326 bls 10f
327
328 ARM_MOD_BODY r0, r1, r2, r3
329
330 10: cmp ip, #0
331 rsbmi r0, r0, #0
332 ret lr
333
334 UNWIND(.fnend)
335 ENDPROC(__modsi3)
336 EXPORT_SYMBOL(__modsi3)
337
338 #ifdef CONFIG_AEABI
339
340 ENTRY(__aeabi_uidivmod)
341 UNWIND(.fnstart)
342 UNWIND(.save {r0, r1, ip, lr} )
343
344 stmfd sp!, {r0, r1, ip, lr}
345 bl __aeabi_uidiv
346 ldmfd sp!, {r1, r2, ip, lr}
347 mul r3, r0, r2
348 sub r1, r1, r3
349 ret lr
350
351 UNWIND(.fnend)
352 ENDPROC(__aeabi_uidivmod)
353 EXPORT_SYMBOL(__aeabi_uidivmod)
354
355 ENTRY(__aeabi_idivmod)
356 UNWIND(.fnstart)
357 UNWIND(.save {r0, r1, ip, lr} )
358 stmfd sp!, {r0, r1, ip, lr}
359 bl __aeabi_idiv
360 ldmfd sp!, {r1, r2, ip, lr}
361 mul r3, r0, r2
362 sub r1, r1, r3
363 ret lr
364
365 UNWIND(.fnend)
366 ENDPROC(__aeabi_idivmod)
367 EXPORT_SYMBOL(__aeabi_idivmod)
368
369 #endif
370
371 Ldiv0:
372 UNWIND(.fnstart)
373 UNWIND(.pad #4)
374 UNWIND(.save {lr})
375 str lr, [sp, #-8]!
376 bl __div0
377 mov r0, #0 @ About as wrong as it could be.
378 ldr pc, [sp], #8
379 UNWIND(.fnend)
380 ENDPROC(Ldiv0)
This page took 0.046813 seconds and 5 git commands to generate.