aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJulian Brown <julian@codesourcery.com>2009-12-17 15:37:23 +0000
committerJulian Brown <jules@gcc.gnu.org>2009-12-17 15:37:23 +0000
commit0c23e1be874aec1658ae7f95499d289d95530ad6 (patch)
tree11aa02e3ca0aaf3665b8f9f816fb7e037bb9c9de /gcc
parentce7611f2f8a757eede90c92ae1489e510a766864 (diff)
downloadgcc-0c23e1be874aec1658ae7f95499d289d95530ad6.zip
gcc-0c23e1be874aec1658ae7f95499d289d95530ad6.tar.gz
gcc-0c23e1be874aec1658ae7f95499d289d95530ad6.tar.bz2
bpabi-v6m.S (test_div_by_zero): New macro.
gcc/ * config/arm/bpabi-v6m.S (test_div_by_zero): New macro. (aeabi_ldivmod, aeabi_uldivmod): Use above macro. * config/arm/bpabi.S (test_div_by_zero): New macro. (aeabi_ldivmod, aeabi_uldivmod): Use above macro. * config/arm/lib1funcs.asm (ARM_LDIV0): Tail-call int div-by-zero handler for EABI. Add signed/unsigned argument, pass correct value to that handler. (THUMB_LDIV0): Same, for Thumb. (DIV_FUNC_END): Add signed argument. (WEAK): New macro (for EABI). (__udivsi3, __umodsi3): Add unsigned argument to DIV_FUNC_END. For __udivsi3, add entry point which skips division-by-zero test. (__divsi3, __modsi3): Add signed argument to DIV_FUNC_END. (__aeabi_uidivmod, __aeabi_idivmod): Check for division by zero. Call __udivsi3 or __divsi3 via entry points which skip division-by-zero tests. (__div0): Rename to __aeabi_idiv0, __aeabi_ldiv0 for EABI, and declare those names weak. From-SVN: r155319
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/config/arm/bpabi-v6m.S45
-rw-r--r--gcc/config/arm/bpabi.S50
-rw-r--r--gcc/config/arm/lib1funcs.asm151
4 files changed, 247 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fe0de91..2282539 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2009-12-17 Julian Brown <julian@codesourcery.com>
+
+ * config/arm/bpabi-v6m.S (test_div_by_zero): New macro.
+ (aeabi_ldivmod, aeabi_uldivmod): Use above macro.
+ * config/arm/bpabi.S (test_div_by_zero): New macro.
+ (aeabi_ldivmod, aeabi_uldivmod): Use above macro.
+ * config/arm/lib1funcs.asm (ARM_LDIV0): Tail-call int div-by-zero
+ handler for EABI. Add signed/unsigned argument, pass correct value
+ to that handler.
+ (THUMB_LDIV0): Same, for Thumb.
+ (DIV_FUNC_END): Add signed argument.
+ (WEAK): New macro (for EABI).
+ (__udivsi3, __umodsi3): Add unsigned argument to DIV_FUNC_END. For
+ __udivsi3, add entry point which skips division-by-zero test.
+ (__divsi3, __modsi3): Add signed argument to DIV_FUNC_END.
+ (__aeabi_uidivmod, __aeabi_idivmod): Check for division by zero.
+ Call __udivsi3 or __divsi3 via entry points which skip
+ division-by-zero tests.
+ (__div0): Rename to __aeabi_idiv0, __aeabi_ldiv0 for EABI, and
+ declare those names weak.
+
2009-12-17 Richard Guenther <rguenther@suse.de>
PR middle-end/42397
diff --git a/gcc/config/arm/bpabi-v6m.S b/gcc/config/arm/bpabi-v6m.S
index 77018e1..75d50d9 100644
--- a/gcc/config/arm/bpabi-v6m.S
+++ b/gcc/config/arm/bpabi-v6m.S
@@ -69,9 +69,52 @@ FUNC_START aeabi_ulcmp
#endif /* L_aeabi_ulcmp */
+.macro test_div_by_zero signed
+ cmp yyh, #0
+ bne 7f
+ cmp yyl, #0
+ bne 7f
+ cmp xxh, #0
+ bne 2f
+ cmp xxl, #0
+2:
+ .ifc \signed, unsigned
+ beq 3f
+ mov xxh, #0
+ mvn xxh, xxh @ 0xffffffff
+ mov xxl, xxh
+3:
+ .else
+ beq 5f
+ blt 6f
+ mov xxl, #0
+ mvn xxl, xxl @ 0xffffffff
+ lsr xxh, xxl, #1 @ 0x7fffffff
+ b 5f
+6: mov xxh, #0x80
+ lsl xxh, xxh, #24 @ 0x80000000
+ mov xxl, #0
+5:
+ .endif
+ @ tailcalls are tricky on v6-m.
+ push {r0, r1, r2}
+ ldr r0, 1f
+ adr r1, 1f
+ 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
+1:
+ .word __aeabi_ldiv0 - 1b
+7:
+.endm
+
#ifdef L_aeabi_ldivmod
FUNC_START aeabi_ldivmod
+ test_div_by_zero signed
+
push {r0, r1}
mov r0, sp
push {r0, lr}
@@ -89,6 +132,8 @@ FUNC_START aeabi_ldivmod
#ifdef L_aeabi_uldivmod
FUNC_START aeabi_uldivmod
+ test_div_by_zero unsigned
+
push {r0, r1}
mov r0, sp
push {r0, lr}
diff --git a/gcc/config/arm/bpabi.S b/gcc/config/arm/bpabi.S
index 850381e..ccc569e 100644
--- a/gcc/config/arm/bpabi.S
+++ b/gcc/config/arm/bpabi.S
@@ -64,9 +64,57 @@ ARM_FUNC_START aeabi_ulcmp
#endif /* L_aeabi_ulcmp */
+.macro test_div_by_zero signed
+/* Tail-call to divide-by-zero handlers which may be overridden by the user,
+ so unwinding works properly. */
+#if defined(__thumb2__)
+ cbnz yyh, 1f
+ cbnz yyl, 1f
+ cmp xxh, #0
+ do_it eq
+ cmpeq xxl, #0
+ .ifc \signed, unsigned
+ beq 2f
+ mov xxh, #0xffffffff
+ mov xxl, xxh
+2:
+ .else
+ do_it lt, t
+ movlt xxl, #0
+ movlt xxh, #0x80000000
+ do_it gt, t
+ movgt xxh, #0x7fffffff
+ movgt xxl, #0xffffffff
+ .endif
+ b SYM (__aeabi_ldiv0) __PLT__
+1:
+#else
+ /* Note: Thumb-1 code calls via an ARM shim on processors which
+ support ARM mode. */
+ cmp yyh, #0
+ cmpeq yyl, #0
+ bne 2f
+ cmp xxh, #0
+ cmpeq xxl, #0
+ .ifc \signed, unsigned
+ movne xxh, #0xffffffff
+ movne xxl, #0xffffffff
+ .else
+ movlt xxh, #0x80000000
+ movlt xxl, #0
+ movgt xxh, #0x7fffffff
+ movgt xxl, #0xffffffff
+ .endif
+ b SYM (__aeabi_ldiv0) __PLT__
+2:
+#endif
+.endm
+
#ifdef L_aeabi_ldivmod
ARM_FUNC_START aeabi_ldivmod
+ test_div_by_zero signed
+
sub sp, sp, #8
#if defined(__thumb2__)
mov ip, sp
@@ -85,6 +133,8 @@ ARM_FUNC_START aeabi_ldivmod
#ifdef L_aeabi_uldivmod
ARM_FUNC_START aeabi_uldivmod
+ test_div_by_zero unsigned
+
sub sp, sp, #8
#if defined(__thumb2__)
mov ip, sp
diff --git a/gcc/config/arm/lib1funcs.asm b/gcc/config/arm/lib1funcs.asm
index 9f7cc63..1035a3c 100644
--- a/gcc/config/arm/lib1funcs.asm
+++ b/gcc/config/arm/lib1funcs.asm
@@ -265,16 +265,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)
@@ -286,18 +361,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
@@ -422,6 +498,12 @@ SYM (__\name):
#define yyl r2
#endif
+#ifdef __ARM_EABI__
+.macro WEAK name
+ .weak SYM (__\name)
+.endm
+#endif
+
#ifdef __thumb__
/* Register aliases. */
@@ -842,6 +924,7 @@ LSYM(Lgot_result):
cmp divisor, #0
beq LSYM(Ldiv0)
+LSYM(udivsi3_skip_div0_test):
mov curbit, #1
mov result, #0
@@ -860,6 +943,9 @@ LSYM(Lgot_result):
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)
@@ -886,20 +972,24 @@ LSYM(Lgot_result):
#endif /* ARM version */
- DIV_FUNC_END udivsi3
+ DIV_FUNC_END udivsi3 unsigned
#if defined(__ARM_ARCH_6M__)
FUNC_START aeabi_uidivmod
+ 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
@@ -946,7 +1036,7 @@ LSYM(Lover10):
#endif /* ARM version. */
- DIV_FUNC_END umodsi3
+ DIV_FUNC_END umodsi3 unsigned
#endif /* L_umodsi3 */
/* ------------------------------------------------------------------------ */
@@ -959,7 +1049,7 @@ LSYM(Lover10):
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.
@@ -994,8 +1084,9 @@ LSYM(Lover12):
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 ?
@@ -1037,20 +1128,24 @@ LSYM(Lover12):
#endif /* ARM version */
- DIV_FUNC_END divsi3
+ DIV_FUNC_END divsi3 signed
#if defined(__ARM_ARCH_6M__)
FUNC_START aeabi_idivmod
+ 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
@@ -1116,21 +1211,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 */
/* ------------------------------------------------------------------------ */
@@ -1140,14 +1239,26 @@ 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