summaryrefslogtreecommitdiff
path: root/arch/arc/lib/libgcc2.c
diff options
context:
space:
mode:
authorAlexey Brodkin <abrodkin@synopsys.com>2015-02-03 13:58:20 +0300
committerAlexey Brodkin <abrodkin@synopsys.com>2015-02-09 16:41:20 +0300
commita67ef280f46803e319639f5380ff8da6c6b7fbe7 (patch)
tree420a2667834a71aca4a714b8fe0c93968fdf4696 /arch/arc/lib/libgcc2.c
parent51f4999bc5ad5f8430da0297d12c1abef9c05568 (diff)
downloadu-boot-imx-a67ef280f46803e319639f5380ff8da6c6b7fbe7.zip
u-boot-imx-a67ef280f46803e319639f5380ff8da6c6b7fbe7.tar.gz
u-boot-imx-a67ef280f46803e319639f5380ff8da6c6b7fbe7.tar.bz2
arc: build libgcc in U-Boot
This way we may have very limited set of functions implemented so we save some space. Also it allows us to build U-Boot for any ARC core with the same one toolchain because we don't rely on pre-built libgcc. For example: * we may use little-endian toolchain but build U-Boot for ether endianess * we may use non-multilibbed uClibc toolchain but build U-Boot for whatever ARC CPU flavour that current GCC supports Private libgcc built from generic C implementation contributes only 144 bytes to .text section so we don't see significant degradation of size: --->8--- $ arc-linux-size u-boot.libgcc-prebuilt text data bss dec hex filename 222217 24912 214820 461949 70c7d u-boot.libgcc-prebuilt $ arc-linux-size u-boot.libgcc-private text data bss dec hex filename 222361 24912 214820 462093 70d0d u-boot.libgcc-private --->8--- Also I don't notice visible performance degradation compared to pre-built libgcc (where at least "*div*" functions are had-written in assembly) on typical operations of downloading 10Mb uImage over TFTP and bootm. Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Diffstat (limited to 'arch/arc/lib/libgcc2.c')
-rw-r--r--arch/arc/lib/libgcc2.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c
new file mode 100644
index 0000000..d5ad327
--- /dev/null
+++ b/arch/arc/lib/libgcc2.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "libgcc2.h"
+
+DWtype
+__ashldi3(DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = W_TYPE_SIZE - b;
+ DWunion w;
+
+ if (bm <= 0) {
+ w.s.low = 0;
+ w.s.high = (UWtype)uu.s.low << -bm;
+ } else {
+ const UWtype carries = (UWtype) uu.s.low >> bm;
+
+ w.s.low = (UWtype)uu.s.low << b;
+ w.s.high = ((UWtype)uu.s.high << b) | carries;
+ }
+
+ return w.ll;
+}
+
+DWtype
+__ashrdi3(DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = W_TYPE_SIZE - b;
+ DWunion w;
+
+ if (bm <= 0) {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
+ w.s.low = uu.s.high >> -bm;
+ } else {
+ const UWtype carries = (UWtype) uu.s.high << bm;
+
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((UWtype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+
+DWtype
+__lshrdi3(DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = W_TYPE_SIZE - b;
+ DWunion w;
+
+ if (bm <= 0) {
+ w.s.high = 0;
+ w.s.low = (UWtype)uu.s.high >> -bm;
+ } else {
+ const UWtype carries = (UWtype)uu.s.high << bm;
+
+ w.s.high = (UWtype)uu.s.high >> b;
+ w.s.low = ((UWtype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+
+unsigned long
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
+{
+ unsigned long bit = 1;
+ unsigned long res = 0;
+
+ while (den < num && bit && !(den & (1L<<31))) {
+ den <<= 1;
+ bit <<= 1;
+ }
+
+ while (bit) {
+ if (num >= den) {
+ num -= den;
+ res |= bit;
+ }
+ bit >>= 1;
+ den >>= 1;
+ }
+
+ if (modwanted)
+ return num;
+
+ return res;
+}
+
+long
+__divsi3(long a, long b)
+{
+ int neg = 0;
+ long res;
+
+ if (a < 0) {
+ a = -a;
+ neg = !neg;
+ }
+
+ if (b < 0) {
+ b = -b;
+ neg = !neg;
+ }
+
+ res = udivmodsi4(a, b, 0);
+
+ if (neg)
+ res = -res;
+
+ return res;
+}
+
+long
+__modsi3(long a, long b)
+{
+ int neg = 0;
+ long res;
+
+ if (a < 0) {
+ a = -a;
+ neg = 1;
+ }
+
+ if (b < 0)
+ b = -b;
+
+ res = udivmodsi4(a, b, 1);
+
+ if (neg)
+ res = -res;
+
+ return res;
+}
+
+long
+__udivsi3(long a, long b)
+{
+ return udivmodsi4(a, b, 0);
+}
+
+long
+__umodsi3(long a, long b)
+{
+ return udivmodsi4(a, b, 1);
+}