aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/arc/lib/libgcc2.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/arc/lib/libgcc2.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/arc/lib/libgcc2.c')
-rw-r--r--roms/u-boot/arch/arc/lib/libgcc2.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arc/lib/libgcc2.c b/roms/u-boot/arch/arc/lib/libgcc2.c
new file mode 100644
index 000000000..ab1dbe1c1
--- /dev/null
+++ b/roms/u-boot/arch/arc/lib/libgcc2.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ */
+
+#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);
+}
+
+UDWtype
+__udivmoddi4(UDWtype n, UDWtype d, UDWtype *rp)
+{
+ UDWtype q = 0, r = n, y = d;
+ UWtype lz1, lz2, i, k;
+
+ /*
+ * Implements align divisor shift dividend method. This algorithm
+ * aligns the divisor under the dividend and then perform number of
+ * test-subtract iterations which shift the dividend left. Number of
+ * iterations is k + 1 where k is the number of bit positions the
+ * divisor must be shifted left to align it under the dividend.
+ * quotient bits can be saved in the rightmost positions of the
+ * dividend as it shifts left on each test-subtract iteration.
+ */
+
+ if (y <= r) {
+ lz1 = __builtin_clzll(d);
+ lz2 = __builtin_clzll(n);
+
+ k = lz1 - lz2;
+ y = (y << k);
+
+ /*
+ * Dividend can exceed 2 ^ (width - 1) - 1 but still be less
+ * than the aligned divisor. Normal iteration can drops the
+ * high order bit of the dividend. Therefore, first
+ * test-subtract iteration is a special case, saving its
+ * quotient bit in a separate location and not shifting
+ * the dividend.
+ */
+
+ if (r >= y) {
+ r = r - y;
+ q = (1ULL << k);
+ }
+
+ if (k > 0) {
+ y = y >> 1;
+
+ /*
+ * k additional iterations where k regular test
+ * subtract shift dividend iterations are done.
+ */
+ i = k;
+ do {
+ if (r >= y)
+ r = ((r - y) << 1) + 1;
+ else
+ r = (r << 1);
+ i = i - 1;
+ } while (i != 0);
+
+ /*
+ * First quotient bit is combined with the quotient
+ * bits resulting from the k regular iterations.
+ */
+ q = q + r;
+ r = r >> k;
+ q = q - (r << k);
+ }
+ }
+
+ if (rp)
+ *rp = r;
+
+ return q;
+}
+
+UDWtype
+__udivdi3(UDWtype n, UDWtype d)
+{
+ return __udivmoddi4(n, d, (UDWtype *)0);
+}