| Index: gcc/gcc/config/arm/lib1funcs.asm
|
| diff --git a/gcc/gcc/config/arm/lib1funcs.asm b/gcc/gcc/config/arm/lib1funcs.asm
|
| index b1f2bcc74b97e9041bb1086063d5dde5d5cb921f..cd64da35860e70a2ac920acd2ed9566d4b58afb1 100644
|
| --- a/gcc/gcc/config/arm/lib1funcs.asm
|
| +++ b/gcc/gcc/config/arm/lib1funcs.asm
|
| @@ -2,7 +2,7 @@
|
| @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
|
|
| /* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005, 2007, 2008,
|
| - 2009 Free Software Foundation, Inc.
|
| + 2009, 2010 Free Software Foundation, Inc.
|
|
|
| This file is free software; you can redistribute it and/or modify it
|
| under the terms of the GNU General Public License as published by the
|
| @@ -27,8 +27,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
| #if defined(__ELF__) && defined(__linux__)
|
| .section .note.GNU-stack,"",%progbits
|
| .previous
|
| -#endif
|
| -
|
| +#endif /* __ELF__ and __linux__ */
|
| +
|
| +#ifdef __ARM_EABI__
|
| +/* Some attributes that are common to all routines in this file. */
|
| + /* Tag_ABI_align8_needed: This code does not require 8-byte
|
| + alignment from the caller. */
|
| + /* .eabi_attribute 24, 0 -- default setting. */
|
| + /* Tag_ABI_align8_preserved: This code preserves 8-byte
|
| + alignment in any callee. */
|
| + .eabi_attribute 25, 1
|
| +#endif /* __ARM_EABI__ */
|
| /* ------------------------------------------------------------------------ */
|
|
|
| /* We need to know what prefix to add to function names. */
|
| @@ -103,6 +112,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
| #error Unable to determine architecture.
|
| #endif
|
|
|
| +/* There are times when we might prefer Thumb1 code even if ARM code is
|
| + permitted, for example, the code might be smaller, or there might be
|
| + interworking problems with switching to ARM state if interworking is
|
| + disabled. */
|
| +#if (defined(__thumb__) \
|
| + && !defined(__thumb2__) \
|
| + && (!defined(__THUMB_INTERWORK__) \
|
| + || defined (__OPTIMIZE_SIZE__) \
|
| + || defined(__ARM_ARCH_6M__)))
|
| +# define __prefer_thumb__
|
| +#endif
|
| +
|
| /* How to return from a function call depends on the architecture variant. */
|
|
|
| #if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
|
| @@ -256,16 +277,91 @@ LSYM(Lend_fde):
|
| .endm
|
| #endif
|
|
|
| -.macro ARM_LDIV0 name
|
| +#ifdef __ARM_EABI__
|
| +.macro ARM_LDIV0 name signed
|
| + cmp r0, #0
|
| + .ifc \signed, unsigned
|
| + movne r0, #0xffffffff
|
| + .else
|
| + movgt r0, #0x7fffffff
|
| + movlt r0, #0x80000000
|
| + .endif
|
| + b SYM (__aeabi_idiv0) __PLT__
|
| +.endm
|
| +#else
|
| +.macro ARM_LDIV0 name signed
|
| str lr, [sp, #-8]!
|
| 98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
|
| bl SYM (__div0) __PLT__
|
| mov r0, #0 @ About as wrong as it could be.
|
| RETLDM unwind=98b
|
| .endm
|
| +#endif
|
|
|
|
|
| -.macro THUMB_LDIV0 name
|
| +#ifdef __ARM_EABI__
|
| +.macro THUMB_LDIV0 name signed
|
| +#if defined(__ARM_ARCH_6M__)
|
| + .ifc \signed, unsigned
|
| + cmp r0, #0
|
| + beq 1f
|
| + mov r0, #0
|
| + mvn r0, r0 @ 0xffffffff
|
| +1:
|
| + .else
|
| + cmp r0, #0
|
| + beq 2f
|
| + blt 3f
|
| + mov r0, #0
|
| + mvn r0, r0
|
| + lsr r0, r0, #1 @ 0x7fffffff
|
| + b 2f
|
| +3: mov r0, #0x80
|
| + lsl r0, r0, #24 @ 0x80000000
|
| +2:
|
| + .endif
|
| + push {r0, r1, r2}
|
| + ldr r0, 4f
|
| + adr r1, 4f
|
| + add r0, r1
|
| + str r0, [sp, #8]
|
| + @ We know we are not on armv4t, so pop pc is safe.
|
| + pop {r0, r1, pc}
|
| + .align 2
|
| +4:
|
| + .word __aeabi_idiv0 - 4b
|
| +#elif defined(__thumb2__)
|
| + .syntax unified
|
| + .ifc \signed, unsigned
|
| + cbz r0, 1f
|
| + mov r0, #0xffffffff
|
| +1:
|
| + .else
|
| + cmp r0, #0
|
| + do_it gt
|
| + movgt r0, #0x7fffffff
|
| + do_it lt
|
| + movlt r0, #0x80000000
|
| + .endif
|
| + b.w SYM(__aeabi_idiv0) __PLT__
|
| +#else
|
| + .align 2
|
| + bx pc
|
| + nop
|
| + .arm
|
| + cmp r0, #0
|
| + .ifc \signed, unsigned
|
| + movne r0, #0xffffffff
|
| + .else
|
| + movgt r0, #0x7fffffff
|
| + movlt r0, #0x80000000
|
| + .endif
|
| + b SYM(__aeabi_idiv0) __PLT__
|
| + .thumb
|
| +#endif
|
| +.endm
|
| +#else
|
| +.macro THUMB_LDIV0 name signed
|
| push { r1, lr }
|
| 98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
|
| bl SYM (__div0)
|
| @@ -277,18 +373,19 @@ LSYM(Lend_fde):
|
| pop { r1, pc }
|
| #endif
|
| .endm
|
| +#endif
|
|
|
| .macro FUNC_END name
|
| SIZE (__\name)
|
| .endm
|
|
|
| -.macro DIV_FUNC_END name
|
| +.macro DIV_FUNC_END name signed
|
| cfi_start __\name, LSYM(Lend_div0)
|
| LSYM(Ldiv0):
|
| #ifdef __thumb__
|
| - THUMB_LDIV0 \name
|
| + THUMB_LDIV0 \name \signed
|
| #else
|
| - ARM_LDIV0 \name
|
| + ARM_LDIV0 \name \signed
|
| #endif
|
| cfi_end LSYM(Lend_div0)
|
| FUNC_END \name
|
| @@ -413,6 +510,12 @@ SYM (__\name):
|
| #define yyl r2
|
| #endif
|
|
|
| +#ifdef __ARM_EABI__
|
| +.macro WEAK name
|
| + .weak SYM (__\name)
|
| +.endm
|
| +#endif
|
| +
|
| #ifdef __thumb__
|
| /* Register aliases. */
|
|
|
| @@ -437,6 +540,27 @@ pc .req r15
|
|
|
| #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
|
|
|
| +#if defined (__thumb2__)
|
| + clz \curbit, \dividend
|
| + clz \result, \divisor
|
| + sub \curbit, \result, \curbit
|
| + rsb \curbit, \curbit, #31
|
| + adr \result, 1f
|
| + add \curbit, \result, \curbit, lsl #4
|
| + mov \result, #0
|
| + mov pc, \curbit
|
| +.p2align 3
|
| +1:
|
| + .set shift, 32
|
| + .rept 32
|
| + .set shift, shift - 1
|
| + cmp.w \dividend, \divisor, lsl #shift
|
| + nop.n
|
| + adc.w \result, \result, \result
|
| + it cs
|
| + subcs.w \dividend, \dividend, \divisor, lsl #shift
|
| + .endr
|
| +#else
|
| clz \curbit, \dividend
|
| clz \result, \divisor
|
| sub \curbit, \result, \curbit
|
| @@ -452,6 +576,7 @@ pc .req r15
|
| adc \result, \result, \result
|
| subcs \dividend, \dividend, \divisor, lsl #shift
|
| .endr
|
| +#endif
|
|
|
| #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
|
| #if __ARM_ARCH__ >= 5
|
| @@ -499,18 +624,23 @@ pc .req r15
|
|
|
| @ Division loop
|
| 1: cmp \dividend, \divisor
|
| + do_it hs, t
|
| subhs \dividend, \dividend, \divisor
|
| orrhs \result, \result, \curbit
|
| cmp \dividend, \divisor, lsr #1
|
| + do_it hs, t
|
| subhs \dividend, \dividend, \divisor, lsr #1
|
| orrhs \result, \result, \curbit, lsr #1
|
| cmp \dividend, \divisor, lsr #2
|
| + do_it hs, t
|
| subhs \dividend, \dividend, \divisor, lsr #2
|
| orrhs \result, \result, \curbit, lsr #2
|
| cmp \dividend, \divisor, lsr #3
|
| + do_it hs, t
|
| subhs \dividend, \dividend, \divisor, lsr #3
|
| orrhs \result, \result, \curbit, lsr #3
|
| cmp \dividend, #0 @ Early termination?
|
| + do_it hs, t
|
| movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
|
| movne \divisor, \divisor, lsr #4
|
| bne 1b
|
| @@ -799,13 +929,14 @@ LSYM(Lgot_result):
|
| /* ------------------------------------------------------------------------ */
|
| #ifdef L_udivsi3
|
|
|
| +#if defined(__prefer_thumb__)
|
| +
|
| FUNC_START udivsi3
|
| FUNC_ALIAS aeabi_uidiv udivsi3
|
|
|
| -#ifdef __thumb__
|
| -
|
| cmp divisor, #0
|
| beq LSYM(Ldiv0)
|
| +LSYM(udivsi3_skip_div0_test):
|
| mov curbit, #1
|
| mov result, #0
|
|
|
| @@ -819,9 +950,16 @@ LSYM(Lgot_result):
|
| pop { work }
|
| RET
|
|
|
| -#else /* ARM version. */
|
| +#else /* ARM version/Thumb-2. */
|
|
|
| + ARM_FUNC_START udivsi3
|
| + ARM_FUNC_ALIAS aeabi_uidiv udivsi3
|
| +
|
| + /* Note: if called via udivsi3_skip_div0_test, this will unnecessarily
|
| + check for division-by-zero a second time. */
|
| +LSYM(udivsi3_skip_div0_test):
|
| subs r2, r1, #1
|
| + do_it eq
|
| RETc(eq)
|
| bcc LSYM(Ldiv0)
|
| cmp r0, r1
|
| @@ -834,7 +972,8 @@ LSYM(Lgot_result):
|
| mov r0, r2
|
| RET
|
|
|
| -11: moveq r0, #1
|
| +11: do_it eq, e
|
| + moveq r0, #1
|
| movne r0, #0
|
| RET
|
|
|
| @@ -845,19 +984,24 @@ LSYM(Lgot_result):
|
|
|
| #endif /* ARM version */
|
|
|
| - DIV_FUNC_END udivsi3
|
| + DIV_FUNC_END udivsi3 unsigned
|
|
|
| +#if defined(__prefer_thumb__)
|
| FUNC_START aeabi_uidivmod
|
| -#ifdef __thumb__
|
| + cmp r1, #0
|
| + beq LSYM(Ldiv0)
|
| push {r0, r1, lr}
|
| - bl SYM(__udivsi3)
|
| + bl LSYM(udivsi3_skip_div0_test)
|
| POP {r1, r2, r3}
|
| mul r2, r0
|
| sub r1, r1, r2
|
| bx r3
|
| #else
|
| +ARM_FUNC_START aeabi_uidivmod
|
| + cmp r1, #0
|
| + beq LSYM(Ldiv0)
|
| stmfd sp!, { r0, r1, lr }
|
| - bl SYM(__udivsi3)
|
| + bl LSYM(udivsi3_skip_div0_test)
|
| ldmfd sp!, { r1, r2, lr }
|
| mul r3, r2, r0
|
| sub r1, r1, r3
|
| @@ -904,19 +1048,20 @@ LSYM(Lover10):
|
|
|
| #endif /* ARM version. */
|
|
|
| - DIV_FUNC_END umodsi3
|
| + DIV_FUNC_END umodsi3 unsigned
|
|
|
| #endif /* L_umodsi3 */
|
| /* ------------------------------------------------------------------------ */
|
| #ifdef L_divsi3
|
|
|
| +#if defined(__prefer_thumb__)
|
| +
|
| FUNC_START divsi3
|
| FUNC_ALIAS aeabi_idiv divsi3
|
|
|
| -#ifdef __thumb__
|
| cmp divisor, #0
|
| beq LSYM(Ldiv0)
|
| -
|
| +LSYM(divsi3_skip_div0_test):
|
| push { work }
|
| mov work, dividend
|
| eor work, divisor @ Save the sign of the result.
|
| @@ -945,15 +1090,21 @@ LSYM(Lover12):
|
| pop { work }
|
| RET
|
|
|
| -#else /* ARM version. */
|
| +#else /* ARM/Thumb-2 version. */
|
|
|
| + ARM_FUNC_START divsi3
|
| + ARM_FUNC_ALIAS aeabi_idiv divsi3
|
| +
|
| cmp r1, #0
|
| - eor ip, r0, r1 @ save the sign of the result.
|
| beq LSYM(Ldiv0)
|
| +LSYM(divsi3_skip_div0_test):
|
| + eor ip, r0, r1 @ save the sign of the result.
|
| + do_it mi
|
| rsbmi r1, r1, #0 @ loops below use unsigned.
|
| subs r2, r1, #1 @ division by 1 or -1 ?
|
| beq 10f
|
| movs r3, r0
|
| + do_it mi
|
| rsbmi r3, r0, #0 @ positive dividend value
|
| cmp r3, r1
|
| bls 11f
|
| @@ -963,14 +1114,18 @@ LSYM(Lover12):
|
| ARM_DIV_BODY r3, r1, r0, r2
|
|
|
| cmp ip, #0
|
| + do_it mi
|
| rsbmi r0, r0, #0
|
| RET
|
|
|
| 10: teq ip, r0 @ same sign ?
|
| + do_it mi
|
| rsbmi r0, r0, #0
|
| RET
|
|
|
| -11: movlo r0, #0
|
| +11: do_it lo
|
| + movlo r0, #0
|
| + do_it eq,t
|
| moveq r0, ip, asr #31
|
| orreq r0, r0, #1
|
| RET
|
| @@ -979,24 +1134,30 @@ LSYM(Lover12):
|
|
|
| cmp ip, #0
|
| mov r0, r3, lsr r2
|
| + do_it mi
|
| rsbmi r0, r0, #0
|
| RET
|
|
|
| #endif /* ARM version */
|
|
|
| - DIV_FUNC_END divsi3
|
| + DIV_FUNC_END divsi3 signed
|
|
|
| +#if defined(__prefer_thumb__)
|
| FUNC_START aeabi_idivmod
|
| -#ifdef __thumb__
|
| + cmp r1, #0
|
| + beq LSYM(Ldiv0)
|
| push {r0, r1, lr}
|
| - bl SYM(__divsi3)
|
| + bl LSYM(divsi3_skip_div0_test)
|
| POP {r1, r2, r3}
|
| mul r2, r0
|
| sub r1, r1, r2
|
| bx r3
|
| #else
|
| +ARM_FUNC_START aeabi_idivmod
|
| + cmp r1, #0
|
| + beq LSYM(Ldiv0)
|
| stmfd sp!, { r0, r1, lr }
|
| - bl SYM(__divsi3)
|
| + bl LSYM(divsi3_skip_div0_test)
|
| ldmfd sp!, { r1, r2, lr }
|
| mul r3, r2, r0
|
| sub r1, r1, r3
|
| @@ -1062,21 +1223,25 @@ LSYM(Lover12):
|
|
|
| #endif /* ARM version */
|
|
|
| - DIV_FUNC_END modsi3
|
| + DIV_FUNC_END modsi3 signed
|
|
|
| #endif /* L_modsi3 */
|
| /* ------------------------------------------------------------------------ */
|
| #ifdef L_dvmd_tls
|
|
|
| - FUNC_START div0
|
| - FUNC_ALIAS aeabi_idiv0 div0
|
| - FUNC_ALIAS aeabi_ldiv0 div0
|
| -
|
| +#ifdef __ARM_EABI__
|
| + WEAK aeabi_idiv0
|
| + WEAK aeabi_ldiv0
|
| + FUNC_START aeabi_idiv0
|
| + FUNC_START aeabi_ldiv0
|
| RET
|
| -
|
| FUNC_END aeabi_ldiv0
|
| FUNC_END aeabi_idiv0
|
| +#else
|
| + FUNC_START div0
|
| + RET
|
| FUNC_END div0
|
| +#endif
|
|
|
| #endif /* L_divmodsi_tools */
|
| /* ------------------------------------------------------------------------ */
|
| @@ -1086,16 +1251,49 @@ LSYM(Lover12):
|
| /* Constant taken from <asm/signal.h>. */
|
| #define SIGFPE 8
|
|
|
| +#ifdef __ARM_EABI__
|
| + WEAK aeabi_idiv0
|
| + WEAK aeabi_ldiv0
|
| + ARM_FUNC_START aeabi_idiv0
|
| + ARM_FUNC_START aeabi_ldiv0
|
| +#else
|
| ARM_FUNC_START div0
|
| +#endif
|
|
|
| do_push {r1, lr}
|
| mov r0, #SIGFPE
|
| bl SYM(raise) __PLT__
|
| RETLDM r1
|
|
|
| +#ifdef __ARM_EABI__
|
| + FUNC_END aeabi_ldiv0
|
| + FUNC_END aeabi_idiv0
|
| +#else
|
| FUNC_END div0
|
| +#endif
|
|
|
| #endif /* L_dvmd_lnx */
|
| +#ifdef L_clear_cache
|
| +#if defined __ARM_EABI__ && defined __linux__
|
| +@ EABI GNU/Linux call to cacheflush syscall.
|
| + ARM_FUNC_START clear_cache
|
| + do_push {r7}
|
| +#if __ARM_ARCH__ >= 7 || defined(__ARM_ARCH_6T2__)
|
| + movw r7, #2
|
| + movt r7, #0xf
|
| +#else
|
| + mov r7, #0xf0000
|
| + add r7, r7, #2
|
| +#endif
|
| + mov r2, #0
|
| + swi 0
|
| + do_pop {r7}
|
| + RET
|
| + FUNC_END clear_cache
|
| +#else
|
| +#error "This is only for ARM EABI GNU/Linux"
|
| +#endif
|
| +#endif /* L_clear_cache */
|
| /* ------------------------------------------------------------------------ */
|
| /* Dword shift operations. */
|
| /* All the following Dword shift variants rely on the fact that
|
| @@ -1512,6 +1710,111 @@ LSYM(Lchange_\register):
|
|
|
| #endif /* L_interwork_call_via_rX */
|
| #endif /* !__thumb2__ */
|
| +
|
| +/* Functions to support compact pic switch tables in thumb1 state.
|
| + All these routines take an index into the table in r0. The
|
| + table is at LR & ~1 (but this must be rounded up in the case
|
| + of 32-bit entires). They are only permitted to clobber r12
|
| + and r14 and r0 must be preserved on exit. */
|
| +#ifdef L_thumb1_case_sqi
|
| +
|
| + .text
|
| + .align 0
|
| + .force_thumb
|
| + .syntax unified
|
| + THUMB_FUNC_START __gnu_thumb1_case_sqi
|
| + push {r1}
|
| + mov r1, lr
|
| + lsrs r1, r1, #1
|
| + lsls r1, r1, #1
|
| + ldrsb r1, [r1, r0]
|
| + lsls r1, r1, #1
|
| + add lr, lr, r1
|
| + pop {r1}
|
| + bx lr
|
| + SIZE (__gnu_thumb1_case_sqi)
|
| +#endif
|
| +
|
| +#ifdef L_thumb1_case_uqi
|
| +
|
| + .text
|
| + .align 0
|
| + .force_thumb
|
| + .syntax unified
|
| + THUMB_FUNC_START __gnu_thumb1_case_uqi
|
| + push {r1}
|
| + mov r1, lr
|
| + lsrs r1, r1, #1
|
| + lsls r1, r1, #1
|
| + ldrb r1, [r1, r0]
|
| + lsls r1, r1, #1
|
| + add lr, lr, r1
|
| + pop {r1}
|
| + bx lr
|
| + SIZE (__gnu_thumb1_case_uqi)
|
| +#endif
|
| +
|
| +#ifdef L_thumb1_case_shi
|
| +
|
| + .text
|
| + .align 0
|
| + .force_thumb
|
| + .syntax unified
|
| + THUMB_FUNC_START __gnu_thumb1_case_shi
|
| + push {r0, r1}
|
| + mov r1, lr
|
| + lsrs r1, r1, #1
|
| + lsls r0, r0, #1
|
| + lsls r1, r1, #1
|
| + ldrsh r1, [r1, r0]
|
| + lsls r1, r1, #1
|
| + add lr, lr, r1
|
| + pop {r0, r1}
|
| + bx lr
|
| + SIZE (__gnu_thumb1_case_shi)
|
| +#endif
|
| +
|
| +#ifdef L_thumb1_case_uhi
|
| +
|
| + .text
|
| + .align 0
|
| + .force_thumb
|
| + .syntax unified
|
| + THUMB_FUNC_START __gnu_thumb1_case_uhi
|
| + push {r0, r1}
|
| + mov r1, lr
|
| + lsrs r1, r1, #1
|
| + lsls r0, r0, #1
|
| + lsls r1, r1, #1
|
| + ldrh r1, [r1, r0]
|
| + lsls r1, r1, #1
|
| + add lr, lr, r1
|
| + pop {r0, r1}
|
| + bx lr
|
| + SIZE (__gnu_thumb1_case_uhi)
|
| +#endif
|
| +
|
| +#ifdef L_thumb1_case_si
|
| +
|
| + .text
|
| + .align 0
|
| + .force_thumb
|
| + .syntax unified
|
| + THUMB_FUNC_START __gnu_thumb1_case_si
|
| + push {r0, r1}
|
| + mov r1, lr
|
| + adds.n r1, r1, #2 /* Align to word. */
|
| + lsrs r1, r1, #2
|
| + lsls r0, r0, #2
|
| + lsls r1, r1, #2
|
| + ldr r0, [r1, r0]
|
| + adds r0, r0, r1
|
| + mov lr, r0
|
| + pop {r0, r1}
|
| + mov pc, lr /* We know we were called from thumb code. */
|
| + SIZE (__gnu_thumb1_case_si)
|
| +#endif
|
| +
|
| #endif /* Arch supports thumb. */
|
|
|
| #ifndef __symbian__
|
|
|