summaryrefslogtreecommitdiffstats
path: root/lib/arm_support/support-arm.S
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2012-01-17 07:36:08 +0100
committerThomas Martitz <kugel@rockbox.org>2012-01-21 18:39:19 +0100
commitcf333a61c7861361b4025cb0f67c8f75b0b07eef (patch)
treececb037f3c38ecb035ff79de75dafa6b135bb595 /lib/arm_support/support-arm.S
parent4343011955bffaf61b002a89b0137d48e873d9d0 (diff)
downloadrockbox-cf333a61c7861361b4025cb0f67c8f75b0b07eef.tar.gz
rockbox-cf333a61c7861361b4025cb0f67c8f75b0b07eef.zip
Move supprt-arm.S to separate library.
Core, codecs and plugins link it separately so this gets rid of SOURCES trickery. Don't build it for hosted targets. Change-Id: If15ef90e93cd218a4352ae8e89eea95d3122452f
Diffstat (limited to 'lib/arm_support/support-arm.S')
-rw-r--r--lib/arm_support/support-arm.S703
1 files changed, 703 insertions, 0 deletions
diff --git a/lib/arm_support/support-arm.S b/lib/arm_support/support-arm.S
new file mode 100644
index 0000000000..6141a3f158
--- /dev/null
+++ b/lib/arm_support/support-arm.S
@@ -0,0 +1,703 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Jens Arnold
+ * Copyright (C) 2009 by Andrew Mahone
+ *
+ * Optimised replacements for libgcc functions
+ *
+ * Based on: libgcc routines for ARM cpu, additional algorithms from ARM System
+ * Developer's Guide
+ * Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+ * Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+ * Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <config.h>
+
+.macro ARM_SDIV32_PRE numerator, divisor, sign
+ /* sign[31] = divisor sign */
+ ands \sign, \divisor, #1<<31
+ rsbeq \divisor, \divisor, #0
+ /* sign[31] = result sign, sign[0:30], C = numerator sign */
+ eors \sign, \sign, \numerator, asr #32
+ rsbcs \numerator, \numerator, #0
+.endm
+
+.macro ARM_SDIV32_POST quotient, remainder, sign
+ movs \sign, \sign, lsl #1
+.ifnc "", "\quotient"
+ rsbcs \quotient, \quotient, #0
+.endif
+.ifnc "", "\remainder"
+ rsbmi \remainder, \remainder, #0
+.endif
+.endm
+
+#if ARM_ARCH < 5
+.macro ARMV4_UDIV32_BODY numerator, divisor, quotient, remainder, tmp, bits, div0label, return
+.ifnc "", "\div0label"
+ rsbs \divisor, \divisor, #0
+ beq \div0label
+.else
+ rsb \divisor, \divisor, #0
+.endif
+ /* This SWAR divider requires a numerator less than 1<<31, because it must
+ be able to shift the remainder left at each step without shifting out
+ topmost bit. Since a shift might be needed for the aligned remainder to
+ exceed the divisor, the topmost bit must be unset at the start to avoid
+ this overflow case. The original numerator is saved so that the result
+ can be corrected after the reduced division completes. */
+ cmn \numerator, \divisor
+.ifc "", "\quotient"
+.ifc "\numerator", "\remainder"
+.if \return
+ bxcc lr
+.else
+ b 99f
+.endif
+.else
+ bcc 20f
+.endif
+.else
+ bcc 20f
+.endif
+ movs \tmp, \numerator
+ movmi \numerator, \numerator, lsr #1
+ mov \bits, #30
+.set shift, 16
+.rept 5
+ cmn \divisor, \numerator, lsr #shift
+ subcs \bits, \bits, #shift
+ movcs \divisor, \divisor, lsl #shift
+.set shift, shift >> 1
+.endr
+ adds \numerator, \numerator, \divisor
+ subcc \numerator, \numerator, \divisor
+ add pc, pc, \bits, lsl #3
+ nop
+.rept 30
+ adcs \numerator, \divisor, \numerator, lsl #1
+ subcc \numerator, \numerator, \divisor
+.endr
+ adc \numerator, \numerator, \numerator
+ movs \tmp, \tmp, asr #1
+ rsb \bits, \bits, #31
+ bmi 10f
+.ifc "", "\quotient"
+ mov \remainder, \numerator, lsr \bits
+.else
+.ifc "", "\remainder"
+ mov \divisor, \numerator, lsr \bits
+ eor \quotient, \numerator, \divisor, lsl \bits
+.else
+ mov \remainder, \numerator, lsr \bits
+ eor \quotient, \numerator, \remainder, lsl \bits
+.endif
+.endif
+.ifne \return
+ bx lr
+.else
+ b 99f
+.endif
+10:
+ mov \tmp, \numerator, lsr \bits
+ eor \numerator, \numerator, \tmp, lsl \bits
+ sub \bits, \bits, #1
+ adc \tmp, \tmp, \tmp
+ adds \tmp, \tmp, \divisor, asr \bits
+.ifnc "", "\quotient"
+ adc \quotient, \numerator, \numerator
+.endif
+.ifnc "", "\remainder"
+ subcc \remainder, \tmp, \divisor, asr \bits
+ movcs \remainder, \tmp
+.endif
+.ifne \return
+ bx lr
+.else
+ b 99f
+.endif
+20:
+.ifnc "", "\remainder"
+.ifnc "\remainder", "\numerator"
+ mov \remainder, \numerator
+.endif
+.endif
+.ifnc "", "\quotient"
+ mov \quotient, #0
+.endif
+.ifne \return
+ bx lr
+.else
+99:
+.endif
+.endm
+
+.macro ARMV4_SDIV32_BODY numerator, divisor, quotient, remainder, bits, sign, div0label, return
+ /* When this is wrapped for signed division, the wrapper code will handle
+ inverting the divisor, and also the zero divisor test. */
+ ARM_SDIV32_PRE \numerator, \divisor, \sign
+.ifnc "", "\div0label"
+ tst \divisor, \divisor
+ beq \div0label
+.endif
+ /* This SWAR divider requires a numerator less than 1<<31, because it must
+ be able to shift the remainder left at each step without shifting out
+ topmost bit. With signed inputs, whose absolute value may not exceed
+ 1<<31,this may be accomplished simply by subtracting the divisor before
+ beginning division, and adding 1 to the quotient. */
+ adds \numerator, \numerator, \divisor
+ bcc 20f
+ mov \bits, #30
+.set shift, 16
+.rept 5
+ cmn \divisor, \numerator, lsr #shift
+ subcs \bits, \bits, #shift
+ movcs \divisor, \divisor, lsl #shift
+.set shift, shift >> 1
+.endr
+ adds \numerator, \numerator, \divisor
+ subcc \numerator, \numerator, \divisor
+ add pc, pc, \bits, lsl #3
+ nop
+.rept 30
+ adcs \numerator, \divisor, \numerator, lsl #1
+ subcc \numerator, \numerator, \divisor
+.endr
+ rsb \bits, \bits, #31
+ adc \numerator, \numerator, \numerator
+.ifc "", "\quotient"
+ mov \remainder, \numerator, lsr \bits
+.else
+.ifc "", "\remainder"
+ mov \divisor, \numerator, lsr \bits
+ add \numerator, \numerator, #1
+ sub \quotient, \numerator, \divisor, lsl \bits
+.else
+ mov \remainder, \numerator, lsr \bits
+ add \numerator, \numerator, #1
+ sub \quotient, \numerator, \remainder, lsl \bits
+.endif
+.endif
+.ifne \return
+ ARM_SDIV32_POST \quotient, \remainder, \sign
+ bx lr
+.else
+ b 99f
+.endif
+20:
+.ifnc "", "\remainder"
+ sub \remainder, \numerator, \divisor
+.endif
+.ifnc "", "\quotient"
+ mov \quotient, #0
+.endif
+.ifne \return
+ ARM_SDIV32_POST "", \remainder, \sign
+ bx lr
+.else
+99:
+ ARM_SDIV32_POST \quotient, \remainder, \sign
+.endif
+.endm
+
+#else
+.macro ARMV5_UDIV32_BODY numerator, divisor, quotient, remainder, bits, inv, neg, div0label, return
+ cmp \numerator, \divisor
+ clz \bits, \divisor
+ bcc 30f
+ mov \inv, \divisor, lsl \bits
+ add \neg, pc, \inv, lsr #25
+ /* Test whether divisor is 2^N */
+ cmp \inv, #1<<31
+ /* Load approximate reciprocal */
+ ldrhib \inv, [\neg, #.L_udiv_est_table-.-64]
+ bls 20f
+ subs \bits, \bits, #7
+ rsb \neg, \divisor, #0
+ /* Scale approximate reciprocal, or else branch to large-divisor path */
+ movpl \divisor, \inv, lsl \bits
+ bmi 10f
+ /* Newton-Raphson iteration to improve reciprocal accuracy */
+ mul \inv, \divisor, \neg
+ smlawt \divisor, \divisor, \inv, \divisor
+ mul \inv, \divisor, \neg
+ /* Complete N-R math and produce approximate quotient. Use smmla/smmul on
+ ARMv6. */
+#if ARM_ARCH >= 6
+ tst \numerator, \numerator
+ smmla \divisor, \divisor, \inv, \divisor
+ /* Branch to large-numerator handler, or else use smmul if sign bit is not
+ set. This wins on average with random numerators, and should be no
+ slower than using umull for small numerator, even if prediction fails.
+ */
+ bmi 40f
+ smmul \inv, \numerator, \divisor
+#else
+ /* ARMv5e lacks smmul, so always uses umull. */
+ mov \bits, #0
+ smlal \bits, \divisor, \inv, \divisor
+ umull \bits, \inv, \numerator, \divisor
+#endif
+ /* Calculate remainder and correct result. */
+ add \numerator, \numerator, \neg
+.ifnc "", "\remainder"
+ mla \remainder, \inv, \neg, \numerator
+.ifnc "", "\quotient"
+ mov \quotient, \inv
+ cmn \remainder, \neg
+ subcs \remainder, \remainder, \neg
+ addpl \remainder, \remainder, \neg, lsl #1
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+.else
+ cmn \remainder, \neg
+ subcs \remainder, \remainder, \neg
+ addpl \remainder, \remainder, \neg, lsl #1
+.endif
+.else
+ mla \divisor, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \divisor, \neg
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+.endif
+.if \return
+ bx lr
+.else
+ b 99f
+.endif
+10:
+ /* Very large divisors can be handled without further improving the
+ reciprocal. First the reciprocal must be reduced to ensure that it
+ underestimates the correct value. */
+ rsb \bits, \bits, #0
+ sub \inv, \inv, #4
+ mov \divisor, \inv, lsr \bits
+ /* Calculate approximate quotient and remainder */
+ umull \bits, \inv, \numerator, \divisor
+ /* Correct quotient and remainder */
+.ifnc "", "\remainder"
+ mla \remainder, \inv, \neg, \numerator
+.ifnc "", "\quotient"
+ mov \quotient, \inv
+ cmn \neg, \remainder, lsr #1
+ addcs \remainder, \remainder, \neg, lsl #1
+ addcs \quotient, \quotient, #2
+ cmn \neg, \remainder
+ addcs \remainder, \remainder, \neg
+ addcs \quotient, \quotient, #1
+.else
+ cmn \neg, \remainder, lsr #1
+ addcs \remainder, \remainder, \neg, lsl #1
+ cmn \neg, \remainder
+ addcs \remainder, \remainder, \neg
+.endif
+.else
+ mla \divisor, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \neg, \divisor, lsr #1
+ addcs \divisor, \divisor, \neg, lsl #1
+ addcs \quotient, \quotient, #2
+ cmn \neg, \divisor
+ addcs \quotient, \quotient, #1
+.endif
+.if \return
+ bx lr
+.else
+ b 99f
+.endif
+20:
+ /* Handle division by powers of two by shifting right. Mod is handled
+ by using divisor-1 as a bitmask. */
+.ifnc "", "\remainder"
+.ifnc "", "\div0label"
+ bne \div0label
+.endif
+.ifnc "", "\quotient"
+ sub \divisor, \divisor, #1
+ rsb \bits, \bits, #31
+ and \remainder, \numerator, \divisor
+ mov \quotient, \numerator, lsr \bits
+.else
+ sub \divisor, \divisor, #1
+ and \remainder, \numerator, \divisor
+.endif
+.else
+ rsb \bits, \bits, #31
+.ifnc "", "\div0label"
+ bne \div0label
+.endif
+ mov \quotient, \numerator, lsr \bits
+.endif
+.if \return
+ bx lr
+.else
+ b 99f
+.endif
+30:
+ /* Handle numerator < divisor - quotient is zero, remainder is numerator,
+ which must be restored to its original value on ARMv6. */
+.ifnc "", "\remainder"
+ mov \remainder, \numerator
+.endif
+.ifnc "", "\quotient"
+ mov \quotient, #0
+.endif
+.if \return
+ bx lr
+.endif
+#if ARM_ARCH >= 6
+40:
+ /* Handle large (sign bit set) numerators. Works exactly as the ARMv5e code
+ above 10:. */
+ umull \bits, \inv, \numerator, \divisor
+ add \numerator, \numerator, \neg
+.ifnc "", "\remainder"
+ mla \remainder, \inv, \neg, \numerator
+.ifnc "", "\quotient"
+ mla \remainder, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \remainder, \neg
+ subcs \remainder, \remainder, \neg
+ addpl \remainder, \remainder, \neg, lsl #1
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+.else
+ cmn \remainder, \neg
+ subcs \remainder, \remainder, \neg
+ addpl \remainder, \remainder, \neg, lsl #1
+.endif
+.else
+ mla \divisor, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \divisor, \neg
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+.endif
+.if \return
+ bx lr
+.else
+ b 99f
+.endif
+#endif
+99:
+.endm
+
+.macro ARMV5_SDIV32_BODY numerator, divisor, quotient, remainder, bits, inv, neg, sign, div0label, return
+ /* sign[31] = divisor sign */
+ ands \sign, \divisor, #1<<31
+ rsbne \divisor, \divisor, #0
+ /* sign[31] = result sign, sign[0:30], C = numerator sign */
+ eors \sign, \sign, \numerator, asr #32
+ clz \bits, \divisor
+ rsbcs \numerator, \numerator, #0
+ /* On ARMv6, subtract divisor before performing division, which ensures
+ numerator sign bit is clear and smmul may be used in place of umull. The
+ fixup for the results can be fit entirely into existing delay slots on
+ the main division paths. It costs 1c in the num<div path if the
+ the remainder is to be produced in the numerator's register, and 1c in
+ the power-of-2-divisor path only if producing both remainder and
+ quotient. */
+#if ARM_ARCH >= 6
+ subs \numerator, \numerator, \divisor
+#else
+ cmp \numerator, \divisor
+#endif
+ movcs \inv, \divisor, lsl \bits
+ bcc 30f
+ /* Test whether divisor is 2^N */
+ cmp \inv, #1<<31
+ add \inv, pc, \inv, lsr #25
+ bls 20f
+ /* Load approximate reciprocal */
+ ldrb \inv, [\inv, #.L_udiv_est_table-.-64]
+ subs \bits, \bits, #7
+ rsb \neg, \divisor, #0
+ /* Scale approximate reciprocal, or else branch to large-divisor path */
+ movpl \divisor, \inv, lsl \bits
+ bmi 10f
+ /* Newton-Raphson iteration to improve reciprocal accuracy */
+ mul \inv, \divisor, \neg
+ smlawt \divisor, \divisor, \inv, \divisor
+ mul \inv, \divisor, \neg
+ /* Complete N-R math and produce approximate quotient. Use smmla/smmul on
+ ARMv6. */
+#if ARM_ARCH >= 6
+ smmla \divisor, \divisor, \inv, \divisor
+ smmul \inv, \numerator, \divisor
+#else
+ mov \bits, #0
+ smlal \bits, \divisor, \inv, \divisor
+ umull \bits, \inv, \numerator, \divisor
+#endif
+ /* Calculate remainder and correct quotient. */
+ add \numerator, \numerator, \neg
+.ifnc "", "\remainder"
+ mla \remainder, \inv, \neg, \numerator
+.ifnc "", "\quotient"
+#if ARM_ARCH >= 6
+ add \quotient, \inv, #1
+#else
+ mov \quotient, \inv
+#endif
+ cmn \remainder, \neg
+ subcs \remainder, \remainder, \neg
+ addpl \remainder, \remainder, \neg, lsl #1
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+.else
+ cmn \remainder, \neg
+ subcs \remainder, \remainder, \neg
+ addpl \remainder, \remainder, \neg, lsl #1
+.endif
+.else
+ mla \divisor, \inv, \neg, \numerator
+#if ARM_ARCH >= 6
+ add \quotient, \inv, #1
+#else
+ mov \quotient, \inv
+#endif
+ cmn \divisor, \neg
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+.endif
+ ARM_SDIV32_POST \quotient, \remainder, \sign
+.ifnc "", "\return"
+ \return
+.else
+ b 99f
+.endif
+10:
+ /* Very large divisors can be handled without further improving the
+ reciprocal. First the reciprocal must be reduced to ensure that it
+ underestimates the correct value. */
+ rsb \bits, \bits, #0
+ sub \inv, \inv, #4
+ mov \divisor, \inv, lsr \bits
+ /* Calculate approximate quotient and remainder */
+#if ARM_ARCH >= 6
+ smmul \inv, \numerator, \divisor
+#else
+ umull \bits, \inv, \numerator, \divisor
+#endif
+ /* Correct quotient and remainder */
+.ifnc "", "\remainder"
+ mla \remainder, \inv, \neg, \numerator
+.ifnc "", "\quotient"
+#if ARM_ARCH >= 6
+ add \quotient, \inv, #1
+#else
+ mov \quotient, \inv
+#endif
+ cmn \neg, \remainder, lsr #1
+ addcs \remainder, \remainder, \neg, lsl #1
+ addcs \quotient, \quotient, #2
+ cmn \neg, \remainder
+ addcs \remainder, \remainder, \neg
+ addcs \quotient, \quotient, #1
+.else
+ cmn \neg, \remainder, lsr #1
+ addcs \remainder, \remainder, \neg, lsl #1
+ cmn \neg, \remainder
+ addcs \remainder, \remainder, \neg
+.endif
+.else
+ mla \divisor, \inv, \neg, \numerator
+#if ARM_ARCH >= 6
+ add \quotient, \inv, #1
+#else
+ mov \quotient, \inv
+#endif
+ cmn \neg, \divisor, lsr #1
+ addcs \divisor, \divisor, \neg, lsl #1
+ addcs \quotient, \quotient, #2
+ cmn \neg, \divisor
+ addcs \quotient, \quotient, #1
+.endif
+ ARM_SDIV32_POST \quotient, \remainder, \sign
+.ifnc "", "\return"
+ \return
+.else
+ b 99f
+.endif
+20:
+ /* Handle division by powers of two by shifting right. Mod is handled
+ by using divisor-1 as a bitmask. */
+.ifnc "", "\div0label"
+ bne \div0label
+.endif
+.ifnc "", "\remainder"
+.ifnc "", "\quotient"
+ rsb \bits, \bits, #31
+#if ARM_ARCH >= 6
+ add \numerator, \numerator, \divisor
+#endif
+ sub \divisor, \divisor, #1
+ and \remainder, \numerator, \divisor
+ mov \quotient, \numerator, lsr \bits
+.else
+ sub \divisor, \divisor, #1
+ and \remainder, \numerator, \divisor
+.endif
+.else
+ rsb \bits, \bits, #31
+#if ARM_ARCH >= 6
+ add \numerator, \numerator, \divisor
+#endif
+ mov \quotient, \numerator, lsr \bits
+.endif
+ ARM_SDIV32_POST \quotient, \remainder, \sign
+.ifnc "", "\return"
+ \return
+.else
+ b 99f
+.endif
+30:
+ /* Handle numerator < divisor - quotient is zero, remainder is numerator,
+ which must be restored to its original value on ARMv6. */
+.ifnc "", "\remainder"
+#if ARM_ARCH >= 6
+ add \remainder, \numerator, \divisor
+#else
+.ifnc "\remainder", "\numerator"
+ mov \remainder, \numerator
+.endif
+#endif
+.endif
+.ifnc "", "\quotient"
+ mov \quotient, #0
+.endif
+.ifnc "", "\remainder"
+ ARM_SDIV32_POST "", \remainder, \sign
+.endif
+.ifnc "", "\return"
+ \return
+.endif
+99:
+.endm
+#endif
+
+ .section .text
+
+__div0_wrap_s:
+ sub sp, sp, #4
+ b __div0
+ .size __div0_wrap_s, . - __div0_wrap_s
+
+__div0_wrap:
+ str lr, [sp, #-4]!
+ b __div0
+ .size __div0_wrap, . - __div0_wrap
+
+#ifndef __ARM_EABI__
+ .global __divsi3
+ .type __divsi3,%function
+ .global __udivsi3
+ .type __udivsi3,%function
+ .global __udivsi3
+ .type __udivsi3,%function
+#else
+/* The div+mod averagess a fraction of a cycle worse for signed values, and
+ slightly better for unsigned, so just alias div to divmod. */
+ .global __aeabi_uidivmod
+ .type __aeabi_uidivmod,%function
+ .global __aeabi_uidiv
+ .type __aeabi_uidiv,%function
+ .set __aeabi_uidiv,__aeabi_uidivmod
+ .global __aeabi_idivmod
+ .type __aeabi_idivmod,%function
+ .global __aeabi_idiv
+ .type __aeabi_idiv,%function
+ .set __aeabi_idiv,__aeabi_idivmod
+#endif
+
+
+#if ARM_ARCH < 5
+ .global __clzsi2
+ .type __clzsi2, %function
+
+__clzsi2:
+ orr r0, r0, r0, lsr #8
+ orr r0, r0, r0, lsr #4
+ orr r0, r0, r0, lsr #2
+ orr r0, r0, r0, lsr #1
+ bic r0, r0, r0, lsr #16
+ rsb r0, r0, r0, lsl #14
+ rsb r0, r0, r0, lsl #11
+ rsb r0, r0, r0, lsl #9
+ ldrb r0, [pc, r0, lsr #26]
+ bx lr
+ .byte 32, 20, 19, 0, 0, 18, 0, 7, 10, 17, 0, 0, 14, 0, 6, 0
+ .byte 0, 9, 0, 16, 0, 0, 1, 26, 0, 13, 0, 0, 24, 5, 0, 0
+ .byte 0, 21, 0, 8, 11, 0, 15, 0, 0, 0, 0, 2, 27, 0, 25, 0
+ .byte 22, 0, 12, 0, 0, 3, 28, 0, 23, 0, 4, 29, 0, 0, 30, 31
+ .size __clzsi2, .-__clzsi2
+
+#ifndef __ARM_EABI__
+__udivsi3:
+ ARMV4_UDIV32_BODY r0, r1, r0, "", r2, r3, __div0_wrap, 1
+ .size __udivsi3, . - __udivsi3
+
+__divsi3:
+ ARMV4_SDIV32_BODY r0, r1, r0, "", r2, r3, __div0_wrap, 1
+ .size __divsi3, . - __divsi3
+
+#else
+__aeabi_uidivmod:
+ ARMV4_UDIV32_BODY r0, r1, r0, r1, r2, r3, __div0_wrap, 1
+ .size __aeabi_uidivmod, . - __aeabi_uidivmod
+
+__aeabi_idivmod:
+ ARMV4_SDIV32_BODY r0, r1, r0, r1, r2, r3, __div0_wrap, 1
+ .size __aeabi_idivmod, . - __aeabi_idivmod
+#endif
+
+#else
+#ifndef __ARM_EABI__
+__udivsi3:
+ ARMV5_UDIV32_BODY r0, r1, r0, "", r2, r3, ip, __div0_wrap, 1
+ .size __udivsi3, . - __udivsi3
+
+__divsi3:
+ str lr, [sp, #-4]
+ ARMV5_SDIV32_BODY r0, r1, r0, "", r2, lr, ip, r3, __div0_wrap_s, "ldr pc, [sp, #-4]"
+ .size __divsi3, . - __divsi3
+
+#else
+__aeabi_uidivmod:
+ ARMV5_UDIV32_BODY r0, r1, r0, r1, r2, r3, ip, __div0_wrap, 1
+ .size __aeabi_uidivmod, . - __aeabi_uidivmod
+
+__aeabi_idivmod:
+ str lr, [sp, #-4]
+ ARMV5_SDIV32_BODY r0, r1, r0, r1, r2, lr, ip, r3, __div0_wrap_s, "ldr pc, [sp, #-4]"
+ .size __aeabi_idivmod, . - __aeabi_idivmod
+#endif
+
+.L_udiv_est_table:
+ .byte 0xff, 0xfc, 0xf8, 0xf4, 0xf0, 0xed, 0xea, 0xe6
+ .byte 0xe3, 0xe0, 0xdd, 0xda, 0xd7, 0xd4, 0xd2, 0xcf
+ .byte 0xcc, 0xca, 0xc7, 0xc5, 0xc3, 0xc0, 0xbe, 0xbc
+ .byte 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 0xae, 0xac
+ .byte 0xaa, 0xa8, 0xa7, 0xa5, 0xa3, 0xa2, 0xa0, 0x9f
+ .byte 0x9d, 0x9c, 0x9a, 0x99, 0x97, 0x96, 0x94, 0x93
+ .byte 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x89
+ .byte 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81
+#endif