]>
Commit | Line | Data |
---|---|---|
fbd26352 | 1 | /* Copyright (C) 2014-2019 Free Software Foundation, Inc. |
8992df51 | 2 | |
3 | This file is part of GCC. | |
4 | ||
5 | GCC is free software; you can redistribute it and/or modify it under | |
6 | the terms of the GNU General Public License as published by the Free | |
7 | Software Foundation; either version 3, or (at your option) any later | |
8 | version. | |
9 | ||
10 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | for more details. | |
14 | ||
15 | Under Section 7 of GPL version 3, you are granted additional | |
16 | permissions described in the GCC Runtime Library Exception, version | |
17 | 3.1, as published by the Free Software Foundation. | |
18 | ||
19 | You should have received a copy of the GNU General Public License and | |
20 | a copy of the GCC Runtime Library Exception along with this program; | |
21 | see 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)) | |
107 | static inline __attribute__ ((__always_inline__)) | |
108 | #endif | |
109 | UDWtype | |
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 | |
232 | DWtype | |
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 | |
256 | DWtype | |
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 | |
279 | UDWtype | |
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 | |
291 | UDWtype | |
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 | |
300 | extern void __set_trampoline_parity (UWtype *); | |
301 | ||
302 | static inline UWtype | |
303 | parity_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 | ||
313 | void | |
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 */ |