OSDN Git Service

gcc/
authorjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Dec 2009 15:37:23 +0000 (15:37 +0000)
committerjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Dec 2009 15:37:23 +0000 (15:37 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155319 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/bpabi-v6m.S
gcc/config/arm/bpabi.S
gcc/config/arm/lib1funcs.asm

index fe0de91..2282539 100644 (file)
@@ -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
index 77018e1..75d50d9 100644 (file)
@@ -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}
index 850381e..ccc569e 100644 (file)
@@ -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
index 9f7cc63..1035a3c 100644 (file)
@@ -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