aboutsummaryrefslogtreecommitdiff
path: root/libgcc/config/msp430/lib2divSI.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/config/msp430/lib2divSI.c')
-rw-r--r--libgcc/config/msp430/lib2divSI.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/libgcc/config/msp430/lib2divSI.c b/libgcc/config/msp430/lib2divSI.c
index cc45c4c87ea..fa6ac4552e6 100644
--- a/libgcc/config/msp430/lib2divSI.c
+++ b/libgcc/config/msp430/lib2divSI.c
@@ -40,3 +40,32 @@ typedef int word_type __attribute__ ((mode (__word__)));
#define NAME_MODE si
#include "msp430-divmod.h"
+
+/* ---------------------------------------------------------------------*/
+
+/* There is a typo in the MSP430 ABI document. It calls the unsigned
+ long integer division function __mspabi_divlu when it should be
+ __mspabi_divul. Likewise the unsigned long long integer division
+ function is called __mspabi_divllu when it should be __mspabi_divull.
+
+ Earlier versions of this toolchain used generate the ABI compliant
+ names, so in order to support object files built with those tools
+ we provide stub functions that call the correct routines. */
+
+asm (".global __mspabi_divlu\n\
+ .set __mspabi_divlu, __mspabi_divul");
+
+/* We cannot use the same trick for __mspabi_divllu as that is defined
+ in a different file. Instead we create a stub here. The cost of
+ executing the branch instruction will be trivial compared to the
+ cost of executing a long long division. */
+
+#ifdef __MSP430X_LARGE__
+asm (".global __mspabi_divllu\n\
+ __mspabi_divllu:\n\
+ BRA #__mspabi_divull");
+#else
+asm (".global __mspabi_divllu\n\
+ __mspabi_divllu:\n\
+ BR #__mspabi_divull");
+#endif