]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/visium/lib2funcs.c
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / visium / lib2funcs.c
CommitLineData
fbd26352 1/* Copyright (C) 2014-2019 Free Software Foundation, Inc.
8992df51 2
3This file is part of GCC.
4
5GCC is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License as published by the Free
7Software Foundation; either version 3, or (at your option) any later
8version.
9
10GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or
12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13for more details.
14
15Under Section 7 of GPL version 3, you are granted additional
16permissions described in the GCC Runtime Library Exception, version
173.1, as published by the Free Software Foundation.
18
19You should have received a copy of the GNU General Public License and
20a copy of the GCC Runtime Library Exception along with this program;
21see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
22<http://www.gnu.org/licenses/>. */
23
24#include "tconfig.h"
25#include "tsystem.h"
26#include "coretypes.h"
27#include "tm.h"
28#include "libgcc_tm.h"
29
30#ifdef HAVE_GAS_HIDDEN
31#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
32#else
33#define ATTRIBUTE_HIDDEN
34#endif
35
36/* Work out the largest "word" size that we can deal with on this target. */
37#if MIN_UNITS_PER_WORD > 4
38# define LIBGCC2_MAX_UNITS_PER_WORD 8
39#elif (MIN_UNITS_PER_WORD > 2 \
40 || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
41# define LIBGCC2_MAX_UNITS_PER_WORD 4
42#else
43# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
44#endif
45
46/* Work out what word size we are using for this compilation.
47 The value can be set on the command line. */
48#ifndef LIBGCC2_UNITS_PER_WORD
49#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
50#endif
51
52#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
53
54#include "libgcc2.h"
55
56/* umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two
57 UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype
58 word product in HIGH_PROD and LOW_PROD. */
59
60#undef umul_ppmm
61#define umul_ppmm(wh, wl, u, v) \
62 do { \
63 /* Generate multu instruction. */ \
64 UDWtype __t = (UDWtype)(u) * (UDWtype)(v); \
65 (wl) = (UWtype)__t; \
66 (wh) = (UWtype)(__t >> W_TYPE_SIZE); \
67 } while (0)
68
69/* sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
70 high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
71 composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
72 LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
73 and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
74 and is lost. */
75
76#undef sub_ddmmss
77#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
78 __asm__ ("sub.l %0,%2,%4\n\t" \
79 "subc.l %1,%3,%5" \
80 : "=&r" (sl), "=r" (sh) \
81 : "r" (al), "r" (ah), "r" (bl), "r" (bh))
82
83/* udiv_qqrnnd(high_quotient, low_quotient, remainder, high_numerator,
84 low_numerator, denominator) divides a UDWtype, composed by the UWtype
85 HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
86 in QUOTIENT and the remainder in REMAINDER. */
87
88#define udiv_qqrnnd(qh, ql, r, nh, nl, d) \
89 __asm__ ("writemd %3,%4\n\t" \
90 "divdu %5\n\t" \
91 "readmda %0\n\t" \
92 "readmdb %1\n\t" \
93 "readmdc %2" \
94 : "=r" (ql), "=r" (qh), "=r" (r) \
95 : "r" (nl), "r" (nh), "r" (d) \
96 : "mdb", "mdc")
97\f
98#if (defined (L_udivdi3) || defined (L_divdi3) || \
99 defined (L_umoddi3) || defined (L_moddi3))
100#define L_udivmoddi4
101#endif
102\f
103#ifdef L_udivmoddi4
104
105#if (defined (L_udivdi3) || defined (L_divdi3) || \
106 defined (L_umoddi3) || defined (L_moddi3))
107static inline __attribute__ ((__always_inline__))
108#endif
109UDWtype
110__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
111{
112 const DWunion nn = {.ll = n};
113 const DWunion dd = {.ll = d};
114 DWunion rr;
115 UWtype d0, d1, n0, n1, n2;
116 UWtype q0, q1;
117 UWtype b, bm;
118
119 d0 = dd.s.low;
120 d1 = dd.s.high;
121 n0 = nn.s.low;
122 n1 = nn.s.high;
123
124 if (d1 == 0)
125 {
126 /* qq = NN / 0d */
127
128 if (d0 == 0)
129 d0 = 1 / d0; /* Divide intentionally by zero. */
130
131 udiv_qqrnnd (q1, q0, n0, n1, n0, d0);
132
133 /* Remainder in n0. */
134
135 if (rp != 0)
136 {
137 rr.s.low = n0;
138 rr.s.high = 0;
139 *rp = rr.ll;
140 }
141 }
142
143 else
144 {
145 if (d1 > n1)
146 {
147 /* 00 = nn / DD */
148
149 q0 = 0;
150 q1 = 0;
151
152 /* Remainder in n1n0. */
153 if (rp != 0)
154 {
155 rr.s.low = n0;
156 rr.s.high = n1;
157 *rp = rr.ll;
158 }
159 }
160 else
161 {
162 /* 0q = NN / dd */
163
164 count_leading_zeros (bm, d1);
165 if (bm == 0)
166 {
167 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
168 conclude (the most significant bit of n1 is set) /\ (the
169 quotient digit q0 = 0 or 1).
170
171 This special case is necessary, not an optimization. */
172
173 /* The condition on the next line takes advantage of that
174 n1 >= d1 (true due to program flow). */
175 if (n1 > d1 || n0 >= d0)
176 {
177 q0 = 1;
178 sub_ddmmss (n1, n0, n1, n0, d1, d0);
179 }
180 else
181 q0 = 0;
182
183 q1 = 0;
184
185 if (rp != 0)
186 {
187 rr.s.low = n0;
188 rr.s.high = n1;
189 *rp = rr.ll;
190 }
191 }
192 else
193 {
194 UWtype m1, m0;
195 /* Normalize. */
196
197 b = W_TYPE_SIZE - bm;
198
199 d1 = (d1 << bm) | (d0 >> b);
200 d0 = d0 << bm;
201 n2 = n1 >> b;
202 n1 = (n1 << bm) | (n0 >> b);
203 n0 = n0 << bm;
204
205 udiv_qqrnnd (q1, q0, n1, n2, n1, d1);
206 umul_ppmm (m1, m0, q0, d0);
207
208 if (m1 > n1 || (m1 == n1 && m0 > n0))
209 {
210 q0--;
211 sub_ddmmss (m1, m0, m1, m0, d1, d0);
212 }
213
214 /* Remainder in (n1n0 - m1m0) >> bm. */
215 if (rp != 0)
216 {
217 sub_ddmmss (n1, n0, n1, n0, m1, m0);
218 rr.s.low = (n1 << b) | (n0 >> bm);
219 rr.s.high = n1 >> bm;
220 *rp = rr.ll;
221 }
222 }
223 }
224 }
225
226 const DWunion ww = {{.low = q0, .high = q1}};
227 return ww.ll;
228}
229#endif
230
231#ifdef L_divdi3
232DWtype
233__divdi3 (DWtype u, DWtype v)
234{
235 Wtype c = 0;
236 DWunion uu = {.ll = u};
237 DWunion vv = {.ll = v};
238 DWtype w;
239
240 if (uu.s.high < 0)
241 c = ~c,
242 uu.ll = -uu.ll;
243 if (vv.s.high < 0)
244 c = ~c,
245 vv.ll = -vv.ll;
246
247 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
248 if (c)
249 w = -w;
250
251 return w;
252}
253#endif
254
255#ifdef L_moddi3
256DWtype
257__moddi3 (DWtype u, DWtype v)
258{
259 Wtype c = 0;
260 DWunion uu = {.ll = u};
261 DWunion vv = {.ll = v};
262 DWtype w;
263
264 if (uu.s.high < 0)
265 c = ~c,
266 uu.ll = -uu.ll;
267 if (vv.s.high < 0)
268 vv.ll = -vv.ll;
269
270 (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
271 if (c)
272 w = -w;
273
274 return w;
275}
276#endif
277
278#ifdef L_umoddi3
279UDWtype
280__umoddi3 (UDWtype u, UDWtype v)
281{
282 UDWtype w;
283
284 (void) __udivmoddi4 (u, v, &w);
285
286 return w;
287}
288#endif
289
290#ifdef L_udivdi3
291UDWtype
292__udivdi3 (UDWtype n, UDWtype d)
293{
294 return __udivmoddi4 (n, d, (UDWtype *) 0);
295}
296#endif
297\f
298#ifdef L_set_trampoline_parity
299#undef int
300extern void __set_trampoline_parity (UWtype *);
301
302static inline UWtype
303parity_bit (UWtype x)
304{
305 x ^= x << 16;
306 x ^= x << 8;
307 x ^= x << 4;
308 x ^= x << 2;
309 x ^= x << 1;
310 return x & ((UWtype) 1 << (W_TYPE_SIZE - 1));
311}
312
313void
314__set_trampoline_parity (UWtype *addr)
315{
316 int i;
317
d2dc729f 318 for (i = 0; i < (TRAMPOLINE_SIZE * __CHAR_BIT__) / W_TYPE_SIZE; i++)
8992df51 319 addr[i] |= parity_bit (addr[i]);
320}
321#endif
322\f
323#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */