All,

The attached patch causes libgcc to use the UDIV and SDIV instructions when possible in the implementation of the ARM div/mod functions in libgcc.

This will benefit Cortex-M3, Cortex-M4, all Cortex-R* CPUs, Cortex-A7, and Cortex-A15.

The special case of some Cortex-R* CPUs where the UDIV/SDIV instructions are only available in Thumb mode, making it beneficial to force these library functions into Thumb mode to make use of those instructions, is not handled.

This was tested by configuring GCC --with-cpu cortex-a15, and then running the testsuite with -mcpu=cortex-a9. I've also manually inspected libgcc to make sure the functions are being built as expected.

Please can someone review?

Thanks,

Matt

libgcc/ChangeLog:

2011-11-15  Matthew Gretton-Dann  <matthew.gretton-d...@arm.com>

        * config/arm/lib1funcs.asm (udivsi3): Add support for divide
        functions.
        (aeabi_uidivmod): Likewise.     
        (umodsi3): Likewise.
        (divsi3): Likewise.
        (aeabi_idivmod): Likewise.
        (modsi3): Likewise.

Thanks,

Matt

--
Matthew Gretton-Dann
Principal Engineer, PD Software - Tools, ARM Ltd
diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S
index 2e76c01..094d79a 100644
--- a/libgcc/config/arm/lib1funcs.S
+++ b/libgcc/config/arm/lib1funcs.S
@@ -951,6 +951,17 @@ LSYM(udivsi3_skip_div0_test):
        pop     { work }
        RET
 
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+
+       ARM_FUNC_START udivsi3
+       ARM_FUNC_ALIAS aeabi_uidiv udivsi3
+
+       cmp     r1, #0
+       beq     LSYM(Ldiv0)
+
+       udiv    r0, r0, r1
+       RET
+
 #else /* ARM version/Thumb-2.  */
 
        ARM_FUNC_START udivsi3
@@ -997,6 +1008,14 @@ FUNC_START aeabi_uidivmod
        mul     r2, r0
        sub     r1, r1, r2
        bx      r3
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+ARM_FUNC_START aeabi_uidivmod
+       cmp     r1, #0
+       beq     LSYM(Ldiv0)
+       mov     r2, r0 
+       udiv    r0, r0, r1
+       mls     r1, r0, r1, r2
+       RET
 #else
 ARM_FUNC_START aeabi_uidivmod
        cmp     r1, #0
@@ -1014,9 +1033,19 @@ ARM_FUNC_START aeabi_uidivmod
 /* ------------------------------------------------------------------------ */
 #ifdef L_umodsi3
 
-       FUNC_START umodsi3
+#ifdef __ARM_ARCH_EXT_IDIV__
 
-#ifdef __thumb__
+       ARM_FUNC_START umodsi3
+
+       cmp     r1, #0
+       beq     LSYM(Ldiv0)
+       udiv    r2, r0, r1
+       mls     r0, r1, r2, r0
+       RET
+
+#elif defined(__thumb__)
+
+       FUNC_START umodsi3
 
        cmp     divisor, #0
        beq     LSYM(Ldiv0)
@@ -1035,6 +1064,8 @@ LSYM(Lover10):
        
 #else  /* ARM version.  */
        
+       FUNC_START umodsi3
+
        subs    r2, r1, #1                      @ compare divisor with 1
        bcc     LSYM(Ldiv0)
        cmpne   r0, r1                          @ compare dividend with divisor
@@ -1091,6 +1122,16 @@ LSYM(Lover12):
        pop     { work }
        RET
 
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+
+       ARM_FUNC_START divsi3
+       ARM_FUNC_ALIAS aeabi_idiv divsi3
+
+       cmp     r1, #0
+       beq     LSYM(Ldiv0)
+       sdiv    r0, r0, r1
+       RET
+
 #else /* ARM/Thumb-2 version.  */
        
        ARM_FUNC_START divsi3   
@@ -1153,6 +1194,14 @@ FUNC_START aeabi_idivmod
        mul     r2, r0
        sub     r1, r1, r2
        bx      r3
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+ARM_FUNC_START aeabi_idivmod
+       cmp     r1, #0
+       beq     LSYM(Ldiv0)
+       mov     r2, r0
+       sdiv    r0, r0, r1
+       mls     r1, r0, r1, r2
+       RET
 #else
 ARM_FUNC_START aeabi_idivmod
        cmp     r1, #0
@@ -1170,9 +1219,20 @@ ARM_FUNC_START aeabi_idivmod
 /* ------------------------------------------------------------------------ */
 #ifdef L_modsi3
 
-       FUNC_START modsi3
+#if defined(__ARM_ARCH_EXT_IDIV__)
 
-#ifdef __thumb__
+       ARM_FUNC_START modsi3
+
+       cmp     r1, #0
+       beq     LSYM(Ldiv0)
+
+       sdiv    r2, r0, r1
+       mls     r0, r1, r2, r0
+       RET
+
+#elif defined(__thumb__)
+
+       FUNC_START modsi3
 
        mov     curbit, #1
        cmp     divisor, #0
@@ -1204,6 +1264,8 @@ LSYM(Lover12):
 
 #else /* ARM version.  */
        
+       FUNC_START modsi3
+
        cmp     r1, #0
        beq     LSYM(Ldiv0)
        rsbmi   r1, r1, #0                      @ loops below use unsigned.

Reply via email to