0
|
1 @ libgcc routines for ARM cpu.
|
|
2 @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
|
3
|
|
4 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005, 2007, 2008,
|
|
5 2009 Free Software Foundation, Inc.
|
|
6
|
|
7 This file is free software; you can redistribute it and/or modify it
|
|
8 under the terms of the GNU General Public License as published by the
|
|
9 Free Software Foundation; either version 3, or (at your option) any
|
|
10 later version.
|
|
11
|
|
12 This file is distributed in the hope that it will be useful, but
|
|
13 WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15 General Public License for more details.
|
|
16
|
|
17 Under Section 7 of GPL version 3, you are granted additional
|
|
18 permissions described in the GCC Runtime Library Exception, version
|
|
19 3.1, as published by the Free Software Foundation.
|
|
20
|
|
21 You should have received a copy of the GNU General Public License and
|
|
22 a copy of the GCC Runtime Library Exception along with this program;
|
|
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
24 <http://www.gnu.org/licenses/>. */
|
|
25
|
|
26 /* An executable stack is *not* required for these functions. */
|
|
27 #if defined(__ELF__) && defined(__linux__)
|
|
28 .section .note.GNU-stack,"",%progbits
|
|
29 .previous
|
|
30 #endif
|
|
31
|
|
32 /* ------------------------------------------------------------------------ */
|
|
33
|
|
34 /* We need to know what prefix to add to function names. */
|
|
35
|
|
36 #ifndef __USER_LABEL_PREFIX__
|
|
37 #error __USER_LABEL_PREFIX__ not defined
|
|
38 #endif
|
|
39
|
|
40 /* ANSI concatenation macros. */
|
|
41
|
|
42 #define CONCAT1(a, b) CONCAT2(a, b)
|
|
43 #define CONCAT2(a, b) a ## b
|
|
44
|
|
45 /* Use the right prefix for global labels. */
|
|
46
|
|
47 #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
|
48
|
|
49 #ifdef __ELF__
|
|
50 #ifdef __thumb__
|
|
51 #define __PLT__ /* Not supported in Thumb assembler (for now). */
|
|
52 #elif defined __vxworks && !defined __PIC__
|
|
53 #define __PLT__ /* Not supported by the kernel loader. */
|
|
54 #else
|
|
55 #define __PLT__ (PLT)
|
|
56 #endif
|
|
57 #define TYPE(x) .type SYM(x),function
|
|
58 #define SIZE(x) .size SYM(x), . - SYM(x)
|
|
59 #define LSYM(x) .x
|
|
60 #else
|
|
61 #define __PLT__
|
|
62 #define TYPE(x)
|
|
63 #define SIZE(x)
|
|
64 #define LSYM(x) x
|
|
65 #endif
|
|
66
|
|
67 /* Function end macros. Variants for interworking. */
|
|
68
|
|
69 #if defined(__ARM_ARCH_2__)
|
|
70 # define __ARM_ARCH__ 2
|
|
71 #endif
|
|
72
|
|
73 #if defined(__ARM_ARCH_3__)
|
|
74 # define __ARM_ARCH__ 3
|
|
75 #endif
|
|
76
|
|
77 #if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
|
|
78 || defined(__ARM_ARCH_4T__)
|
|
79 /* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
|
|
80 long multiply instructions. That includes v3M. */
|
|
81 # define __ARM_ARCH__ 4
|
|
82 #endif
|
|
83
|
|
84 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
|
85 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
|
86 || defined(__ARM_ARCH_5TEJ__)
|
|
87 # define __ARM_ARCH__ 5
|
|
88 #endif
|
|
89
|
|
90 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
|
91 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|
|
92 || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|
|
93 || defined(__ARM_ARCH_6M__)
|
|
94 # define __ARM_ARCH__ 6
|
|
95 #endif
|
|
96
|
|
97 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
|
98 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
|
|
99 # define __ARM_ARCH__ 7
|
|
100 #endif
|
|
101
|
|
102 #ifndef __ARM_ARCH__
|
|
103 #error Unable to determine architecture.
|
|
104 #endif
|
|
105
|
|
106 /* How to return from a function call depends on the architecture variant. */
|
|
107
|
|
108 #if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
|
|
109
|
|
110 # define RET bx lr
|
|
111 # define RETc(x) bx##x lr
|
|
112
|
|
113 /* Special precautions for interworking on armv4t. */
|
|
114 # if (__ARM_ARCH__ == 4)
|
|
115
|
|
116 /* Always use bx, not ldr pc. */
|
|
117 # if (defined(__thumb__) || defined(__THUMB_INTERWORK__))
|
|
118 # define __INTERWORKING__
|
|
119 # endif /* __THUMB__ || __THUMB_INTERWORK__ */
|
|
120
|
|
121 /* Include thumb stub before arm mode code. */
|
|
122 # if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
|
123 # define __INTERWORKING_STUBS__
|
|
124 # endif /* __thumb__ && !__THUMB_INTERWORK__ */
|
|
125
|
|
126 #endif /* __ARM_ARCH == 4 */
|
|
127
|
|
128 #else
|
|
129
|
|
130 # define RET mov pc, lr
|
|
131 # define RETc(x) mov##x pc, lr
|
|
132
|
|
133 #endif
|
|
134
|
|
135 .macro cfi_pop advance, reg, cfa_offset
|
|
136 #ifdef __ELF__
|
|
137 .pushsection .debug_frame
|
|
138 .byte 0x4 /* DW_CFA_advance_loc4 */
|
|
139 .4byte \advance
|
|
140 .byte (0xc0 | \reg) /* DW_CFA_restore */
|
|
141 .byte 0xe /* DW_CFA_def_cfa_offset */
|
|
142 .uleb128 \cfa_offset
|
|
143 .popsection
|
|
144 #endif
|
|
145 .endm
|
|
146 .macro cfi_push advance, reg, offset, cfa_offset
|
|
147 #ifdef __ELF__
|
|
148 .pushsection .debug_frame
|
|
149 .byte 0x4 /* DW_CFA_advance_loc4 */
|
|
150 .4byte \advance
|
|
151 .byte (0x80 | \reg) /* DW_CFA_offset */
|
|
152 .uleb128 (\offset / -4)
|
|
153 .byte 0xe /* DW_CFA_def_cfa_offset */
|
|
154 .uleb128 \cfa_offset
|
|
155 .popsection
|
|
156 #endif
|
|
157 .endm
|
|
158 .macro cfi_start start_label, end_label
|
|
159 #ifdef __ELF__
|
|
160 .pushsection .debug_frame
|
|
161 LSYM(Lstart_frame):
|
|
162 .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
|
|
163 LSYM(Lstart_cie):
|
|
164 .4byte 0xffffffff @ CIE Identifier Tag
|
|
165 .byte 0x1 @ CIE Version
|
|
166 .ascii "\0" @ CIE Augmentation
|
|
167 .uleb128 0x1 @ CIE Code Alignment Factor
|
|
168 .sleb128 -4 @ CIE Data Alignment Factor
|
|
169 .byte 0xe @ CIE RA Column
|
|
170 .byte 0xc @ DW_CFA_def_cfa
|
|
171 .uleb128 0xd
|
|
172 .uleb128 0x0
|
|
173
|
|
174 .align 2
|
|
175 LSYM(Lend_cie):
|
|
176 .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
|
|
177 LSYM(Lstart_fde):
|
|
178 .4byte LSYM(Lstart_frame) @ FDE CIE offset
|
|
179 .4byte \start_label @ FDE initial location
|
|
180 .4byte \end_label-\start_label @ FDE address range
|
|
181 .popsection
|
|
182 #endif
|
|
183 .endm
|
|
184 .macro cfi_end end_label
|
|
185 #ifdef __ELF__
|
|
186 .pushsection .debug_frame
|
|
187 .align 2
|
|
188 LSYM(Lend_fde):
|
|
189 .popsection
|
|
190 \end_label:
|
|
191 #endif
|
|
192 .endm
|
|
193
|
|
194 /* Don't pass dirn, it's there just to get token pasting right. */
|
|
195
|
|
196 .macro RETLDM regs=, cond=, unwind=, dirn=ia
|
|
197 #if defined (__INTERWORKING__)
|
|
198 .ifc "\regs",""
|
|
199 ldr\cond lr, [sp], #8
|
|
200 .else
|
|
201 # if defined(__thumb2__)
|
|
202 pop\cond {\regs, lr}
|
|
203 # else
|
|
204 ldm\cond\dirn sp!, {\regs, lr}
|
|
205 # endif
|
|
206 .endif
|
|
207 .ifnc "\unwind", ""
|
|
208 /* Mark LR as restored. */
|
|
209 97: cfi_pop 97b - \unwind, 0xe, 0x0
|
|
210 .endif
|
|
211 bx\cond lr
|
|
212 #else
|
|
213 /* Caller is responsible for providing IT instruction. */
|
|
214 .ifc "\regs",""
|
|
215 ldr\cond pc, [sp], #8
|
|
216 .else
|
|
217 # if defined(__thumb2__)
|
|
218 pop\cond {\regs, pc}
|
|
219 # else
|
|
220 ldm\cond\dirn sp!, {\regs, pc}
|
|
221 # endif
|
|
222 .endif
|
|
223 #endif
|
|
224 .endm
|
|
225
|
|
226 /* The Unified assembly syntax allows the same code to be assembled for both
|
|
227 ARM and Thumb-2. However this is only supported by recent gas, so define
|
|
228 a set of macros to allow ARM code on older assemblers. */
|
|
229 #if defined(__thumb2__)
|
|
230 .macro do_it cond, suffix=""
|
|
231 it\suffix \cond
|
|
232 .endm
|
|
233 .macro shift1 op, arg0, arg1, arg2
|
|
234 \op \arg0, \arg1, \arg2
|
|
235 .endm
|
|
236 #define do_push push
|
|
237 #define do_pop pop
|
|
238 #define COND(op1, op2, cond) op1 ## op2 ## cond
|
|
239 /* Perform an arithmetic operation with a variable shift operand. This
|
|
240 requires two instructions and a scratch register on Thumb-2. */
|
|
241 .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
|
|
242 \shiftop \tmp, \src2, \shiftreg
|
|
243 \name \dest, \src1, \tmp
|
|
244 .endm
|
|
245 #else
|
|
246 .macro do_it cond, suffix=""
|
|
247 .endm
|
|
248 .macro shift1 op, arg0, arg1, arg2
|
|
249 mov \arg0, \arg1, \op \arg2
|
|
250 .endm
|
|
251 #define do_push stmfd sp!,
|
|
252 #define do_pop ldmfd sp!,
|
|
253 #define COND(op1, op2, cond) op1 ## cond ## op2
|
|
254 .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
|
|
255 \name \dest, \src1, \src2, \shiftop \shiftreg
|
|
256 .endm
|
|
257 #endif
|
|
258
|
|
259 .macro ARM_LDIV0 name
|
|
260 str lr, [sp, #-8]!
|
|
261 98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
|
|
262 bl SYM (__div0) __PLT__
|
|
263 mov r0, #0 @ About as wrong as it could be.
|
|
264 RETLDM unwind=98b
|
|
265 .endm
|
|
266
|
|
267
|
|
268 .macro THUMB_LDIV0 name
|
|
269 push { r1, lr }
|
|
270 98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
|
|
271 bl SYM (__div0)
|
|
272 mov r0, #0 @ About as wrong as it could be.
|
|
273 #if defined (__INTERWORKING__)
|
|
274 pop { r1, r2 }
|
|
275 bx r2
|
|
276 #else
|
|
277 pop { r1, pc }
|
|
278 #endif
|
|
279 .endm
|
|
280
|
|
281 .macro FUNC_END name
|
|
282 SIZE (__\name)
|
|
283 .endm
|
|
284
|
|
285 .macro DIV_FUNC_END name
|
|
286 cfi_start __\name, LSYM(Lend_div0)
|
|
287 LSYM(Ldiv0):
|
|
288 #ifdef __thumb__
|
|
289 THUMB_LDIV0 \name
|
|
290 #else
|
|
291 ARM_LDIV0 \name
|
|
292 #endif
|
|
293 cfi_end LSYM(Lend_div0)
|
|
294 FUNC_END \name
|
|
295 .endm
|
|
296
|
|
297 .macro THUMB_FUNC_START name
|
|
298 .globl SYM (\name)
|
|
299 TYPE (\name)
|
|
300 .thumb_func
|
|
301 SYM (\name):
|
|
302 .endm
|
|
303
|
|
304 /* Function start macros. Variants for ARM and Thumb. */
|
|
305
|
|
306 #ifdef __thumb__
|
|
307 #define THUMB_FUNC .thumb_func
|
|
308 #define THUMB_CODE .force_thumb
|
|
309 # if defined(__thumb2__)
|
|
310 #define THUMB_SYNTAX .syntax divided
|
|
311 # else
|
|
312 #define THUMB_SYNTAX
|
|
313 # endif
|
|
314 #else
|
|
315 #define THUMB_FUNC
|
|
316 #define THUMB_CODE
|
|
317 #define THUMB_SYNTAX
|
|
318 #endif
|
|
319
|
|
320 .macro FUNC_START name
|
|
321 .text
|
|
322 .globl SYM (__\name)
|
|
323 TYPE (__\name)
|
|
324 .align 0
|
|
325 THUMB_CODE
|
|
326 THUMB_FUNC
|
|
327 THUMB_SYNTAX
|
|
328 SYM (__\name):
|
|
329 .endm
|
|
330
|
|
331 /* Special function that will always be coded in ARM assembly, even if
|
|
332 in Thumb-only compilation. */
|
|
333
|
|
334 #if defined(__thumb2__)
|
|
335
|
|
336 /* For Thumb-2 we build everything in thumb mode. */
|
|
337 .macro ARM_FUNC_START name
|
|
338 FUNC_START \name
|
|
339 .syntax unified
|
|
340 .endm
|
|
341 #define EQUIV .thumb_set
|
|
342 .macro ARM_CALL name
|
|
343 bl __\name
|
|
344 .endm
|
|
345
|
|
346 #elif defined(__INTERWORKING_STUBS__)
|
|
347
|
|
348 .macro ARM_FUNC_START name
|
|
349 FUNC_START \name
|
|
350 bx pc
|
|
351 nop
|
|
352 .arm
|
|
353 /* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
|
354 directly from other local arm routines. */
|
|
355 _L__\name:
|
|
356 .endm
|
|
357 #define EQUIV .thumb_set
|
|
358 /* Branch directly to a function declared with ARM_FUNC_START.
|
|
359 Must be called in arm mode. */
|
|
360 .macro ARM_CALL name
|
|
361 bl _L__\name
|
|
362 .endm
|
|
363
|
|
364 #else /* !(__INTERWORKING_STUBS__ || __thumb2__) */
|
|
365
|
|
366 #ifdef __ARM_ARCH_6M__
|
|
367 #define EQUIV .thumb_set
|
|
368 #else
|
|
369 .macro ARM_FUNC_START name
|
|
370 .text
|
|
371 .globl SYM (__\name)
|
|
372 TYPE (__\name)
|
|
373 .align 0
|
|
374 .arm
|
|
375 SYM (__\name):
|
|
376 .endm
|
|
377 #define EQUIV .set
|
|
378 .macro ARM_CALL name
|
|
379 bl __\name
|
|
380 .endm
|
|
381 #endif
|
|
382
|
|
383 #endif
|
|
384
|
|
385 .macro FUNC_ALIAS new old
|
|
386 .globl SYM (__\new)
|
|
387 #if defined (__thumb__)
|
|
388 .thumb_set SYM (__\new), SYM (__\old)
|
|
389 #else
|
|
390 .set SYM (__\new), SYM (__\old)
|
|
391 #endif
|
|
392 .endm
|
|
393
|
|
394 #ifndef __ARM_ARCH_6M__
|
|
395 .macro ARM_FUNC_ALIAS new old
|
|
396 .globl SYM (__\new)
|
|
397 EQUIV SYM (__\new), SYM (__\old)
|
|
398 #if defined(__INTERWORKING_STUBS__)
|
|
399 .set SYM (_L__\new), SYM (_L__\old)
|
|
400 #endif
|
|
401 .endm
|
|
402 #endif
|
|
403
|
|
404 #ifdef __ARMEB__
|
|
405 #define xxh r0
|
|
406 #define xxl r1
|
|
407 #define yyh r2
|
|
408 #define yyl r3
|
|
409 #else
|
|
410 #define xxh r1
|
|
411 #define xxl r0
|
|
412 #define yyh r3
|
|
413 #define yyl r2
|
|
414 #endif
|
|
415
|
|
416 #ifdef __thumb__
|
|
417 /* Register aliases. */
|
|
418
|
|
419 work .req r4 @ XXXX is this safe ?
|
|
420 dividend .req r0
|
|
421 divisor .req r1
|
|
422 overdone .req r2
|
|
423 result .req r2
|
|
424 curbit .req r3
|
|
425 #endif
|
|
426 #if 0
|
|
427 ip .req r12
|
|
428 sp .req r13
|
|
429 lr .req r14
|
|
430 pc .req r15
|
|
431 #endif
|
|
432
|
|
433 /* ------------------------------------------------------------------------ */
|
|
434 /* Bodies of the division and modulo routines. */
|
|
435 /* ------------------------------------------------------------------------ */
|
|
436 .macro ARM_DIV_BODY dividend, divisor, result, curbit
|
|
437
|
|
438 #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
|
|
439
|
|
440 clz \curbit, \dividend
|
|
441 clz \result, \divisor
|
|
442 sub \curbit, \result, \curbit
|
|
443 rsbs \curbit, \curbit, #31
|
|
444 addne \curbit, \curbit, \curbit, lsl #1
|
|
445 mov \result, #0
|
|
446 addne pc, pc, \curbit, lsl #2
|
|
447 nop
|
|
448 .set shift, 32
|
|
449 .rept 32
|
|
450 .set shift, shift - 1
|
|
451 cmp \dividend, \divisor, lsl #shift
|
|
452 adc \result, \result, \result
|
|
453 subcs \dividend, \dividend, \divisor, lsl #shift
|
|
454 .endr
|
|
455
|
|
456 #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
|
|
457 #if __ARM_ARCH__ >= 5
|
|
458
|
|
459 clz \curbit, \divisor
|
|
460 clz \result, \dividend
|
|
461 sub \result, \curbit, \result
|
|
462 mov \curbit, #1
|
|
463 mov \divisor, \divisor, lsl \result
|
|
464 mov \curbit, \curbit, lsl \result
|
|
465 mov \result, #0
|
|
466
|
|
467 #else /* __ARM_ARCH__ < 5 */
|
|
468
|
|
469 @ Initially shift the divisor left 3 bits if possible,
|
|
470 @ set curbit accordingly. This allows for curbit to be located
|
|
471 @ at the left end of each 4-bit nibbles in the division loop
|
|
472 @ to save one loop in most cases.
|
|
473 tst \divisor, #0xe0000000
|
|
474 moveq \divisor, \divisor, lsl #3
|
|
475 moveq \curbit, #8
|
|
476 movne \curbit, #1
|
|
477
|
|
478 @ Unless the divisor is very big, shift it up in multiples of
|
|
479 @ four bits, since this is the amount of unwinding in the main
|
|
480 @ division loop. Continue shifting until the divisor is
|
|
481 @ larger than the dividend.
|
|
482 1: cmp \divisor, #0x10000000
|
|
483 cmplo \divisor, \dividend
|
|
484 movlo \divisor, \divisor, lsl #4
|
|
485 movlo \curbit, \curbit, lsl #4
|
|
486 blo 1b
|
|
487
|
|
488 @ For very big divisors, we must shift it a bit at a time, or
|
|
489 @ we will be in danger of overflowing.
|
|
490 1: cmp \divisor, #0x80000000
|
|
491 cmplo \divisor, \dividend
|
|
492 movlo \divisor, \divisor, lsl #1
|
|
493 movlo \curbit, \curbit, lsl #1
|
|
494 blo 1b
|
|
495
|
|
496 mov \result, #0
|
|
497
|
|
498 #endif /* __ARM_ARCH__ < 5 */
|
|
499
|
|
500 @ Division loop
|
|
501 1: cmp \dividend, \divisor
|
|
502 subhs \dividend, \dividend, \divisor
|
|
503 orrhs \result, \result, \curbit
|
|
504 cmp \dividend, \divisor, lsr #1
|
|
505 subhs \dividend, \dividend, \divisor, lsr #1
|
|
506 orrhs \result, \result, \curbit, lsr #1
|
|
507 cmp \dividend, \divisor, lsr #2
|
|
508 subhs \dividend, \dividend, \divisor, lsr #2
|
|
509 orrhs \result, \result, \curbit, lsr #2
|
|
510 cmp \dividend, \divisor, lsr #3
|
|
511 subhs \dividend, \dividend, \divisor, lsr #3
|
|
512 orrhs \result, \result, \curbit, lsr #3
|
|
513 cmp \dividend, #0 @ Early termination?
|
|
514 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
|
|
515 movne \divisor, \divisor, lsr #4
|
|
516 bne 1b
|
|
517
|
|
518 #endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
|
|
519
|
|
520 .endm
|
|
521 /* ------------------------------------------------------------------------ */
|
|
522 .macro ARM_DIV2_ORDER divisor, order
|
|
523
|
|
524 #if __ARM_ARCH__ >= 5
|
|
525
|
|
526 clz \order, \divisor
|
|
527 rsb \order, \order, #31
|
|
528
|
|
529 #else
|
|
530
|
|
531 cmp \divisor, #(1 << 16)
|
|
532 movhs \divisor, \divisor, lsr #16
|
|
533 movhs \order, #16
|
|
534 movlo \order, #0
|
|
535
|
|
536 cmp \divisor, #(1 << 8)
|
|
537 movhs \divisor, \divisor, lsr #8
|
|
538 addhs \order, \order, #8
|
|
539
|
|
540 cmp \divisor, #(1 << 4)
|
|
541 movhs \divisor, \divisor, lsr #4
|
|
542 addhs \order, \order, #4
|
|
543
|
|
544 cmp \divisor, #(1 << 2)
|
|
545 addhi \order, \order, #3
|
|
546 addls \order, \order, \divisor, lsr #1
|
|
547
|
|
548 #endif
|
|
549
|
|
550 .endm
|
|
551 /* ------------------------------------------------------------------------ */
|
|
552 .macro ARM_MOD_BODY dividend, divisor, order, spare
|
|
553
|
|
554 #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
|
|
555
|
|
556 clz \order, \divisor
|
|
557 clz \spare, \dividend
|
|
558 sub \order, \order, \spare
|
|
559 rsbs \order, \order, #31
|
|
560 addne pc, pc, \order, lsl #3
|
|
561 nop
|
|
562 .set shift, 32
|
|
563 .rept 32
|
|
564 .set shift, shift - 1
|
|
565 cmp \dividend, \divisor, lsl #shift
|
|
566 subcs \dividend, \dividend, \divisor, lsl #shift
|
|
567 .endr
|
|
568
|
|
569 #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
|
|
570 #if __ARM_ARCH__ >= 5
|
|
571
|
|
572 clz \order, \divisor
|
|
573 clz \spare, \dividend
|
|
574 sub \order, \order, \spare
|
|
575 mov \divisor, \divisor, lsl \order
|
|
576
|
|
577 #else /* __ARM_ARCH__ < 5 */
|
|
578
|
|
579 mov \order, #0
|
|
580
|
|
581 @ Unless the divisor is very big, shift it up in multiples of
|
|
582 @ four bits, since this is the amount of unwinding in the main
|
|
583 @ division loop. Continue shifting until the divisor is
|
|
584 @ larger than the dividend.
|
|
585 1: cmp \divisor, #0x10000000
|
|
586 cmplo \divisor, \dividend
|
|
587 movlo \divisor, \divisor, lsl #4
|
|
588 addlo \order, \order, #4
|
|
589 blo 1b
|
|
590
|
|
591 @ For very big divisors, we must shift it a bit at a time, or
|
|
592 @ we will be in danger of overflowing.
|
|
593 1: cmp \divisor, #0x80000000
|
|
594 cmplo \divisor, \dividend
|
|
595 movlo \divisor, \divisor, lsl #1
|
|
596 addlo \order, \order, #1
|
|
597 blo 1b
|
|
598
|
|
599 #endif /* __ARM_ARCH__ < 5 */
|
|
600
|
|
601 @ Perform all needed substractions to keep only the reminder.
|
|
602 @ Do comparisons in batch of 4 first.
|
|
603 subs \order, \order, #3 @ yes, 3 is intended here
|
|
604 blt 2f
|
|
605
|
|
606 1: cmp \dividend, \divisor
|
|
607 subhs \dividend, \dividend, \divisor
|
|
608 cmp \dividend, \divisor, lsr #1
|
|
609 subhs \dividend, \dividend, \divisor, lsr #1
|
|
610 cmp \dividend, \divisor, lsr #2
|
|
611 subhs \dividend, \dividend, \divisor, lsr #2
|
|
612 cmp \dividend, \divisor, lsr #3
|
|
613 subhs \dividend, \dividend, \divisor, lsr #3
|
|
614 cmp \dividend, #1
|
|
615 mov \divisor, \divisor, lsr #4
|
|
616 subges \order, \order, #4
|
|
617 bge 1b
|
|
618
|
|
619 tst \order, #3
|
|
620 teqne \dividend, #0
|
|
621 beq 5f
|
|
622
|
|
623 @ Either 1, 2 or 3 comparison/substractions are left.
|
|
624 2: cmn \order, #2
|
|
625 blt 4f
|
|
626 beq 3f
|
|
627 cmp \dividend, \divisor
|
|
628 subhs \dividend, \dividend, \divisor
|
|
629 mov \divisor, \divisor, lsr #1
|
|
630 3: cmp \dividend, \divisor
|
|
631 subhs \dividend, \dividend, \divisor
|
|
632 mov \divisor, \divisor, lsr #1
|
|
633 4: cmp \dividend, \divisor
|
|
634 subhs \dividend, \dividend, \divisor
|
|
635 5:
|
|
636
|
|
637 #endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
|
|
638
|
|
639 .endm
|
|
640 /* ------------------------------------------------------------------------ */
|
|
641 .macro THUMB_DIV_MOD_BODY modulo
|
|
642 @ Load the constant 0x10000000 into our work register.
|
|
643 mov work, #1
|
|
644 lsl work, #28
|
|
645 LSYM(Loop1):
|
|
646 @ Unless the divisor is very big, shift it up in multiples of
|
|
647 @ four bits, since this is the amount of unwinding in the main
|
|
648 @ division loop. Continue shifting until the divisor is
|
|
649 @ larger than the dividend.
|
|
650 cmp divisor, work
|
|
651 bhs LSYM(Lbignum)
|
|
652 cmp divisor, dividend
|
|
653 bhs LSYM(Lbignum)
|
|
654 lsl divisor, #4
|
|
655 lsl curbit, #4
|
|
656 b LSYM(Loop1)
|
|
657 LSYM(Lbignum):
|
|
658 @ Set work to 0x80000000
|
|
659 lsl work, #3
|
|
660 LSYM(Loop2):
|
|
661 @ For very big divisors, we must shift it a bit at a time, or
|
|
662 @ we will be in danger of overflowing.
|
|
663 cmp divisor, work
|
|
664 bhs LSYM(Loop3)
|
|
665 cmp divisor, dividend
|
|
666 bhs LSYM(Loop3)
|
|
667 lsl divisor, #1
|
|
668 lsl curbit, #1
|
|
669 b LSYM(Loop2)
|
|
670 LSYM(Loop3):
|
|
671 @ Test for possible subtractions ...
|
|
672 .if \modulo
|
|
673 @ ... On the final pass, this may subtract too much from the dividend,
|
|
674 @ so keep track of which subtractions are done, we can fix them up
|
|
675 @ afterwards.
|
|
676 mov overdone, #0
|
|
677 cmp dividend, divisor
|
|
678 blo LSYM(Lover1)
|
|
679 sub dividend, dividend, divisor
|
|
680 LSYM(Lover1):
|
|
681 lsr work, divisor, #1
|
|
682 cmp dividend, work
|
|
683 blo LSYM(Lover2)
|
|
684 sub dividend, dividend, work
|
|
685 mov ip, curbit
|
|
686 mov work, #1
|
|
687 ror curbit, work
|
|
688 orr overdone, curbit
|
|
689 mov curbit, ip
|
|
690 LSYM(Lover2):
|
|
691 lsr work, divisor, #2
|
|
692 cmp dividend, work
|
|
693 blo LSYM(Lover3)
|
|
694 sub dividend, dividend, work
|
|
695 mov ip, curbit
|
|
696 mov work, #2
|
|
697 ror curbit, work
|
|
698 orr overdone, curbit
|
|
699 mov curbit, ip
|
|
700 LSYM(Lover3):
|
|
701 lsr work, divisor, #3
|
|
702 cmp dividend, work
|
|
703 blo LSYM(Lover4)
|
|
704 sub dividend, dividend, work
|
|
705 mov ip, curbit
|
|
706 mov work, #3
|
|
707 ror curbit, work
|
|
708 orr overdone, curbit
|
|
709 mov curbit, ip
|
|
710 LSYM(Lover4):
|
|
711 mov ip, curbit
|
|
712 .else
|
|
713 @ ... and note which bits are done in the result. On the final pass,
|
|
714 @ this may subtract too much from the dividend, but the result will be ok,
|
|
715 @ since the "bit" will have been shifted out at the bottom.
|
|
716 cmp dividend, divisor
|
|
717 blo LSYM(Lover1)
|
|
718 sub dividend, dividend, divisor
|
|
719 orr result, result, curbit
|
|
720 LSYM(Lover1):
|
|
721 lsr work, divisor, #1
|
|
722 cmp dividend, work
|
|
723 blo LSYM(Lover2)
|
|
724 sub dividend, dividend, work
|
|
725 lsr work, curbit, #1
|
|
726 orr result, work
|
|
727 LSYM(Lover2):
|
|
728 lsr work, divisor, #2
|
|
729 cmp dividend, work
|
|
730 blo LSYM(Lover3)
|
|
731 sub dividend, dividend, work
|
|
732 lsr work, curbit, #2
|
|
733 orr result, work
|
|
734 LSYM(Lover3):
|
|
735 lsr work, divisor, #3
|
|
736 cmp dividend, work
|
|
737 blo LSYM(Lover4)
|
|
738 sub dividend, dividend, work
|
|
739 lsr work, curbit, #3
|
|
740 orr result, work
|
|
741 LSYM(Lover4):
|
|
742 .endif
|
|
743
|
|
744 cmp dividend, #0 @ Early termination?
|
|
745 beq LSYM(Lover5)
|
|
746 lsr curbit, #4 @ No, any more bits to do?
|
|
747 beq LSYM(Lover5)
|
|
748 lsr divisor, #4
|
|
749 b LSYM(Loop3)
|
|
750 LSYM(Lover5):
|
|
751 .if \modulo
|
|
752 @ Any subtractions that we should not have done will be recorded in
|
|
753 @ the top three bits of "overdone". Exactly which were not needed
|
|
754 @ are governed by the position of the bit, stored in ip.
|
|
755 mov work, #0xe
|
|
756 lsl work, #28
|
|
757 and overdone, work
|
|
758 beq LSYM(Lgot_result)
|
|
759
|
|
760 @ If we terminated early, because dividend became zero, then the
|
|
761 @ bit in ip will not be in the bottom nibble, and we should not
|
|
762 @ perform the additions below. We must test for this though
|
|
763 @ (rather relying upon the TSTs to prevent the additions) since
|
|
764 @ the bit in ip could be in the top two bits which might then match
|
|
765 @ with one of the smaller RORs.
|
|
766 mov curbit, ip
|
|
767 mov work, #0x7
|
|
768 tst curbit, work
|
|
769 beq LSYM(Lgot_result)
|
|
770
|
|
771 mov curbit, ip
|
|
772 mov work, #3
|
|
773 ror curbit, work
|
|
774 tst overdone, curbit
|
|
775 beq LSYM(Lover6)
|
|
776 lsr work, divisor, #3
|
|
777 add dividend, work
|
|
778 LSYM(Lover6):
|
|
779 mov curbit, ip
|
|
780 mov work, #2
|
|
781 ror curbit, work
|
|
782 tst overdone, curbit
|
|
783 beq LSYM(Lover7)
|
|
784 lsr work, divisor, #2
|
|
785 add dividend, work
|
|
786 LSYM(Lover7):
|
|
787 mov curbit, ip
|
|
788 mov work, #1
|
|
789 ror curbit, work
|
|
790 tst overdone, curbit
|
|
791 beq LSYM(Lgot_result)
|
|
792 lsr work, divisor, #1
|
|
793 add dividend, work
|
|
794 .endif
|
|
795 LSYM(Lgot_result):
|
|
796 .endm
|
|
797 /* ------------------------------------------------------------------------ */
|
|
798 /* Start of the Real Functions */
|
|
799 /* ------------------------------------------------------------------------ */
|
|
800 #ifdef L_udivsi3
|
|
801
|
|
802 FUNC_START udivsi3
|
|
803 FUNC_ALIAS aeabi_uidiv udivsi3
|
|
804
|
|
805 #ifdef __thumb__
|
|
806
|
|
807 cmp divisor, #0
|
|
808 beq LSYM(Ldiv0)
|
|
809 mov curbit, #1
|
|
810 mov result, #0
|
|
811
|
|
812 push { work }
|
|
813 cmp dividend, divisor
|
|
814 blo LSYM(Lgot_result)
|
|
815
|
|
816 THUMB_DIV_MOD_BODY 0
|
|
817
|
|
818 mov r0, result
|
|
819 pop { work }
|
|
820 RET
|
|
821
|
|
822 #else /* ARM version. */
|
|
823
|
|
824 subs r2, r1, #1
|
|
825 RETc(eq)
|
|
826 bcc LSYM(Ldiv0)
|
|
827 cmp r0, r1
|
|
828 bls 11f
|
|
829 tst r1, r2
|
|
830 beq 12f
|
|
831
|
|
832 ARM_DIV_BODY r0, r1, r2, r3
|
|
833
|
|
834 mov r0, r2
|
|
835 RET
|
|
836
|
|
837 11: moveq r0, #1
|
|
838 movne r0, #0
|
|
839 RET
|
|
840
|
|
841 12: ARM_DIV2_ORDER r1, r2
|
|
842
|
|
843 mov r0, r0, lsr r2
|
|
844 RET
|
|
845
|
|
846 #endif /* ARM version */
|
|
847
|
|
848 DIV_FUNC_END udivsi3
|
|
849
|
|
850 FUNC_START aeabi_uidivmod
|
|
851 #ifdef __thumb__
|
|
852 push {r0, r1, lr}
|
|
853 bl SYM(__udivsi3)
|
|
854 POP {r1, r2, r3}
|
|
855 mul r2, r0
|
|
856 sub r1, r1, r2
|
|
857 bx r3
|
|
858 #else
|
|
859 stmfd sp!, { r0, r1, lr }
|
|
860 bl SYM(__udivsi3)
|
|
861 ldmfd sp!, { r1, r2, lr }
|
|
862 mul r3, r2, r0
|
|
863 sub r1, r1, r3
|
|
864 RET
|
|
865 #endif
|
|
866 FUNC_END aeabi_uidivmod
|
|
867
|
|
868 #endif /* L_udivsi3 */
|
|
869 /* ------------------------------------------------------------------------ */
|
|
870 #ifdef L_umodsi3
|
|
871
|
|
872 FUNC_START umodsi3
|
|
873
|
|
874 #ifdef __thumb__
|
|
875
|
|
876 cmp divisor, #0
|
|
877 beq LSYM(Ldiv0)
|
|
878 mov curbit, #1
|
|
879 cmp dividend, divisor
|
|
880 bhs LSYM(Lover10)
|
|
881 RET
|
|
882
|
|
883 LSYM(Lover10):
|
|
884 push { work }
|
|
885
|
|
886 THUMB_DIV_MOD_BODY 1
|
|
887
|
|
888 pop { work }
|
|
889 RET
|
|
890
|
|
891 #else /* ARM version. */
|
|
892
|
|
893 subs r2, r1, #1 @ compare divisor with 1
|
|
894 bcc LSYM(Ldiv0)
|
|
895 cmpne r0, r1 @ compare dividend with divisor
|
|
896 moveq r0, #0
|
|
897 tsthi r1, r2 @ see if divisor is power of 2
|
|
898 andeq r0, r0, r2
|
|
899 RETc(ls)
|
|
900
|
|
901 ARM_MOD_BODY r0, r1, r2, r3
|
|
902
|
|
903 RET
|
|
904
|
|
905 #endif /* ARM version. */
|
|
906
|
|
907 DIV_FUNC_END umodsi3
|
|
908
|
|
909 #endif /* L_umodsi3 */
|
|
910 /* ------------------------------------------------------------------------ */
|
|
911 #ifdef L_divsi3
|
|
912
|
|
913 FUNC_START divsi3
|
|
914 FUNC_ALIAS aeabi_idiv divsi3
|
|
915
|
|
916 #ifdef __thumb__
|
|
917 cmp divisor, #0
|
|
918 beq LSYM(Ldiv0)
|
|
919
|
|
920 push { work }
|
|
921 mov work, dividend
|
|
922 eor work, divisor @ Save the sign of the result.
|
|
923 mov ip, work
|
|
924 mov curbit, #1
|
|
925 mov result, #0
|
|
926 cmp divisor, #0
|
|
927 bpl LSYM(Lover10)
|
|
928 neg divisor, divisor @ Loops below use unsigned.
|
|
929 LSYM(Lover10):
|
|
930 cmp dividend, #0
|
|
931 bpl LSYM(Lover11)
|
|
932 neg dividend, dividend
|
|
933 LSYM(Lover11):
|
|
934 cmp dividend, divisor
|
|
935 blo LSYM(Lgot_result)
|
|
936
|
|
937 THUMB_DIV_MOD_BODY 0
|
|
938
|
|
939 mov r0, result
|
|
940 mov work, ip
|
|
941 cmp work, #0
|
|
942 bpl LSYM(Lover12)
|
|
943 neg r0, r0
|
|
944 LSYM(Lover12):
|
|
945 pop { work }
|
|
946 RET
|
|
947
|
|
948 #else /* ARM version. */
|
|
949
|
|
950 cmp r1, #0
|
|
951 eor ip, r0, r1 @ save the sign of the result.
|
|
952 beq LSYM(Ldiv0)
|
|
953 rsbmi r1, r1, #0 @ loops below use unsigned.
|
|
954 subs r2, r1, #1 @ division by 1 or -1 ?
|
|
955 beq 10f
|
|
956 movs r3, r0
|
|
957 rsbmi r3, r0, #0 @ positive dividend value
|
|
958 cmp r3, r1
|
|
959 bls 11f
|
|
960 tst r1, r2 @ divisor is power of 2 ?
|
|
961 beq 12f
|
|
962
|
|
963 ARM_DIV_BODY r3, r1, r0, r2
|
|
964
|
|
965 cmp ip, #0
|
|
966 rsbmi r0, r0, #0
|
|
967 RET
|
|
968
|
|
969 10: teq ip, r0 @ same sign ?
|
|
970 rsbmi r0, r0, #0
|
|
971 RET
|
|
972
|
|
973 11: movlo r0, #0
|
|
974 moveq r0, ip, asr #31
|
|
975 orreq r0, r0, #1
|
|
976 RET
|
|
977
|
|
978 12: ARM_DIV2_ORDER r1, r2
|
|
979
|
|
980 cmp ip, #0
|
|
981 mov r0, r3, lsr r2
|
|
982 rsbmi r0, r0, #0
|
|
983 RET
|
|
984
|
|
985 #endif /* ARM version */
|
|
986
|
|
987 DIV_FUNC_END divsi3
|
|
988
|
|
989 FUNC_START aeabi_idivmod
|
|
990 #ifdef __thumb__
|
|
991 push {r0, r1, lr}
|
|
992 bl SYM(__divsi3)
|
|
993 POP {r1, r2, r3}
|
|
994 mul r2, r0
|
|
995 sub r1, r1, r2
|
|
996 bx r3
|
|
997 #else
|
|
998 stmfd sp!, { r0, r1, lr }
|
|
999 bl SYM(__divsi3)
|
|
1000 ldmfd sp!, { r1, r2, lr }
|
|
1001 mul r3, r2, r0
|
|
1002 sub r1, r1, r3
|
|
1003 RET
|
|
1004 #endif
|
|
1005 FUNC_END aeabi_idivmod
|
|
1006
|
|
1007 #endif /* L_divsi3 */
|
|
1008 /* ------------------------------------------------------------------------ */
|
|
1009 #ifdef L_modsi3
|
|
1010
|
|
1011 FUNC_START modsi3
|
|
1012
|
|
1013 #ifdef __thumb__
|
|
1014
|
|
1015 mov curbit, #1
|
|
1016 cmp divisor, #0
|
|
1017 beq LSYM(Ldiv0)
|
|
1018 bpl LSYM(Lover10)
|
|
1019 neg divisor, divisor @ Loops below use unsigned.
|
|
1020 LSYM(Lover10):
|
|
1021 push { work }
|
|
1022 @ Need to save the sign of the dividend, unfortunately, we need
|
|
1023 @ work later on. Must do this after saving the original value of
|
|
1024 @ the work register, because we will pop this value off first.
|
|
1025 push { dividend }
|
|
1026 cmp dividend, #0
|
|
1027 bpl LSYM(Lover11)
|
|
1028 neg dividend, dividend
|
|
1029 LSYM(Lover11):
|
|
1030 cmp dividend, divisor
|
|
1031 blo LSYM(Lgot_result)
|
|
1032
|
|
1033 THUMB_DIV_MOD_BODY 1
|
|
1034
|
|
1035 pop { work }
|
|
1036 cmp work, #0
|
|
1037 bpl LSYM(Lover12)
|
|
1038 neg dividend, dividend
|
|
1039 LSYM(Lover12):
|
|
1040 pop { work }
|
|
1041 RET
|
|
1042
|
|
1043 #else /* ARM version. */
|
|
1044
|
|
1045 cmp r1, #0
|
|
1046 beq LSYM(Ldiv0)
|
|
1047 rsbmi r1, r1, #0 @ loops below use unsigned.
|
|
1048 movs ip, r0 @ preserve sign of dividend
|
|
1049 rsbmi r0, r0, #0 @ if negative make positive
|
|
1050 subs r2, r1, #1 @ compare divisor with 1
|
|
1051 cmpne r0, r1 @ compare dividend with divisor
|
|
1052 moveq r0, #0
|
|
1053 tsthi r1, r2 @ see if divisor is power of 2
|
|
1054 andeq r0, r0, r2
|
|
1055 bls 10f
|
|
1056
|
|
1057 ARM_MOD_BODY r0, r1, r2, r3
|
|
1058
|
|
1059 10: cmp ip, #0
|
|
1060 rsbmi r0, r0, #0
|
|
1061 RET
|
|
1062
|
|
1063 #endif /* ARM version */
|
|
1064
|
|
1065 DIV_FUNC_END modsi3
|
|
1066
|
|
1067 #endif /* L_modsi3 */
|
|
1068 /* ------------------------------------------------------------------------ */
|
|
1069 #ifdef L_dvmd_tls
|
|
1070
|
|
1071 FUNC_START div0
|
|
1072 FUNC_ALIAS aeabi_idiv0 div0
|
|
1073 FUNC_ALIAS aeabi_ldiv0 div0
|
|
1074
|
|
1075 RET
|
|
1076
|
|
1077 FUNC_END aeabi_ldiv0
|
|
1078 FUNC_END aeabi_idiv0
|
|
1079 FUNC_END div0
|
|
1080
|
|
1081 #endif /* L_divmodsi_tools */
|
|
1082 /* ------------------------------------------------------------------------ */
|
|
1083 #ifdef L_dvmd_lnx
|
|
1084 @ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
|
|
1085
|
|
1086 /* Constant taken from <asm/signal.h>. */
|
|
1087 #define SIGFPE 8
|
|
1088
|
|
1089 ARM_FUNC_START div0
|
|
1090
|
|
1091 do_push {r1, lr}
|
|
1092 mov r0, #SIGFPE
|
|
1093 bl SYM(raise) __PLT__
|
|
1094 RETLDM r1
|
|
1095
|
|
1096 FUNC_END div0
|
|
1097
|
|
1098 #endif /* L_dvmd_lnx */
|
|
1099 /* ------------------------------------------------------------------------ */
|
|
1100 /* Dword shift operations. */
|
|
1101 /* All the following Dword shift variants rely on the fact that
|
|
1102 shft xxx, Reg
|
|
1103 is in fact done as
|
|
1104 shft xxx, (Reg & 255)
|
|
1105 so for Reg value in (32...63) and (-1...-31) we will get zero (in the
|
|
1106 case of logical shifts) or the sign (for asr). */
|
|
1107
|
|
1108 #ifdef __ARMEB__
|
|
1109 #define al r1
|
|
1110 #define ah r0
|
|
1111 #else
|
|
1112 #define al r0
|
|
1113 #define ah r1
|
|
1114 #endif
|
|
1115
|
|
1116 /* Prevent __aeabi double-word shifts from being produced on SymbianOS. */
|
|
1117 #ifndef __symbian__
|
|
1118
|
|
1119 #ifdef L_lshrdi3
|
|
1120
|
|
1121 FUNC_START lshrdi3
|
|
1122 FUNC_ALIAS aeabi_llsr lshrdi3
|
|
1123
|
|
1124 #ifdef __thumb__
|
|
1125 lsr al, r2
|
|
1126 mov r3, ah
|
|
1127 lsr ah, r2
|
|
1128 mov ip, r3
|
|
1129 sub r2, #32
|
|
1130 lsr r3, r2
|
|
1131 orr al, r3
|
|
1132 neg r2, r2
|
|
1133 mov r3, ip
|
|
1134 lsl r3, r2
|
|
1135 orr al, r3
|
|
1136 RET
|
|
1137 #else
|
|
1138 subs r3, r2, #32
|
|
1139 rsb ip, r2, #32
|
|
1140 movmi al, al, lsr r2
|
|
1141 movpl al, ah, lsr r3
|
|
1142 orrmi al, al, ah, lsl ip
|
|
1143 mov ah, ah, lsr r2
|
|
1144 RET
|
|
1145 #endif
|
|
1146 FUNC_END aeabi_llsr
|
|
1147 FUNC_END lshrdi3
|
|
1148
|
|
1149 #endif
|
|
1150
|
|
1151 #ifdef L_ashrdi3
|
|
1152
|
|
1153 FUNC_START ashrdi3
|
|
1154 FUNC_ALIAS aeabi_lasr ashrdi3
|
|
1155
|
|
1156 #ifdef __thumb__
|
|
1157 lsr al, r2
|
|
1158 mov r3, ah
|
|
1159 asr ah, r2
|
|
1160 sub r2, #32
|
|
1161 @ If r2 is negative at this point the following step would OR
|
|
1162 @ the sign bit into all of AL. That's not what we want...
|
|
1163 bmi 1f
|
|
1164 mov ip, r3
|
|
1165 asr r3, r2
|
|
1166 orr al, r3
|
|
1167 mov r3, ip
|
|
1168 1:
|
|
1169 neg r2, r2
|
|
1170 lsl r3, r2
|
|
1171 orr al, r3
|
|
1172 RET
|
|
1173 #else
|
|
1174 subs r3, r2, #32
|
|
1175 rsb ip, r2, #32
|
|
1176 movmi al, al, lsr r2
|
|
1177 movpl al, ah, asr r3
|
|
1178 orrmi al, al, ah, lsl ip
|
|
1179 mov ah, ah, asr r2
|
|
1180 RET
|
|
1181 #endif
|
|
1182
|
|
1183 FUNC_END aeabi_lasr
|
|
1184 FUNC_END ashrdi3
|
|
1185
|
|
1186 #endif
|
|
1187
|
|
1188 #ifdef L_ashldi3
|
|
1189
|
|
1190 FUNC_START ashldi3
|
|
1191 FUNC_ALIAS aeabi_llsl ashldi3
|
|
1192
|
|
1193 #ifdef __thumb__
|
|
1194 lsl ah, r2
|
|
1195 mov r3, al
|
|
1196 lsl al, r2
|
|
1197 mov ip, r3
|
|
1198 sub r2, #32
|
|
1199 lsl r3, r2
|
|
1200 orr ah, r3
|
|
1201 neg r2, r2
|
|
1202 mov r3, ip
|
|
1203 lsr r3, r2
|
|
1204 orr ah, r3
|
|
1205 RET
|
|
1206 #else
|
|
1207 subs r3, r2, #32
|
|
1208 rsb ip, r2, #32
|
|
1209 movmi ah, ah, lsl r2
|
|
1210 movpl ah, al, lsl r3
|
|
1211 orrmi ah, ah, al, lsr ip
|
|
1212 mov al, al, lsl r2
|
|
1213 RET
|
|
1214 #endif
|
|
1215 FUNC_END aeabi_llsl
|
|
1216 FUNC_END ashldi3
|
|
1217
|
|
1218 #endif
|
|
1219
|
|
1220 #endif /* __symbian__ */
|
|
1221
|
|
1222 #if ((__ARM_ARCH__ > 5) && !defined(__ARM_ARCH_6M__)) \
|
|
1223 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
|
1224 || defined(__ARM_ARCH_5TEJ__)
|
|
1225 #define HAVE_ARM_CLZ 1
|
|
1226 #endif
|
|
1227
|
|
1228 #ifdef L_clzsi2
|
|
1229 #if defined(__ARM_ARCH_6M__)
|
|
1230 FUNC_START clzsi2
|
|
1231 mov r1, #28
|
|
1232 mov r3, #1
|
|
1233 lsl r3, r3, #16
|
|
1234 cmp r0, r3 /* 0x10000 */
|
|
1235 bcc 2f
|
|
1236 lsr r0, r0, #16
|
|
1237 sub r1, r1, #16
|
|
1238 2: lsr r3, r3, #8
|
|
1239 cmp r0, r3 /* #0x100 */
|
|
1240 bcc 2f
|
|
1241 lsr r0, r0, #8
|
|
1242 sub r1, r1, #8
|
|
1243 2: lsr r3, r3, #4
|
|
1244 cmp r0, r3 /* #0x10 */
|
|
1245 bcc 2f
|
|
1246 lsr r0, r0, #4
|
|
1247 sub r1, r1, #4
|
|
1248 2: adr r2, 1f
|
|
1249 ldrb r0, [r2, r0]
|
|
1250 add r0, r0, r1
|
|
1251 bx lr
|
|
1252 .align 2
|
|
1253 1:
|
|
1254 .byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
|
|
1255 FUNC_END clzsi2
|
|
1256 #else
|
|
1257 ARM_FUNC_START clzsi2
|
|
1258 # if defined(HAVE_ARM_CLZ)
|
|
1259 clz r0, r0
|
|
1260 RET
|
|
1261 # else
|
|
1262 mov r1, #28
|
|
1263 cmp r0, #0x10000
|
|
1264 do_it cs, t
|
|
1265 movcs r0, r0, lsr #16
|
|
1266 subcs r1, r1, #16
|
|
1267 cmp r0, #0x100
|
|
1268 do_it cs, t
|
|
1269 movcs r0, r0, lsr #8
|
|
1270 subcs r1, r1, #8
|
|
1271 cmp r0, #0x10
|
|
1272 do_it cs, t
|
|
1273 movcs r0, r0, lsr #4
|
|
1274 subcs r1, r1, #4
|
|
1275 adr r2, 1f
|
|
1276 ldrb r0, [r2, r0]
|
|
1277 add r0, r0, r1
|
|
1278 RET
|
|
1279 .align 2
|
|
1280 1:
|
|
1281 .byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
|
|
1282 # endif /* !HAVE_ARM_CLZ */
|
|
1283 FUNC_END clzsi2
|
|
1284 #endif
|
|
1285 #endif /* L_clzsi2 */
|
|
1286
|
|
1287 #ifdef L_clzdi2
|
|
1288 #if !defined(HAVE_ARM_CLZ)
|
|
1289
|
|
1290 # if defined(__ARM_ARCH_6M__)
|
|
1291 FUNC_START clzdi2
|
|
1292 push {r4, lr}
|
|
1293 # else
|
|
1294 ARM_FUNC_START clzdi2
|
|
1295 do_push {r4, lr}
|
|
1296 # endif
|
|
1297 cmp xxh, #0
|
|
1298 bne 1f
|
|
1299 # ifdef __ARMEB__
|
|
1300 mov r0, xxl
|
|
1301 bl __clzsi2
|
|
1302 add r0, r0, #32
|
|
1303 b 2f
|
|
1304 1:
|
|
1305 bl __clzsi2
|
|
1306 # else
|
|
1307 bl __clzsi2
|
|
1308 add r0, r0, #32
|
|
1309 b 2f
|
|
1310 1:
|
|
1311 mov r0, xxh
|
|
1312 bl __clzsi2
|
|
1313 # endif
|
|
1314 2:
|
|
1315 # if defined(__ARM_ARCH_6M__)
|
|
1316 pop {r4, pc}
|
|
1317 # else
|
|
1318 RETLDM r4
|
|
1319 # endif
|
|
1320 FUNC_END clzdi2
|
|
1321
|
|
1322 #else /* HAVE_ARM_CLZ */
|
|
1323
|
|
1324 ARM_FUNC_START clzdi2
|
|
1325 cmp xxh, #0
|
|
1326 do_it eq, et
|
|
1327 clzeq r0, xxl
|
|
1328 clzne r0, xxh
|
|
1329 addeq r0, r0, #32
|
|
1330 RET
|
|
1331 FUNC_END clzdi2
|
|
1332
|
|
1333 #endif
|
|
1334 #endif /* L_clzdi2 */
|
|
1335
|
|
1336 /* ------------------------------------------------------------------------ */
|
|
1337 /* These next two sections are here despite the fact that they contain Thumb
|
|
1338 assembler because their presence allows interworked code to be linked even
|
|
1339 when the GCC library is this one. */
|
|
1340
|
|
1341 /* Do not build the interworking functions when the target architecture does
|
|
1342 not support Thumb instructions. (This can be a multilib option). */
|
|
1343 #if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
|
|
1344 || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
|
|
1345 || __ARM_ARCH__ >= 6
|
|
1346
|
|
1347 #if defined L_call_via_rX
|
|
1348
|
|
1349 /* These labels & instructions are used by the Arm/Thumb interworking code.
|
|
1350 The address of function to be called is loaded into a register and then
|
|
1351 one of these labels is called via a BL instruction. This puts the
|
|
1352 return address into the link register with the bottom bit set, and the
|
|
1353 code here switches to the correct mode before executing the function. */
|
|
1354
|
|
1355 .text
|
|
1356 .align 0
|
|
1357 .force_thumb
|
|
1358
|
|
1359 .macro call_via register
|
|
1360 THUMB_FUNC_START _call_via_\register
|
|
1361
|
|
1362 bx \register
|
|
1363 nop
|
|
1364
|
|
1365 SIZE (_call_via_\register)
|
|
1366 .endm
|
|
1367
|
|
1368 call_via r0
|
|
1369 call_via r1
|
|
1370 call_via r2
|
|
1371 call_via r3
|
|
1372 call_via r4
|
|
1373 call_via r5
|
|
1374 call_via r6
|
|
1375 call_via r7
|
|
1376 call_via r8
|
|
1377 call_via r9
|
|
1378 call_via sl
|
|
1379 call_via fp
|
|
1380 call_via ip
|
|
1381 call_via sp
|
|
1382 call_via lr
|
|
1383
|
|
1384 #endif /* L_call_via_rX */
|
|
1385
|
|
1386 /* Don't bother with the old interworking routines for Thumb-2. */
|
|
1387 /* ??? Maybe only omit these on "m" variants. */
|
|
1388 #if !defined(__thumb2__) && !defined(__ARM_ARCH_6M__)
|
|
1389
|
|
1390 #if defined L_interwork_call_via_rX
|
|
1391
|
|
1392 /* These labels & instructions are used by the Arm/Thumb interworking code,
|
|
1393 when the target address is in an unknown instruction set. The address
|
|
1394 of function to be called is loaded into a register and then one of these
|
|
1395 labels is called via a BL instruction. This puts the return address
|
|
1396 into the link register with the bottom bit set, and the code here
|
|
1397 switches to the correct mode before executing the function. Unfortunately
|
|
1398 the target code cannot be relied upon to return via a BX instruction, so
|
|
1399 instead we have to store the resturn address on the stack and allow the
|
|
1400 called function to return here instead. Upon return we recover the real
|
|
1401 return address and use a BX to get back to Thumb mode.
|
|
1402
|
|
1403 There are three variations of this code. The first,
|
|
1404 _interwork_call_via_rN(), will push the return address onto the
|
|
1405 stack and pop it in _arm_return(). It should only be used if all
|
|
1406 arguments are passed in registers.
|
|
1407
|
|
1408 The second, _interwork_r7_call_via_rN(), instead stores the return
|
|
1409 address at [r7, #-4]. It is the caller's responsibility to ensure
|
|
1410 that this address is valid and contains no useful data.
|
|
1411
|
|
1412 The third, _interwork_r11_call_via_rN(), works in the same way but
|
|
1413 uses r11 instead of r7. It is useful if the caller does not really
|
|
1414 need a frame pointer. */
|
|
1415
|
|
1416 .text
|
|
1417 .align 0
|
|
1418
|
|
1419 .code 32
|
|
1420 .globl _arm_return
|
|
1421 LSYM(Lstart_arm_return):
|
|
1422 cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return)
|
|
1423 cfi_push 0, 0xe, -0x8, 0x8
|
|
1424 nop @ This nop is for the benefit of debuggers, so that
|
|
1425 @ backtraces will use the correct unwind information.
|
|
1426 _arm_return:
|
|
1427 RETLDM unwind=LSYM(Lstart_arm_return)
|
|
1428 cfi_end LSYM(Lend_arm_return)
|
|
1429
|
|
1430 .globl _arm_return_r7
|
|
1431 _arm_return_r7:
|
|
1432 ldr lr, [r7, #-4]
|
|
1433 bx lr
|
|
1434
|
|
1435 .globl _arm_return_r11
|
|
1436 _arm_return_r11:
|
|
1437 ldr lr, [r11, #-4]
|
|
1438 bx lr
|
|
1439
|
|
1440 .macro interwork_with_frame frame, register, name, return
|
|
1441 .code 16
|
|
1442
|
|
1443 THUMB_FUNC_START \name
|
|
1444
|
|
1445 bx pc
|
|
1446 nop
|
|
1447
|
|
1448 .code 32
|
|
1449 tst \register, #1
|
|
1450 streq lr, [\frame, #-4]
|
|
1451 adreq lr, _arm_return_\frame
|
|
1452 bx \register
|
|
1453
|
|
1454 SIZE (\name)
|
|
1455 .endm
|
|
1456
|
|
1457 .macro interwork register
|
|
1458 .code 16
|
|
1459
|
|
1460 THUMB_FUNC_START _interwork_call_via_\register
|
|
1461
|
|
1462 bx pc
|
|
1463 nop
|
|
1464
|
|
1465 .code 32
|
|
1466 .globl LSYM(Lchange_\register)
|
|
1467 LSYM(Lchange_\register):
|
|
1468 tst \register, #1
|
|
1469 streq lr, [sp, #-8]!
|
|
1470 adreq lr, _arm_return
|
|
1471 bx \register
|
|
1472
|
|
1473 SIZE (_interwork_call_via_\register)
|
|
1474
|
|
1475 interwork_with_frame r7,\register,_interwork_r7_call_via_\register
|
|
1476 interwork_with_frame r11,\register,_interwork_r11_call_via_\register
|
|
1477 .endm
|
|
1478
|
|
1479 interwork r0
|
|
1480 interwork r1
|
|
1481 interwork r2
|
|
1482 interwork r3
|
|
1483 interwork r4
|
|
1484 interwork r5
|
|
1485 interwork r6
|
|
1486 interwork r7
|
|
1487 interwork r8
|
|
1488 interwork r9
|
|
1489 interwork sl
|
|
1490 interwork fp
|
|
1491 interwork ip
|
|
1492 interwork sp
|
|
1493
|
|
1494 /* The LR case has to be handled a little differently... */
|
|
1495 .code 16
|
|
1496
|
|
1497 THUMB_FUNC_START _interwork_call_via_lr
|
|
1498
|
|
1499 bx pc
|
|
1500 nop
|
|
1501
|
|
1502 .code 32
|
|
1503 .globl .Lchange_lr
|
|
1504 .Lchange_lr:
|
|
1505 tst lr, #1
|
|
1506 stmeqdb r13!, {lr, pc}
|
|
1507 mov ip, lr
|
|
1508 adreq lr, _arm_return
|
|
1509 bx ip
|
|
1510
|
|
1511 SIZE (_interwork_call_via_lr)
|
|
1512
|
|
1513 #endif /* L_interwork_call_via_rX */
|
|
1514 #endif /* !__thumb2__ */
|
|
1515 #endif /* Arch supports thumb. */
|
|
1516
|
|
1517 #ifndef __symbian__
|
|
1518 #ifndef __ARM_ARCH_6M__
|
|
1519 #include "ieee754-df.S"
|
|
1520 #include "ieee754-sf.S"
|
|
1521 #include "bpabi.S"
|
|
1522 #else /* __ARM_ARCH_6M__ */
|
|
1523 #include "bpabi-v6m.S"
|
|
1524 #endif /* __ARM_ARCH_6M__ */
|
|
1525 #endif /* !__symbian__ */
|