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.