aboutsummaryrefslogtreecommitdiff
path: root/src/arch/arm/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/libgcc')
-rw-r--r--src/arch/arm/libgcc/bpabi.c214
-rw-r--r--src/arch/arm/libgcc/bpabi_asm.S130
-rw-r--r--src/arch/arm/libgcc/uldivmod.S28
3 files changed, 19 insertions, 353 deletions
diff --git a/src/arch/arm/libgcc/bpabi.c b/src/arch/arm/libgcc/bpabi.c
deleted file mode 100644
index 8cb7ddf129..0000000000
--- a/src/arch/arm/libgcc/bpabi.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Miscellaneous BPABI functions.
-
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC.
-
- This file 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, or (at your option) any
- later version.
-
- In addition to the permissions in the GNU General Public License, the
- Free Software Foundation gives you unlimited permission to link the
- compiled version of this file into combinations with other programs,
- and to distribute those combinations without any restriction coming
- from the use of this file. (The General Public License restrictions
- do apply in other respects; for example, they cover modification of
- the file, and distribution when not linked into a combine
- executable.)
-
- This file is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#if defined __GNUC__
-
-#include <stdint.h>
-
-uint64_t __udivmoddi4(uint64_t n, uint64_t d, uint64_t *rp);
-extern int64_t __divdi3(int64_t, int64_t);
-extern uint64_t __udivdi3(uint64_t, uint64_t);
-extern int64_t __gnu_ldivmod_helper(int64_t, int64_t, int64_t *);
-extern uint64_t __gnu_uldivmod_helper(uint64_t, uint64_t, uint64_t *);
-
-typedef union
-{
- struct {
- int32_t low;
- int32_t high;
- } s;
- int64_t ll;
-} DWunion;
-
-uint64_t
-__udivmoddi4(uint64_t n, uint64_t d, uint64_t *rp)
-{
- const DWunion nn = {.ll = n};
- const DWunion dd = {.ll = d};
- DWunion rr;
- uint32_t d0, d1, n0, n1, n2;
- uint32_t q0, q1;
- uint32_t b, bm;
-
- d0 = dd.s.low;
- d1 = dd.s.high;
- n0 = nn.s.low;
- n1 = nn.s.high;
-
- if (d1 == 0) {
- if (d0 > n1) {
- /* 0q = nn / 0D */
- udiv_qrnnd(q0, n0, n1, n0, d0);
- q1 = 0;
- /* Remainder in n0. */
- } else {
- /* qq = NN / 0d */
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- udiv_qrnnd(q1, n1, 0, n1, d0);
- udiv_qrnnd(q0, n0, n1, n0, d0);
-
- /* Remainder in n0. */
- }
-
- if (rp != 0) {
- rr.s.low = n0;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- } else {
- if (d1 > n1) {
- /* 00 = nn / DD */
- q0 = 0;
- q1 = 0;
-
- /* Remainder in n1n0. */
- if (rp != 0) {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- } else {
- /* 0q = NN / dd */
-
- count_leading_zeros(bm, d1);
- if (bm == 0) {
- /* From (n1 >= d1) /\ (the most significant
- bit of d1 is set), conclude (the most
- significant bit of n1 is set) /\ (the
- quotient digit q0 = 0 or 1).
-
- This special case is necessary, not an
- optimization. */
-
- /* The condition on the next line takes
- advantage of that n1 >= d1 (true due to
- program flow). */
- if (n1 > d1 || n0 >= d0) {
- q0 = 1;
- sub_ddmmss(n1, n0, n1, n0, d1, d0);
- } else
- q0 = 0;
-
- q1 = 0;
-
- if (rp != 0) {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- } else {
- uint32_t m1, m0;
- /* Normalize. */
-
- b = 32 - bm;
-
- d1 = (d1 << bm) | (d0 >> b);
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd(q0, n1, n2, n1, d1);
- umul_ppmm(m1, m0, q0, d0);
-
- if (m1 > n1 || (m1 == n1 && m0 > n0)) {
- q0--;
- sub_ddmmss(m1, m0, m1, m0, d1, d0);
- }
-
- q1 = 0;
-
- /* Remainder in (n1n0 - m1m0) >> bm. */
- if (rp != 0) {
- sub_ddmmss(n1, n0, n1, n0, m1, m0);
- rr.s.low = (n1 << b) | (n0 >> bm);
- rr.s.high = n1 >> bm;
- *rp = rr.ll;
- }
- }
- }
- }
-
- const DWunion ww = {{.low = q0, .high = q1}};
- return ww.ll;
-}
-
-int64_t
-__divdi3(int64_t u, int64_t v)
-{
- int32_t c = 0;
- DWunion uu = {.ll = u};
- DWunion vv = {.ll = v};
- int64_t w;
-
- if (uu.s.high < 0) {
- c = ~c;
- uu.ll = -uu.ll;
- }
- if (vv.s.high < 0) {
- c = ~c;
- vv.ll = -vv.ll;
- }
-
- w = __udivmoddi4(uu.ll, vv.ll, (uint64_t *)0);
- if (c)
- w = -w;
-
- return w;
-}
-
-int64_t
-__gnu_ldivmod_helper (int64_t a, int64_t b, int64_t *remainder)
-{
- int64_t quotient;
-
- quotient = __divdi3(a, b);
- *remainder = a - b * quotient;
- return quotient;
-}
-
-uint64_t
-__udivdi3(uint64_t n, uint64_t d)
-{
- return __udivmoddi4(n, d, (uint64_t *)0);
-}
-
-uint64_t
-__gnu_uldivmod_helper(uint64_t a, uint64_t b, uint64_t *remainder)
-{
- uint64_t quotient;
-
- quotient = __udivdi3(a, b);
- *remainder = a - b * quotient;
- return quotient;
-}
-
-#endif
diff --git a/src/arch/arm/libgcc/bpabi_asm.S b/src/arch/arm/libgcc/bpabi_asm.S
deleted file mode 100644
index 27b4a1cfe8..0000000000
--- a/src/arch/arm/libgcc/bpabi_asm.S
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Miscellaneous BPABI functions.
-
- Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
- Contributed by CodeSourcery, LLC.
-
- This file 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, or (at your option) any
- later version.
-
- In addition to the permissions in the GNU General Public License, the
- Free Software Foundation gives you unlimited permission to link the
- compiled version of this file into combinations with other programs,
- and to distribute those combinations without any restriction coming
- from the use of this file. (The General Public License restrictions
- do apply in other respects; for example, they cover modification of
- the file, and distribution when not linked into a combine
- executable.)
-
- This file is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-
-#include <arch/asm.h>
-
-#ifdef __ARMEB__
-#define xxh r0
-#define xxl r1
-#define yyh r2
-#define yyl r3
-#else
-#define xxh r1
-#define xxl r0
-#define yyh r3
-#define yyl r2
-#endif
-
-#if defined __thumb2__
-
-.macro do_it cond
- it \cond
-.endm
-#define do_push push
-#define do_pop pop
-
-#else
-
-.macro do_it cond
-.endm
-#define do_push stmfd sp!,
-#define do_pop ldmfd sp!,
-
-#endif
-
-ENTRY(__aeabi_lcmp)
-
- cmp xxh, yyh
- do_it lt
- movlt r0, #-1
- do_it gt
- movgt r0, #1
- do_it ne
- movne pc, lr
- subs r0, xxl, yyl
- do_it lo
- movlo r0, #-1
- do_it hi
- movhi r0, #1
- mov pc, lr
-
-ENDPROC(__aeabi_lcmp)
-
-ENTRY(__aeabi_ulcmp)
-
- cmp xxh, yyh
- do_it lo
- movlo r0, #-1
- do_it hi
- movhi r0, #1
- do_it ne
- movne pc, lr
- cmp xxl, yyl
- do_it lo
- movlo r0, #-1
- do_it hi
- movhi r0, #1
- do_it eq
- moveq r0, #0
- mov pc, lr
-
-ENDPROC(__aeabi_ulcmp)
-
-ENTRY(__aeabi_ldivmod)
- sub sp, sp, #8
-#if defined(__thumb2__)
- mov ip, sp
- push {ip, lr}
-#else
- do_push {sp, lr}
-#endif
- bl __gnu_ldivmod_helper
- ldr lr, [sp, #4]
- add sp, sp, #8
- do_pop {r2, r3}
- mov pc, lr
-
-ENDPROC(__aeabi_ldivmod)
-
-ENTRY(__aeabi_uldivmod)
- sub sp, sp, #8
-#if defined(__thumb2__)
- mov ip, sp
- push {ip, lr}
-#else
- do_push {sp, lr}
-#endif
- bl __gnu_uldivmod_helper
- ldr lr, [sp, #4]
- add sp, sp, #8
- do_pop {r2, r3}
- mov pc, lr
-
-ENDPROC(__aeabi_uldivmod)
diff --git a/src/arch/arm/libgcc/uldivmod.S b/src/arch/arm/libgcc/uldivmod.S
index ac267d006e..521a5d1e33 100644
--- a/src/arch/arm/libgcc/uldivmod.S
+++ b/src/arch/arm/libgcc/uldivmod.S
@@ -55,8 +55,12 @@ Q_1 .req r1
R_0 .req r2
R_1 .req r3
+THUMB(
+TMP .req r8
+)
+
ENTRY(__aeabi_uldivmod)
- stmfd sp!, {r4, r5, r6, r7, lr}
+ stmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) lr}
@ Test if B == 0
orrs ip, B_0, B_1 @ Z set -> B == 0
beq L_div_by_0
@@ -92,12 +96,16 @@ L_div_64_64:
subs D_1, D_0, #32
rsb ip, D_0, #32
movmi B_1, B_1, lsl D_0
- orrmi B_1, B_1, B_0, lsr ip
+ARM( orrmi B_1, B_1, B_0, lsr ip )
+THUMB( lsrmi TMP, B_0, ip )
+THUMB( orrmi B_1, B_1, TMP )
movpl B_1, B_0, lsl D_1
mov B_0, B_0, lsl D_0
@ C = 1 << (clz B - clz A)
movmi C_1, C_1, lsl D_0
- orrmi C_1, C_1, C_0, lsr ip
+ARM( orrmi C_1, C_1, C_0, lsr ip )
+THUMB( lsrmi TMP, C_0, ip )
+THUMB( orrmi C_1, C_1, TMP )
movpl C_1, C_0, lsl D_1
mov C_0, C_0, lsl D_0
L_done_shift:
@@ -170,7 +178,7 @@ L_exit:
mov R_1, A_1
mov Q_0, D_0
mov Q_1, D_1
- ldmfd sp!, {r4, r5, r6, r7, pc}
+ ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
L_div_32_32:
@ Note: A_0 & r0 are aliases
@@ -180,7 +188,7 @@ L_div_32_32:
mov R_0, r1
mov R_1, #0
mov Q_1, #0
- ldmfd sp!, {r4, r5, r6, r7, pc}
+ ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
L_pow2:
/* CLZ only exists in ARM architecture version 5 and above. */
@@ -201,12 +209,14 @@ L_pow2:
add D_0, D_0, #32
L_1:
movpl A_0, A_0, lsr D_0
- orrpl A_0, A_0, A_1, lsl D_1
+ARM( orrpl A_0, A_0, A_1, lsl D_1 )
+THUMB( lslpl TMP, A_1, D_1 )
+THUMB( orrpl A_0, A_0, TMP )
mov A_1, A_1, lsr D_0
@ Mov back C to R
mov R_0, C_0
mov R_1, C_1
- ldmfd sp!, {r4, r5, r6, r7, pc}
+ ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
#else
@ Note: A, B and Q, R are aliases
@ R = A & (B - 1)
@@ -244,7 +254,7 @@ L_1:
@ Move C to R
mov R_0, C_0
mov R_1, C_1
- ldmfd sp!, {r4, r5, r6, r7, pc}
+ ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
#endif
L_div_by_0:
@@ -254,5 +264,5 @@ L_div_by_0:
mov Q_1, #0
mov R_0, #0
mov R_1, #0
- ldmfd sp!, {r4, r5, r6, r7, pc}
+ ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc}
ENDPROC(__aeabi_uldivmod)