Commit 0c23e1be by Julian Brown Committed by Julian Brown

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
parent ce7611f2
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
......@@ -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}
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment