From a67ef280f46803e319639f5380ff8da6c6b7fbe7 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:20 +0300 Subject: 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 --- arch/arc/lib/libgcc2.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 arch/arc/lib/libgcc2.c (limited to 'arch/arc/lib/libgcc2.c') 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); +} -- cgit v1.1