xref: /openbmc/u-boot/arch/arc/lib/libgcc2.c (revision c978b524)
1 /*
2  * Copyright (C) 1989-2013 Free Software Foundation, Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include "libgcc2.h"
8 
9 DWtype
10 __ashldi3(DWtype u, shift_count_type b)
11 {
12 	if (b == 0)
13 		return u;
14 
15 	const DWunion uu = {.ll = u};
16 	const shift_count_type bm = W_TYPE_SIZE - b;
17 	DWunion w;
18 
19 	if (bm <= 0) {
20 		w.s.low = 0;
21 		w.s.high = (UWtype)uu.s.low << -bm;
22 	} else {
23 		const UWtype carries = (UWtype) uu.s.low >> bm;
24 
25 		w.s.low = (UWtype)uu.s.low << b;
26 		w.s.high = ((UWtype)uu.s.high << b) | carries;
27 	}
28 
29 	return w.ll;
30 }
31 
32 DWtype
33 __ashrdi3(DWtype u, shift_count_type b)
34 {
35 	if (b == 0)
36 		return u;
37 
38 	const DWunion uu = {.ll = u};
39 	const shift_count_type bm = W_TYPE_SIZE - b;
40 	DWunion w;
41 
42 	if (bm <= 0) {
43 		/* w.s.high = 1..1 or 0..0 */
44 		w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
45 		w.s.low = uu.s.high >> -bm;
46 	} else {
47 		const UWtype carries = (UWtype) uu.s.high << bm;
48 
49 		w.s.high = uu.s.high >> b;
50 		w.s.low = ((UWtype)uu.s.low >> b) | carries;
51 	}
52 
53 	return w.ll;
54 }
55 
56 DWtype
57 __lshrdi3(DWtype u, shift_count_type b)
58 {
59 	if (b == 0)
60 		return u;
61 
62 	const DWunion uu = {.ll = u};
63 	const shift_count_type bm = W_TYPE_SIZE - b;
64 	DWunion w;
65 
66 	if (bm <= 0) {
67 		w.s.high = 0;
68 		w.s.low = (UWtype)uu.s.high >> -bm;
69 	} else {
70 		const UWtype carries = (UWtype)uu.s.high << bm;
71 
72 		w.s.high = (UWtype)uu.s.high >> b;
73 		w.s.low = ((UWtype)uu.s.low >> b) | carries;
74 	}
75 
76 	return w.ll;
77 }
78 
79 unsigned long
80 udivmodsi4(unsigned long num, unsigned long den, int modwanted)
81 {
82 	unsigned long bit = 1;
83 	unsigned long res = 0;
84 
85 	while (den < num && bit && !(den & (1L<<31))) {
86 		den <<= 1;
87 		bit <<= 1;
88 	}
89 
90 	while (bit) {
91 		if (num >= den) {
92 			num -= den;
93 			res |= bit;
94 		}
95 		bit >>= 1;
96 		den >>= 1;
97 	}
98 
99 	if (modwanted)
100 		return num;
101 
102 	return res;
103 }
104 
105 long
106 __divsi3(long a, long b)
107 {
108 	int neg = 0;
109 	long res;
110 
111 	if (a < 0) {
112 		a = -a;
113 		neg = !neg;
114 	}
115 
116 	if (b < 0) {
117 		b = -b;
118 		neg = !neg;
119 	}
120 
121 	res = udivmodsi4(a, b, 0);
122 
123 	if (neg)
124 		res = -res;
125 
126 	return res;
127 }
128 
129 long
130 __modsi3(long a, long b)
131 {
132 	int neg = 0;
133 	long res;
134 
135 	if (a < 0) {
136 		a = -a;
137 		neg = 1;
138 	}
139 
140 	if (b < 0)
141 		b = -b;
142 
143 	res = udivmodsi4(a, b, 1);
144 
145 	if (neg)
146 		res = -res;
147 
148 	return res;
149 }
150 
151 long
152 __udivsi3(long a, long b)
153 {
154 	return udivmodsi4(a, b, 0);
155 }
156 
157 long
158 __umodsi3(long a, long b)
159 {
160 	return udivmodsi4(a, b, 1);
161 }
162