aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 19:20:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 19:20:28 -0400
commit3dca04d694f16cc74dc87de9a13547e2ffec81d7 (patch)
tree7853d982b1c726fdfd6434dfccbb1ff158b8411c /lib
parent9bb9d4fdce9e6b351b7b905f150745a0fccccc06 (diff)
parentef70696a63c773280ef46f5764a6cda39ef2f383 (diff)
Merge tag 'riscv-for-linus-4.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux
Pull more RISC-V updates from Palmer Dabbelt: "This contains the follow-on patches I'd like to target for the 4.20 merge window. I'm being somewhat conservative here, as while there are a few patches on the mailing list that were posted early in the merge window I'd like to let those bake for another round -- this was a fairly big release as far as RISC-V is concerened, and we need to walk before we can run. As far as the patches that made it go: - A patch to ignore offline CPUs when calculating AT_HWCAP. This should fix GDB on the HiFive unleashed, which has an embedded core for hart 0 which is exposed to Linux as an offline CPU. - A move of EM_RISCV to elf-em.h, which is where it should have been to begin with. - I've also removed the 64-bit divide routines. I know I'm not really playing by my own rules here because I posted the patches this morning, but since they shouldn't be in the kernel I think it's better to err on the side of going too fast here. I don't anticipate any more patch sets for the merge window" * tag 'riscv-for-linus-4.20-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux: Move EM_RISCV into elf-em.h RISC-V: properly determine hardware caps Revert "lib: Add umoddi3 and udivmoddi4 of GCC library routines" Revert "RISC-V: Select GENERIC_LIB_UMODDI3 on RV32"
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile1
-rw-r--r--lib/udivmoddi4.c310
-rw-r--r--lib/umoddi3.c32
4 files changed, 0 insertions, 346 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index d1573a16aa92..a9965f4af4dd 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -624,6 +624,3 @@ config GENERIC_LIB_CMPDI2
624 624
625config GENERIC_LIB_UCMPDI2 625config GENERIC_LIB_UCMPDI2
626 bool 626 bool
627
628config GENERIC_LIB_UMODDI3
629 bool
diff --git a/lib/Makefile b/lib/Makefile
index 988949c4fd3a..db06d1237898 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -274,4 +274,3 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
274obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o 274obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
275obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o 275obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
276obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o 276obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
277obj-$(CONFIG_GENERIC_LIB_UMODDI3) += umoddi3.o udivmoddi4.o
diff --git a/lib/udivmoddi4.c b/lib/udivmoddi4.c
deleted file mode 100644
index c08bc8a5f1cf..000000000000
--- a/lib/udivmoddi4.c
+++ /dev/null
@@ -1,310 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see the file COPYING, or write
16 * to the Free Software Foundation, Inc.
17 */
18
19#include <linux/libgcc.h>
20
21#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz(X))
22
23#define W_TYPE_SIZE 32
24
25#define __ll_B ((unsigned long) 1 << (W_TYPE_SIZE / 2))
26#define __ll_lowpart(t) ((unsigned long) (t) & (__ll_B - 1))
27#define __ll_highpart(t) ((unsigned long) (t) >> (W_TYPE_SIZE / 2))
28
29/* If we still don't have umul_ppmm, define it using plain C. */
30#if !defined(umul_ppmm)
31#define umul_ppmm(w1, w0, u, v) \
32 do { \
33 unsigned long __x0, __x1, __x2, __x3; \
34 unsigned short __ul, __vl, __uh, __vh; \
35 \
36 __ul = __ll_lowpart(u); \
37 __uh = __ll_highpart(u); \
38 __vl = __ll_lowpart(v); \
39 __vh = __ll_highpart(v); \
40 \
41 __x0 = (unsigned long) __ul * __vl; \
42 __x1 = (unsigned long) __ul * __vh; \
43 __x2 = (unsigned long) __uh * __vl; \
44 __x3 = (unsigned long) __uh * __vh; \
45 \
46 __x1 += __ll_highpart(__x0); \
47 __x1 += __x2; \
48 if (__x1 < __x2) \
49 __x3 += __ll_B; \
50 \
51 (w1) = __x3 + __ll_highpart(__x1); \
52 (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\
53 } while (0)
54#endif
55
56#if !defined(sub_ddmmss)
57#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
58 do { \
59 unsigned long __x; \
60 __x = (al) - (bl); \
61 (sh) = (ah) - (bh) - (__x > (al)); \
62 (sl) = __x; \
63 } while (0)
64#endif
65
66/* Define this unconditionally, so it can be used for debugging. */
67#define __udiv_qrnnd_c(q, r, n1, n0, d) \
68 do { \
69 unsigned long __d1, __d0, __q1, __q0; \
70 unsigned long __r1, __r0, __m; \
71 __d1 = __ll_highpart(d); \
72 __d0 = __ll_lowpart(d); \
73 \
74 __r1 = (n1) % __d1; \
75 __q1 = (n1) / __d1; \
76 __m = (unsigned long) __q1 * __d0; \
77 __r1 = __r1 * __ll_B | __ll_highpart(n0); \
78 if (__r1 < __m) { \
79 __q1--, __r1 += (d); \
80 if (__r1 >= (d)) \
81 if (__r1 < __m) \
82 __q1--, __r1 += (d); \
83 } \
84 __r1 -= __m; \
85 \
86 __r0 = __r1 % __d1; \
87 __q0 = __r1 / __d1; \
88 __m = (unsigned long) __q0 * __d0; \
89 __r0 = __r0 * __ll_B | __ll_lowpart(n0); \
90 if (__r0 < __m) { \
91 __q0--, __r0 += (d); \
92 if (__r0 >= (d)) \
93 if (__r0 < __m) \
94 __q0--, __r0 += (d); \
95 } \
96 __r0 -= __m; \
97 \
98 (q) = (unsigned long) __q1 * __ll_B | __q0; \
99 (r) = __r0; \
100 } while (0)
101
102/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
103#if !defined(udiv_qrnnd)
104#define UDIV_NEEDS_NORMALIZATION 1
105#define udiv_qrnnd __udiv_qrnnd_c
106#endif
107
108unsigned long long __udivmoddi4(unsigned long long u, unsigned long long v,
109 unsigned long long *rp)
110{
111 const DWunion nn = {.ll = u };
112 const DWunion dd = {.ll = v };
113 DWunion rr, ww;
114 unsigned long d0, d1, n0, n1, n2;
115 unsigned long q0 = 0, q1 = 0;
116 unsigned long b, bm;
117
118 d0 = dd.s.low;
119 d1 = dd.s.high;
120 n0 = nn.s.low;
121 n1 = nn.s.high;
122
123#if !UDIV_NEEDS_NORMALIZATION
124
125 if (d1 == 0) {
126 if (d0 > n1) {
127 /* 0q = nn / 0D */
128
129 udiv_qrnnd(q0, n0, n1, n0, d0);
130 q1 = 0;
131
132 /* Remainder in n0. */
133 } else {
134 /* qq = NN / 0d */
135
136 if (d0 == 0)
137 /* Divide intentionally by zero. */
138 d0 = 1 / d0;
139
140 udiv_qrnnd(q1, n1, 0, n1, d0);
141 udiv_qrnnd(q0, n0, n1, n0, d0);
142
143 /* Remainder in n0. */
144 }
145
146 if (rp != 0) {
147 rr.s.low = n0;
148 rr.s.high = 0;
149 *rp = rr.ll;
150 }
151
152#else /* UDIV_NEEDS_NORMALIZATION */
153
154 if (d1 == 0) {
155 if (d0 > n1) {
156 /* 0q = nn / 0D */
157
158 count_leading_zeros(bm, d0);
159
160 if (bm != 0) {
161 /*
162 * Normalize, i.e. make the most significant bit
163 * of the denominator set.
164 */
165
166 d0 = d0 << bm;
167 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
168 n0 = n0 << bm;
169 }
170
171 udiv_qrnnd(q0, n0, n1, n0, d0);
172 q1 = 0;
173
174 /* Remainder in n0 >> bm. */
175 } else {
176 /* qq = NN / 0d */
177
178 if (d0 == 0)
179 /* Divide intentionally by zero. */
180 d0 = 1 / d0;
181
182 count_leading_zeros(bm, d0);
183
184 if (bm == 0) {
185 /*
186 * From (n1 >= d0) /\ (the most significant bit
187 * of d0 is set), conclude (the most significant
188 * bit of n1 is set) /\ (theleading quotient
189 * digit q1 = 1).
190 *
191 * This special case is necessary, not an
192 * optimization. (Shifts counts of W_TYPE_SIZE
193 * are undefined.)
194 */
195
196 n1 -= d0;
197 q1 = 1;
198 } else {
199 /* Normalize. */
200
201 b = W_TYPE_SIZE - bm;
202
203 d0 = d0 << bm;
204 n2 = n1 >> b;
205 n1 = (n1 << bm) | (n0 >> b);
206 n0 = n0 << bm;
207
208 udiv_qrnnd(q1, n1, n2, n1, d0);
209 }
210
211 /* n1 != d0... */
212
213 udiv_qrnnd(q0, n0, n1, n0, d0);
214
215 /* Remainder in n0 >> bm. */
216 }
217
218 if (rp != 0) {
219 rr.s.low = n0 >> bm;
220 rr.s.high = 0;
221 *rp = rr.ll;
222 }
223
224#endif /* UDIV_NEEDS_NORMALIZATION */
225
226 } else {
227 if (d1 > n1) {
228 /* 00 = nn / DD */
229
230 q0 = 0;
231 q1 = 0;
232
233 /* Remainder in n1n0. */
234 if (rp != 0) {
235 rr.s.low = n0;
236 rr.s.high = n1;
237 *rp = rr.ll;
238 }
239 } else {
240 /* 0q = NN / dd */
241
242 count_leading_zeros(bm, d1);
243 if (bm == 0) {
244 /*
245 * From (n1 >= d1) /\ (the most significant bit
246 * of d1 is set), conclude (the most significant
247 * bit of n1 is set) /\ (the quotient digit q0 =
248 * 0 or 1).
249 *
250 * This special case is necessary, not an
251 * optimization.
252 */
253
254 /*
255 * The condition on the next line takes
256 * advantage of that n1 >= d1 (true due to
257 * program flow).
258 */
259 if (n1 > d1 || n0 >= d0) {
260 q0 = 1;
261 sub_ddmmss(n1, n0, n1, n0, d1, d0);
262 } else {
263 q0 = 0;
264 }
265
266 q1 = 0;
267
268 if (rp != 0) {
269 rr.s.low = n0;
270 rr.s.high = n1;
271 *rp = rr.ll;
272 }
273 } else {
274 unsigned long m1, m0;
275 /* Normalize. */
276
277 b = W_TYPE_SIZE - bm;
278
279 d1 = (d1 << bm) | (d0 >> b);
280 d0 = d0 << bm;
281 n2 = n1 >> b;
282 n1 = (n1 << bm) | (n0 >> b);
283 n0 = n0 << bm;
284
285 udiv_qrnnd(q0, n1, n2, n1, d1);
286 umul_ppmm(m1, m0, q0, d0);
287
288 if (m1 > n1 || (m1 == n1 && m0 > n0)) {
289 q0--;
290 sub_ddmmss(m1, m0, m1, m0, d1, d0);
291 }
292
293 q1 = 0;
294
295 /* Remainder in (n1n0 - m1m0) >> bm. */
296 if (rp != 0) {
297 sub_ddmmss(n1, n0, n1, n0, m1, m0);
298 rr.s.low = (n1 << b) | (n0 >> bm);
299 rr.s.high = n1 >> bm;
300 *rp = rr.ll;
301 }
302 }
303 }
304 }
305
306 ww.s.low = q0;
307 ww.s.high = q1;
308
309 return ww.ll;
310}
diff --git a/lib/umoddi3.c b/lib/umoddi3.c
deleted file mode 100644
index d7bbf0f85197..000000000000
--- a/lib/umoddi3.c
+++ /dev/null
@@ -1,32 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see the file COPYING, or write
16 * to the Free Software Foundation, Inc.
17 */
18
19#include <linux/module.h>
20#include <linux/libgcc.h>
21
22extern unsigned long long __udivmoddi4(unsigned long long u,
23 unsigned long long v,
24 unsigned long long *rp);
25
26unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
27{
28 unsigned long long w;
29 (void)__udivmoddi4(u, v, &w);
30 return w;
31}
32EXPORT_SYMBOL(__umoddi3);