Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/arm/lib1funcs.asm @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
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__ */ |