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 <[email protected]>
* 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 Ltddiff --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.