]>
Commit | Line | Data |
---|---|---|
203b91b9 RS |
1 | /* More subroutines needed by GCC output code on some machines. */ |
2 | /* Compile this one with gcc. */ | |
5d0e6486 AO |
3 | /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
4 | 2000, 2001 Free Software Foundation, Inc. | |
203b91b9 | 5 | |
1322177d | 6 | This file is part of GCC. |
203b91b9 | 7 | |
1322177d LB |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free | |
10 | Software Foundation; either version 2, or (at your option) any later | |
11 | version. | |
203b91b9 | 12 | |
f7af368f JL |
13 | In addition to the permissions in the GNU General Public License, the |
14 | Free Software Foundation gives you unlimited permission to link the | |
15 | compiled version of this file into combinations with other programs, | |
16 | and to distribute those combinations without any restriction coming | |
17 | from the use of this file. (The General Public License restrictions | |
18 | do apply in other respects; for example, they cover modification of | |
19 | the file, and distribution when not linked into a combine | |
20 | executable.) | |
21 | ||
1322177d LB |
22 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
23 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
24 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
25 | for more details. | |
203b91b9 RS |
26 | |
27 | You should have received a copy of the GNU General Public License | |
1322177d LB |
28 | along with GCC; see the file COPYING. If not, write to the Free |
29 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
30 | 02111-1307, USA. */ | |
203b91b9 | 31 | |
203b91b9 RS |
32 | /* It is incorrect to include config.h here, because this file is being |
33 | compiled for the target, and hence definitions concerning only the host | |
34 | do not apply. */ | |
35 | ||
0dadecf6 | 36 | #include "tconfig.h" |
2e39bdbe | 37 | #include "tsystem.h" |
2467749d | 38 | |
203b91b9 RS |
39 | /* Don't use `fancy_abort' here even if config.h says to use it. */ |
40 | #ifdef abort | |
41 | #undef abort | |
42 | #endif | |
43 | ||
299b83b7 | 44 | #include "libgcc2.h" |
203b91b9 RS |
45 | \f |
46 | #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) | |
47 | #if defined (L_divdi3) || defined (L_moddi3) | |
48 | static inline | |
49 | #endif | |
3d2adde6 CC |
50 | DWtype |
51 | __negdi2 (DWtype u) | |
52 | { | |
53 | DWunion w; | |
54 | DWunion uu; | |
55 | ||
56 | uu.ll = u; | |
57 | ||
58 | w.s.low = -uu.s.low; | |
59 | w.s.high = -uu.s.high - ((UWtype) w.s.low > 0); | |
60 | ||
61 | return w.ll; | |
62 | } | |
63 | #endif | |
91ce572a CC |
64 | |
65 | #ifdef L_addvsi3 | |
66f77154 MH |
66 | Wtype |
67 | __addvsi3 (Wtype a, Wtype b) | |
91ce572a | 68 | { |
66f77154 | 69 | Wtype w; |
91ce572a CC |
70 | |
71 | w = a + b; | |
72 | ||
73 | if (b >= 0 ? w < a : w > a) | |
74 | abort (); | |
75 | ||
76 | return w; | |
23190837 | 77 | } |
3d2adde6 | 78 | #endif |
91ce572a CC |
79 | \f |
80 | #ifdef L_addvdi3 | |
66f77154 MH |
81 | DWtype |
82 | __addvdi3 (DWtype a, DWtype b) | |
91ce572a | 83 | { |
66f77154 | 84 | DWtype w; |
91ce572a CC |
85 | |
86 | w = a + b; | |
87 | ||
88 | if (b >= 0 ? w < a : w > a) | |
89 | abort (); | |
90 | ||
91 | return w; | |
92 | } | |
93 | #endif | |
94 | \f | |
95 | #ifdef L_subvsi3 | |
66f77154 MH |
96 | Wtype |
97 | __subvsi3 (Wtype a, Wtype b) | |
91ce572a CC |
98 | { |
99 | #ifdef L_addvsi3 | |
100 | return __addvsi3 (a, (-b)); | |
101 | #else | |
66f77154 | 102 | DWtype w; |
91ce572a CC |
103 | |
104 | w = a - b; | |
105 | ||
106 | if (b >= 0 ? w > a : w < a) | |
107 | abort (); | |
108 | ||
109 | return w; | |
110 | #endif | |
111 | } | |
112 | #endif | |
113 | \f | |
114 | #ifdef L_subvdi3 | |
66f77154 MH |
115 | DWtype |
116 | __subvdi3 (DWtype a, DWtype b) | |
91ce572a CC |
117 | { |
118 | #ifdef L_addvdi3 | |
119 | return (a, (-b)); | |
120 | #else | |
66f77154 | 121 | DWtype w; |
91ce572a CC |
122 | |
123 | w = a - b; | |
124 | ||
125 | if (b >= 0 ? w > a : w < a) | |
126 | abort (); | |
127 | ||
128 | return w; | |
129 | #endif | |
130 | } | |
131 | #endif | |
132 | \f | |
133 | #ifdef L_mulvsi3 | |
66f77154 MH |
134 | Wtype |
135 | __mulvsi3 (Wtype a, Wtype b) | |
91ce572a | 136 | { |
66f77154 | 137 | DWtype w; |
91ce572a CC |
138 | |
139 | w = a * b; | |
140 | ||
3cf37281 | 141 | if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0) |
91ce572a CC |
142 | abort (); |
143 | ||
144 | return w; | |
145 | } | |
146 | #endif | |
147 | \f | |
148 | #ifdef L_negvsi2 | |
66f77154 MH |
149 | Wtype |
150 | __negvsi2 (Wtype a) | |
91ce572a | 151 | { |
e11e816e | 152 | Wtype w; |
91ce572a | 153 | |
e11e816e | 154 | w = -a; |
91ce572a CC |
155 | |
156 | if (a >= 0 ? w > 0 : w < 0) | |
157 | abort (); | |
158 | ||
159 | return w; | |
160 | } | |
161 | #endif | |
162 | \f | |
163 | #ifdef L_negvdi2 | |
66f77154 MH |
164 | DWtype |
165 | __negvdi2 (DWtype a) | |
91ce572a | 166 | { |
e11e816e | 167 | DWtype w; |
91ce572a | 168 | |
e11e816e | 169 | w = -a; |
91ce572a CC |
170 | |
171 | if (a >= 0 ? w > 0 : w < 0) | |
172 | abort (); | |
173 | ||
e11e816e | 174 | return w; |
91ce572a CC |
175 | } |
176 | #endif | |
177 | \f | |
178 | #ifdef L_absvsi2 | |
66f77154 MH |
179 | Wtype |
180 | __absvsi2 (Wtype a) | |
91ce572a | 181 | { |
e11e816e | 182 | Wtype w = a; |
91ce572a | 183 | |
e11e816e | 184 | if (a < 0) |
91ce572a | 185 | #ifdef L_negvsi2 |
e11e816e | 186 | w = __negvsi2 (a); |
91ce572a | 187 | #else |
e11e816e | 188 | w = -a; |
91ce572a | 189 | |
e11e816e KH |
190 | if (w < 0) |
191 | abort (); | |
91ce572a CC |
192 | #endif |
193 | ||
194 | return w; | |
195 | } | |
196 | #endif | |
197 | \f | |
198 | #ifdef L_absvdi2 | |
66f77154 MH |
199 | DWtype |
200 | __absvdi2 (DWtype a) | |
91ce572a | 201 | { |
e11e816e | 202 | DWtype w = a; |
91ce572a | 203 | |
e11e816e | 204 | if (a < 0) |
91ce572a | 205 | #ifdef L_negvsi2 |
e11e816e | 206 | w = __negvsi2 (a); |
91ce572a | 207 | #else |
e11e816e | 208 | w = -a; |
91ce572a | 209 | |
e11e816e KH |
210 | if (w < 0) |
211 | abort (); | |
91ce572a CC |
212 | #endif |
213 | ||
e11e816e | 214 | return w; |
91ce572a CC |
215 | } |
216 | #endif | |
217 | \f | |
218 | #ifdef L_mulvdi3 | |
66f77154 MH |
219 | DWtype |
220 | __mulvdi3 (DWtype u, DWtype v) | |
91ce572a | 221 | { |
e11e816e | 222 | DWtype w; |
91ce572a CC |
223 | |
224 | w = u * v; | |
225 | ||
3d2adde6 | 226 | if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0) |
91ce572a CC |
227 | abort (); |
228 | ||
229 | return w; | |
230 | } | |
231 | #endif | |
232 | \f | |
203b91b9 | 233 | |
37ef1054 RK |
234 | /* Unless shift functions are defined whith full ANSI prototypes, |
235 | parameter b will be promoted to int if word_type is smaller than an int. */ | |
203b91b9 | 236 | #ifdef L_lshrdi3 |
996ed075 JJ |
237 | DWtype |
238 | __lshrdi3 (DWtype u, word_type b) | |
203b91b9 | 239 | { |
996ed075 | 240 | DWunion w; |
b799cfc3 | 241 | word_type bm; |
996ed075 | 242 | DWunion uu; |
203b91b9 RS |
243 | |
244 | if (b == 0) | |
245 | return u; | |
246 | ||
247 | uu.ll = u; | |
248 | ||
996ed075 | 249 | bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; |
203b91b9 RS |
250 | if (bm <= 0) |
251 | { | |
252 | w.s.high = 0; | |
6da9c622 | 253 | w.s.low = (UWtype) uu.s.high >> -bm; |
203b91b9 RS |
254 | } |
255 | else | |
256 | { | |
6da9c622 RK |
257 | UWtype carries = (UWtype) uu.s.high << bm; |
258 | ||
259 | w.s.high = (UWtype) uu.s.high >> b; | |
260 | w.s.low = ((UWtype) uu.s.low >> b) | carries; | |
203b91b9 RS |
261 | } |
262 | ||
263 | return w.ll; | |
264 | } | |
265 | #endif | |
266 | ||
267 | #ifdef L_ashldi3 | |
996ed075 JJ |
268 | DWtype |
269 | __ashldi3 (DWtype u, word_type b) | |
203b91b9 | 270 | { |
996ed075 | 271 | DWunion w; |
b799cfc3 | 272 | word_type bm; |
996ed075 | 273 | DWunion uu; |
203b91b9 RS |
274 | |
275 | if (b == 0) | |
276 | return u; | |
277 | ||
278 | uu.ll = u; | |
279 | ||
996ed075 | 280 | bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; |
203b91b9 RS |
281 | if (bm <= 0) |
282 | { | |
283 | w.s.low = 0; | |
6da9c622 | 284 | w.s.high = (UWtype) uu.s.low << -bm; |
203b91b9 RS |
285 | } |
286 | else | |
287 | { | |
6da9c622 RK |
288 | UWtype carries = (UWtype) uu.s.low >> bm; |
289 | ||
290 | w.s.low = (UWtype) uu.s.low << b; | |
291 | w.s.high = ((UWtype) uu.s.high << b) | carries; | |
203b91b9 RS |
292 | } |
293 | ||
294 | return w.ll; | |
295 | } | |
296 | #endif | |
297 | ||
298 | #ifdef L_ashrdi3 | |
996ed075 JJ |
299 | DWtype |
300 | __ashrdi3 (DWtype u, word_type b) | |
203b91b9 | 301 | { |
996ed075 | 302 | DWunion w; |
b799cfc3 | 303 | word_type bm; |
996ed075 | 304 | DWunion uu; |
203b91b9 RS |
305 | |
306 | if (b == 0) | |
307 | return u; | |
308 | ||
309 | uu.ll = u; | |
310 | ||
996ed075 | 311 | bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; |
203b91b9 RS |
312 | if (bm <= 0) |
313 | { | |
314 | /* w.s.high = 1..1 or 0..0 */ | |
996ed075 | 315 | w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1); |
203b91b9 RS |
316 | w.s.low = uu.s.high >> -bm; |
317 | } | |
318 | else | |
319 | { | |
6da9c622 RK |
320 | UWtype carries = (UWtype) uu.s.high << bm; |
321 | ||
203b91b9 | 322 | w.s.high = uu.s.high >> b; |
6da9c622 | 323 | w.s.low = ((UWtype) uu.s.low >> b) | carries; |
203b91b9 RS |
324 | } |
325 | ||
326 | return w.ll; | |
327 | } | |
328 | #endif | |
329 | \f | |
aa66bd06 | 330 | #ifdef L_ffsdi2 |
996ed075 JJ |
331 | DWtype |
332 | __ffsdi2 (DWtype u) | |
aa66bd06 | 333 | { |
d6eacd48 RH |
334 | DWunion uu; |
335 | UWtype word, count, add; | |
336 | ||
aa66bd06 | 337 | uu.ll = u; |
d6eacd48 RH |
338 | if (uu.s.low != 0) |
339 | word = uu.s.low, add = 0; | |
340 | else if (uu.s.high != 0) | |
341 | word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype); | |
342 | else | |
343 | return 0; | |
344 | ||
345 | count_trailing_zeros (count, word); | |
346 | return count + add + 1; | |
aa66bd06 RS |
347 | } |
348 | #endif | |
349 | \f | |
203b91b9 | 350 | #ifdef L_muldi3 |
996ed075 JJ |
351 | DWtype |
352 | __muldi3 (DWtype u, DWtype v) | |
203b91b9 | 353 | { |
996ed075 JJ |
354 | DWunion w; |
355 | DWunion uu, vv; | |
203b91b9 RS |
356 | |
357 | uu.ll = u, | |
358 | vv.ll = v; | |
359 | ||
360 | w.ll = __umulsidi3 (uu.s.low, vv.s.low); | |
996ed075 JJ |
361 | w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high |
362 | + (UWtype) uu.s.high * (UWtype) vv.s.low); | |
203b91b9 RS |
363 | |
364 | return w.ll; | |
365 | } | |
366 | #endif | |
367 | \f | |
3904131a | 368 | #ifdef L_udiv_w_sdiv |
ce13d15f | 369 | #if defined (sdiv_qrnnd) |
996ed075 JJ |
370 | UWtype |
371 | __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d) | |
431b1ee0 | 372 | { |
996ed075 JJ |
373 | UWtype q, r; |
374 | UWtype c0, c1, b1; | |
431b1ee0 | 375 | |
996ed075 | 376 | if ((Wtype) d >= 0) |
431b1ee0 | 377 | { |
996ed075 | 378 | if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1))) |
431b1ee0 TG |
379 | { |
380 | /* dividend, divisor, and quotient are nonnegative */ | |
381 | sdiv_qrnnd (q, r, a1, a0, d); | |
382 | } | |
383 | else | |
384 | { | |
385 | /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ | |
996ed075 | 386 | sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1)); |
431b1ee0 TG |
387 | /* Divide (c1*2^32 + c0) by d */ |
388 | sdiv_qrnnd (q, r, c1, c0, d); | |
389 | /* Add 2^31 to quotient */ | |
996ed075 | 390 | q += (UWtype) 1 << (W_TYPE_SIZE - 1); |
431b1ee0 TG |
391 | } |
392 | } | |
393 | else | |
394 | { | |
395 | b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ | |
396 | c1 = a1 >> 1; /* A/2 */ | |
996ed075 | 397 | c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1); |
431b1ee0 TG |
398 | |
399 | if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ | |
400 | { | |
401 | sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ | |
402 | ||
403 | r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ | |
404 | if ((d & 1) != 0) | |
405 | { | |
406 | if (r >= q) | |
407 | r = r - q; | |
408 | else if (q - r <= d) | |
409 | { | |
410 | r = r - q + d; | |
411 | q--; | |
412 | } | |
413 | else | |
414 | { | |
415 | r = r - q + 2*d; | |
416 | q -= 2; | |
417 | } | |
418 | } | |
419 | } | |
420 | else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ | |
421 | { | |
422 | c1 = (b1 - 1) - c1; | |
423 | c0 = ~c0; /* logical NOT */ | |
424 | ||
425 | sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ | |
426 | ||
427 | q = ~q; /* (A/2)/b1 */ | |
428 | r = (b1 - 1) - r; | |
429 | ||
430 | r = 2*r + (a0 & 1); /* A/(2*b1) */ | |
431 | ||
432 | if ((d & 1) != 0) | |
433 | { | |
434 | if (r >= q) | |
435 | r = r - q; | |
436 | else if (q - r <= d) | |
437 | { | |
438 | r = r - q + d; | |
439 | q--; | |
440 | } | |
441 | else | |
442 | { | |
443 | r = r - q + 2*d; | |
444 | q -= 2; | |
445 | } | |
446 | } | |
447 | } | |
448 | else /* Implies c1 = b1 */ | |
449 | { /* Hence a1 = d - 1 = 2*b1 - 1 */ | |
450 | if (a0 >= -d) | |
451 | { | |
452 | q = -1; | |
453 | r = a0 + d; | |
454 | } | |
455 | else | |
456 | { | |
457 | q = -2; | |
458 | r = a0 + 2*d; | |
459 | } | |
460 | } | |
461 | } | |
462 | ||
463 | *rp = r; | |
464 | return q; | |
465 | } | |
ce13d15f RK |
466 | #else |
467 | /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */ | |
996ed075 JJ |
468 | UWtype |
469 | __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)), | |
470 | UWtype a1 __attribute__ ((__unused__)), | |
471 | UWtype a0 __attribute__ ((__unused__)), | |
472 | UWtype d __attribute__ ((__unused__))) | |
081f5e7e KG |
473 | { |
474 | return 0; | |
475 | } | |
ce13d15f | 476 | #endif |
431b1ee0 TG |
477 | #endif |
478 | \f | |
536bfcd0 RK |
479 | #if (defined (L_udivdi3) || defined (L_divdi3) || \ |
480 | defined (L_umoddi3) || defined (L_moddi3)) | |
481 | #define L_udivmoddi4 | |
482 | #endif | |
483 | ||
d6eacd48 RH |
484 | #ifdef L_clz |
485 | const UQItype __clz_tab[] = | |
203b91b9 RS |
486 | { |
487 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, | |
488 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | |
489 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | |
490 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | |
491 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
492 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
493 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
494 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | |
495 | }; | |
d6eacd48 RH |
496 | #endif |
497 | ||
498 | #ifdef L_udivmoddi4 | |
203b91b9 | 499 | |
536bfcd0 RK |
500 | #if (defined (L_udivdi3) || defined (L_divdi3) || \ |
501 | defined (L_umoddi3) || defined (L_moddi3)) | |
502 | static inline | |
503 | #endif | |
996ed075 JJ |
504 | UDWtype |
505 | __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) | |
203b91b9 | 506 | { |
996ed075 JJ |
507 | DWunion ww; |
508 | DWunion nn, dd; | |
509 | DWunion rr; | |
510 | UWtype d0, d1, n0, n1, n2; | |
511 | UWtype q0, q1; | |
512 | UWtype b, bm; | |
203b91b9 RS |
513 | |
514 | nn.ll = n; | |
515 | dd.ll = d; | |
516 | ||
517 | d0 = dd.s.low; | |
518 | d1 = dd.s.high; | |
519 | n0 = nn.s.low; | |
520 | n1 = nn.s.high; | |
521 | ||
522 | #if !UDIV_NEEDS_NORMALIZATION | |
523 | if (d1 == 0) | |
524 | { | |
525 | if (d0 > n1) | |
526 | { | |
527 | /* 0q = nn / 0D */ | |
528 | ||
529 | udiv_qrnnd (q0, n0, n1, n0, d0); | |
530 | q1 = 0; | |
531 | ||
532 | /* Remainder in n0. */ | |
533 | } | |
534 | else | |
535 | { | |
536 | /* qq = NN / 0d */ | |
537 | ||
538 | if (d0 == 0) | |
539 | d0 = 1 / d0; /* Divide intentionally by zero. */ | |
540 | ||
541 | udiv_qrnnd (q1, n1, 0, n1, d0); | |
542 | udiv_qrnnd (q0, n0, n1, n0, d0); | |
543 | ||
544 | /* Remainder in n0. */ | |
545 | } | |
546 | ||
547 | if (rp != 0) | |
548 | { | |
549 | rr.s.low = n0; | |
550 | rr.s.high = 0; | |
551 | *rp = rr.ll; | |
552 | } | |
553 | } | |
554 | ||
555 | #else /* UDIV_NEEDS_NORMALIZATION */ | |
556 | ||
557 | if (d1 == 0) | |
558 | { | |
559 | if (d0 > n1) | |
560 | { | |
561 | /* 0q = nn / 0D */ | |
562 | ||
563 | count_leading_zeros (bm, d0); | |
564 | ||
565 | if (bm != 0) | |
566 | { | |
567 | /* Normalize, i.e. make the most significant bit of the | |
568 | denominator set. */ | |
569 | ||
570 | d0 = d0 << bm; | |
996ed075 | 571 | n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); |
203b91b9 RS |
572 | n0 = n0 << bm; |
573 | } | |
574 | ||
575 | udiv_qrnnd (q0, n0, n1, n0, d0); | |
576 | q1 = 0; | |
577 | ||
578 | /* Remainder in n0 >> bm. */ | |
579 | } | |
580 | else | |
581 | { | |
582 | /* qq = NN / 0d */ | |
583 | ||
584 | if (d0 == 0) | |
585 | d0 = 1 / d0; /* Divide intentionally by zero. */ | |
586 | ||
587 | count_leading_zeros (bm, d0); | |
588 | ||
589 | if (bm == 0) | |
590 | { | |
591 | /* From (n1 >= d0) /\ (the most significant bit of d0 is set), | |
592 | conclude (the most significant bit of n1 is set) /\ (the | |
593 | leading quotient digit q1 = 1). | |
594 | ||
595 | This special case is necessary, not an optimization. | |
996ed075 | 596 | (Shifts counts of W_TYPE_SIZE are undefined.) */ |
203b91b9 RS |
597 | |
598 | n1 -= d0; | |
599 | q1 = 1; | |
600 | } | |
601 | else | |
602 | { | |
603 | /* Normalize. */ | |
604 | ||
996ed075 | 605 | b = W_TYPE_SIZE - bm; |
203b91b9 RS |
606 | |
607 | d0 = d0 << bm; | |
608 | n2 = n1 >> b; | |
609 | n1 = (n1 << bm) | (n0 >> b); | |
610 | n0 = n0 << bm; | |
611 | ||
612 | udiv_qrnnd (q1, n1, n2, n1, d0); | |
613 | } | |
614 | ||
0f41302f | 615 | /* n1 != d0... */ |
203b91b9 RS |
616 | |
617 | udiv_qrnnd (q0, n0, n1, n0, d0); | |
618 | ||
619 | /* Remainder in n0 >> bm. */ | |
620 | } | |
621 | ||
622 | if (rp != 0) | |
623 | { | |
624 | rr.s.low = n0 >> bm; | |
625 | rr.s.high = 0; | |
626 | *rp = rr.ll; | |
627 | } | |
628 | } | |
629 | #endif /* UDIV_NEEDS_NORMALIZATION */ | |
630 | ||
631 | else | |
632 | { | |
633 | if (d1 > n1) | |
634 | { | |
635 | /* 00 = nn / DD */ | |
636 | ||
637 | q0 = 0; | |
638 | q1 = 0; | |
639 | ||
640 | /* Remainder in n1n0. */ | |
641 | if (rp != 0) | |
642 | { | |
643 | rr.s.low = n0; | |
644 | rr.s.high = n1; | |
645 | *rp = rr.ll; | |
646 | } | |
647 | } | |
648 | else | |
649 | { | |
650 | /* 0q = NN / dd */ | |
651 | ||
652 | count_leading_zeros (bm, d1); | |
653 | if (bm == 0) | |
654 | { | |
655 | /* From (n1 >= d1) /\ (the most significant bit of d1 is set), | |
656 | conclude (the most significant bit of n1 is set) /\ (the | |
657 | quotient digit q0 = 0 or 1). | |
658 | ||
659 | This special case is necessary, not an optimization. */ | |
660 | ||
661 | /* The condition on the next line takes advantage of that | |
662 | n1 >= d1 (true due to program flow). */ | |
663 | if (n1 > d1 || n0 >= d0) | |
664 | { | |
665 | q0 = 1; | |
666 | sub_ddmmss (n1, n0, n1, n0, d1, d0); | |
667 | } | |
668 | else | |
669 | q0 = 0; | |
670 | ||
671 | q1 = 0; | |
672 | ||
673 | if (rp != 0) | |
674 | { | |
675 | rr.s.low = n0; | |
676 | rr.s.high = n1; | |
677 | *rp = rr.ll; | |
678 | } | |
679 | } | |
680 | else | |
681 | { | |
996ed075 | 682 | UWtype m1, m0; |
203b91b9 RS |
683 | /* Normalize. */ |
684 | ||
996ed075 | 685 | b = W_TYPE_SIZE - bm; |
203b91b9 RS |
686 | |
687 | d1 = (d1 << bm) | (d0 >> b); | |
688 | d0 = d0 << bm; | |
689 | n2 = n1 >> b; | |
690 | n1 = (n1 << bm) | (n0 >> b); | |
691 | n0 = n0 << bm; | |
692 | ||
693 | udiv_qrnnd (q0, n1, n2, n1, d1); | |
694 | umul_ppmm (m1, m0, q0, d0); | |
695 | ||
696 | if (m1 > n1 || (m1 == n1 && m0 > n0)) | |
697 | { | |
698 | q0--; | |
699 | sub_ddmmss (m1, m0, m1, m0, d1, d0); | |
700 | } | |
701 | ||
702 | q1 = 0; | |
703 | ||
704 | /* Remainder in (n1n0 - m1m0) >> bm. */ | |
705 | if (rp != 0) | |
706 | { | |
707 | sub_ddmmss (n1, n0, n1, n0, m1, m0); | |
708 | rr.s.low = (n1 << b) | (n0 >> bm); | |
709 | rr.s.high = n1 >> bm; | |
710 | *rp = rr.ll; | |
711 | } | |
712 | } | |
713 | } | |
714 | } | |
715 | ||
716 | ww.s.low = q0; | |
717 | ww.s.high = q1; | |
718 | return ww.ll; | |
719 | } | |
720 | #endif | |
721 | ||
722 | #ifdef L_divdi3 | |
996ed075 JJ |
723 | DWtype |
724 | __divdi3 (DWtype u, DWtype v) | |
203b91b9 | 725 | { |
b799cfc3 | 726 | word_type c = 0; |
996ed075 JJ |
727 | DWunion uu, vv; |
728 | DWtype w; | |
203b91b9 RS |
729 | |
730 | uu.ll = u; | |
731 | vv.ll = v; | |
732 | ||
733 | if (uu.s.high < 0) | |
734 | c = ~c, | |
735 | uu.ll = __negdi2 (uu.ll); | |
736 | if (vv.s.high < 0) | |
737 | c = ~c, | |
738 | vv.ll = __negdi2 (vv.ll); | |
739 | ||
996ed075 | 740 | w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); |
203b91b9 RS |
741 | if (c) |
742 | w = __negdi2 (w); | |
743 | ||
744 | return w; | |
745 | } | |
746 | #endif | |
747 | ||
748 | #ifdef L_moddi3 | |
996ed075 JJ |
749 | DWtype |
750 | __moddi3 (DWtype u, DWtype v) | |
203b91b9 | 751 | { |
b799cfc3 | 752 | word_type c = 0; |
996ed075 JJ |
753 | DWunion uu, vv; |
754 | DWtype w; | |
203b91b9 RS |
755 | |
756 | uu.ll = u; | |
757 | vv.ll = v; | |
758 | ||
759 | if (uu.s.high < 0) | |
760 | c = ~c, | |
761 | uu.ll = __negdi2 (uu.ll); | |
762 | if (vv.s.high < 0) | |
763 | vv.ll = __negdi2 (vv.ll); | |
764 | ||
765 | (void) __udivmoddi4 (uu.ll, vv.ll, &w); | |
766 | if (c) | |
767 | w = __negdi2 (w); | |
768 | ||
769 | return w; | |
770 | } | |
771 | #endif | |
772 | ||
773 | #ifdef L_umoddi3 | |
996ed075 JJ |
774 | UDWtype |
775 | __umoddi3 (UDWtype u, UDWtype v) | |
203b91b9 | 776 | { |
996ed075 | 777 | UDWtype w; |
203b91b9 RS |
778 | |
779 | (void) __udivmoddi4 (u, v, &w); | |
780 | ||
781 | return w; | |
782 | } | |
783 | #endif | |
784 | ||
785 | #ifdef L_udivdi3 | |
996ed075 JJ |
786 | UDWtype |
787 | __udivdi3 (UDWtype n, UDWtype d) | |
203b91b9 | 788 | { |
996ed075 | 789 | return __udivmoddi4 (n, d, (UDWtype *) 0); |
203b91b9 RS |
790 | } |
791 | #endif | |
792 | \f | |
793 | #ifdef L_cmpdi2 | |
4be7c28f | 794 | word_type |
996ed075 | 795 | __cmpdi2 (DWtype a, DWtype b) |
203b91b9 | 796 | { |
996ed075 | 797 | DWunion au, bu; |
203b91b9 RS |
798 | |
799 | au.ll = a, bu.ll = b; | |
800 | ||
801 | if (au.s.high < bu.s.high) | |
802 | return 0; | |
803 | else if (au.s.high > bu.s.high) | |
804 | return 2; | |
996ed075 | 805 | if ((UWtype) au.s.low < (UWtype) bu.s.low) |
203b91b9 | 806 | return 0; |
996ed075 | 807 | else if ((UWtype) au.s.low > (UWtype) bu.s.low) |
203b91b9 RS |
808 | return 2; |
809 | return 1; | |
810 | } | |
811 | #endif | |
812 | ||
813 | #ifdef L_ucmpdi2 | |
4be7c28f | 814 | word_type |
996ed075 | 815 | __ucmpdi2 (DWtype a, DWtype b) |
203b91b9 | 816 | { |
996ed075 | 817 | DWunion au, bu; |
203b91b9 RS |
818 | |
819 | au.ll = a, bu.ll = b; | |
820 | ||
996ed075 | 821 | if ((UWtype) au.s.high < (UWtype) bu.s.high) |
203b91b9 | 822 | return 0; |
996ed075 | 823 | else if ((UWtype) au.s.high > (UWtype) bu.s.high) |
203b91b9 | 824 | return 2; |
996ed075 | 825 | if ((UWtype) au.s.low < (UWtype) bu.s.low) |
203b91b9 | 826 | return 0; |
996ed075 | 827 | else if ((UWtype) au.s.low > (UWtype) bu.s.low) |
203b91b9 RS |
828 | return 2; |
829 | return 1; | |
830 | } | |
831 | #endif | |
832 | \f | |
eaa4b44c | 833 | #if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) |
996ed075 JJ |
834 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
835 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
ab495388 | 836 | |
996ed075 | 837 | DWtype |
6da9c622 | 838 | __fixunstfDI (TFtype a) |
ab495388 RS |
839 | { |
840 | TFtype b; | |
996ed075 | 841 | UDWtype v; |
ab495388 RS |
842 | |
843 | if (a < 0) | |
844 | return 0; | |
845 | ||
846 | /* Compute high word of result, as a flonum. */ | |
847 | b = (a / HIGH_WORD_COEFF); | |
996ed075 | 848 | /* Convert that to fixed (but not to DWtype!), |
ab495388 | 849 | and shift it into the high word. */ |
996ed075 | 850 | v = (UWtype) b; |
ab495388 RS |
851 | v <<= WORD_SIZE; |
852 | /* Remove high part from the TFtype, leaving the low part as flonum. */ | |
853 | a -= (TFtype)v; | |
996ed075 | 854 | /* Convert that to fixed (but not to DWtype!) and add it in. |
ab495388 RS |
855 | Sometimes A comes out negative. This is significant, since |
856 | A has more bits than a long int does. */ | |
857 | if (a < 0) | |
996ed075 | 858 | v -= (UWtype) (- a); |
ab495388 | 859 | else |
996ed075 | 860 | v += (UWtype) a; |
ab495388 RS |
861 | return v; |
862 | } | |
863 | #endif | |
864 | ||
eaa4b44c | 865 | #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) |
996ed075 | 866 | DWtype |
37ef1054 | 867 | __fixtfdi (TFtype a) |
ab495388 RS |
868 | { |
869 | if (a < 0) | |
6da9c622 RK |
870 | return - __fixunstfDI (-a); |
871 | return __fixunstfDI (a); | |
ab495388 RS |
872 | } |
873 | #endif | |
874 | ||
eaa4b44c | 875 | #if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) |
996ed075 JJ |
876 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
877 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
e0799b34 | 878 | |
996ed075 | 879 | DWtype |
6da9c622 | 880 | __fixunsxfDI (XFtype a) |
e0799b34 RS |
881 | { |
882 | XFtype b; | |
996ed075 | 883 | UDWtype v; |
e0799b34 RS |
884 | |
885 | if (a < 0) | |
886 | return 0; | |
887 | ||
888 | /* Compute high word of result, as a flonum. */ | |
889 | b = (a / HIGH_WORD_COEFF); | |
996ed075 | 890 | /* Convert that to fixed (but not to DWtype!), |
e0799b34 | 891 | and shift it into the high word. */ |
996ed075 | 892 | v = (UWtype) b; |
e0799b34 RS |
893 | v <<= WORD_SIZE; |
894 | /* Remove high part from the XFtype, leaving the low part as flonum. */ | |
895 | a -= (XFtype)v; | |
996ed075 | 896 | /* Convert that to fixed (but not to DWtype!) and add it in. |
e0799b34 RS |
897 | Sometimes A comes out negative. This is significant, since |
898 | A has more bits than a long int does. */ | |
899 | if (a < 0) | |
996ed075 | 900 | v -= (UWtype) (- a); |
e0799b34 | 901 | else |
996ed075 | 902 | v += (UWtype) a; |
e0799b34 RS |
903 | return v; |
904 | } | |
905 | #endif | |
906 | ||
eaa4b44c | 907 | #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) |
996ed075 | 908 | DWtype |
37ef1054 | 909 | __fixxfdi (XFtype a) |
e0799b34 RS |
910 | { |
911 | if (a < 0) | |
6da9c622 RK |
912 | return - __fixunsxfDI (-a); |
913 | return __fixunsxfDI (a); | |
e0799b34 RS |
914 | } |
915 | #endif | |
916 | ||
203b91b9 | 917 | #ifdef L_fixunsdfdi |
996ed075 JJ |
918 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
919 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
203b91b9 | 920 | |
996ed075 | 921 | DWtype |
6da9c622 | 922 | __fixunsdfDI (DFtype a) |
203b91b9 | 923 | { |
ab495388 | 924 | DFtype b; |
996ed075 | 925 | UDWtype v; |
203b91b9 RS |
926 | |
927 | if (a < 0) | |
928 | return 0; | |
929 | ||
930 | /* Compute high word of result, as a flonum. */ | |
931 | b = (a / HIGH_WORD_COEFF); | |
996ed075 | 932 | /* Convert that to fixed (but not to DWtype!), |
203b91b9 | 933 | and shift it into the high word. */ |
996ed075 | 934 | v = (UWtype) b; |
203b91b9 | 935 | v <<= WORD_SIZE; |
ab495388 RS |
936 | /* Remove high part from the DFtype, leaving the low part as flonum. */ |
937 | a -= (DFtype)v; | |
996ed075 | 938 | /* Convert that to fixed (but not to DWtype!) and add it in. |
203b91b9 RS |
939 | Sometimes A comes out negative. This is significant, since |
940 | A has more bits than a long int does. */ | |
941 | if (a < 0) | |
996ed075 | 942 | v -= (UWtype) (- a); |
203b91b9 | 943 | else |
996ed075 | 944 | v += (UWtype) a; |
203b91b9 RS |
945 | return v; |
946 | } | |
947 | #endif | |
948 | ||
949 | #ifdef L_fixdfdi | |
996ed075 | 950 | DWtype |
37ef1054 | 951 | __fixdfdi (DFtype a) |
203b91b9 RS |
952 | { |
953 | if (a < 0) | |
6da9c622 RK |
954 | return - __fixunsdfDI (-a); |
955 | return __fixunsdfDI (a); | |
203b91b9 RS |
956 | } |
957 | #endif | |
958 | ||
959 | #ifdef L_fixunssfdi | |
996ed075 JJ |
960 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
961 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
203b91b9 | 962 | |
996ed075 | 963 | DWtype |
6da9c622 | 964 | __fixunssfDI (SFtype original_a) |
203b91b9 | 965 | { |
ab495388 | 966 | /* Convert the SFtype to a DFtype, because that is surely not going |
203b91b9 | 967 | to lose any bits. Some day someone else can write a faster version |
ab495388 RS |
968 | that avoids converting to DFtype, and verify it really works right. */ |
969 | DFtype a = original_a; | |
970 | DFtype b; | |
996ed075 | 971 | UDWtype v; |
203b91b9 RS |
972 | |
973 | if (a < 0) | |
974 | return 0; | |
975 | ||
976 | /* Compute high word of result, as a flonum. */ | |
977 | b = (a / HIGH_WORD_COEFF); | |
996ed075 | 978 | /* Convert that to fixed (but not to DWtype!), |
203b91b9 | 979 | and shift it into the high word. */ |
996ed075 | 980 | v = (UWtype) b; |
203b91b9 | 981 | v <<= WORD_SIZE; |
ab495388 | 982 | /* Remove high part from the DFtype, leaving the low part as flonum. */ |
6da9c622 | 983 | a -= (DFtype) v; |
996ed075 | 984 | /* Convert that to fixed (but not to DWtype!) and add it in. |
203b91b9 RS |
985 | Sometimes A comes out negative. This is significant, since |
986 | A has more bits than a long int does. */ | |
987 | if (a < 0) | |
996ed075 | 988 | v -= (UWtype) (- a); |
203b91b9 | 989 | else |
996ed075 | 990 | v += (UWtype) a; |
203b91b9 RS |
991 | return v; |
992 | } | |
993 | #endif | |
994 | ||
995 | #ifdef L_fixsfdi | |
996ed075 | 996 | DWtype |
ab495388 | 997 | __fixsfdi (SFtype a) |
203b91b9 RS |
998 | { |
999 | if (a < 0) | |
6da9c622 RK |
1000 | return - __fixunssfDI (-a); |
1001 | return __fixunssfDI (a); | |
203b91b9 RS |
1002 | } |
1003 | #endif | |
1004 | ||
eaa4b44c | 1005 | #if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) |
996ed075 JJ |
1006 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
1007 | #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) | |
1008 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
e0799b34 RS |
1009 | |
1010 | XFtype | |
996ed075 | 1011 | __floatdixf (DWtype u) |
e0799b34 RS |
1012 | { |
1013 | XFtype d; | |
e0799b34 | 1014 | |
996ed075 | 1015 | d = (Wtype) (u >> WORD_SIZE); |
e0799b34 RS |
1016 | d *= HIGH_HALFWORD_COEFF; |
1017 | d *= HIGH_HALFWORD_COEFF; | |
996ed075 | 1018 | d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); |
e0799b34 | 1019 | |
e5e809f4 | 1020 | return d; |
e0799b34 RS |
1021 | } |
1022 | #endif | |
1023 | ||
eaa4b44c | 1024 | #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) |
996ed075 JJ |
1025 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
1026 | #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) | |
1027 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
ab495388 RS |
1028 | |
1029 | TFtype | |
996ed075 | 1030 | __floatditf (DWtype u) |
ab495388 RS |
1031 | { |
1032 | TFtype d; | |
ab495388 | 1033 | |
996ed075 | 1034 | d = (Wtype) (u >> WORD_SIZE); |
ab495388 RS |
1035 | d *= HIGH_HALFWORD_COEFF; |
1036 | d *= HIGH_HALFWORD_COEFF; | |
996ed075 | 1037 | d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); |
ab495388 | 1038 | |
e5e809f4 | 1039 | return d; |
ab495388 RS |
1040 | } |
1041 | #endif | |
1042 | ||
203b91b9 | 1043 | #ifdef L_floatdidf |
996ed075 JJ |
1044 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
1045 | #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) | |
1046 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
203b91b9 | 1047 | |
ab495388 | 1048 | DFtype |
996ed075 | 1049 | __floatdidf (DWtype u) |
203b91b9 | 1050 | { |
ab495388 | 1051 | DFtype d; |
203b91b9 | 1052 | |
996ed075 | 1053 | d = (Wtype) (u >> WORD_SIZE); |
203b91b9 RS |
1054 | d *= HIGH_HALFWORD_COEFF; |
1055 | d *= HIGH_HALFWORD_COEFF; | |
996ed075 | 1056 | d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); |
203b91b9 | 1057 | |
e5e809f4 | 1058 | return d; |
203b91b9 RS |
1059 | } |
1060 | #endif | |
1061 | ||
1062 | #ifdef L_floatdisf | |
996ed075 JJ |
1063 | #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) |
1064 | #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) | |
1065 | #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) | |
23190837 | 1066 | |
15e5ad76 | 1067 | #define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT) |
b216cd4a ZW |
1068 | #define DF_SIZE DBL_MANT_DIG |
1069 | #define SF_SIZE FLT_MANT_DIG | |
203b91b9 | 1070 | |
ab495388 | 1071 | SFtype |
996ed075 | 1072 | __floatdisf (DWtype u) |
203b91b9 | 1073 | { |
56b03d5f RS |
1074 | /* Do the calculation in DFmode |
1075 | so that we don't lose any of the precision of the high word | |
1076 | while multiplying it. */ | |
1077 | DFtype f; | |
203b91b9 | 1078 | |
d9e1ab8d RK |
1079 | /* Protect against double-rounding error. |
1080 | Represent any low-order bits, that might be truncated in DFmode, | |
1081 | by a bit that won't be lost. The bit can go in anywhere below the | |
1082 | rounding position of the SFmode. A fixed mask and bit position | |
1083 | handles all usual configurations. It doesn't handle the case | |
1084 | of 128-bit DImode, however. */ | |
1085 | if (DF_SIZE < DI_SIZE | |
1086 | && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) | |
1087 | { | |
6da9c622 | 1088 | #define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) |
996ed075 JJ |
1089 | if (! (- ((DWtype) 1 << DF_SIZE) < u |
1090 | && u < ((DWtype) 1 << DF_SIZE))) | |
d9e1ab8d | 1091 | { |
6da9c622 | 1092 | if ((UDWtype) u & (REP_BIT - 1)) |
d9e1ab8d RK |
1093 | u |= REP_BIT; |
1094 | } | |
1095 | } | |
996ed075 | 1096 | f = (Wtype) (u >> WORD_SIZE); |
203b91b9 RS |
1097 | f *= HIGH_HALFWORD_COEFF; |
1098 | f *= HIGH_HALFWORD_COEFF; | |
996ed075 | 1099 | f += (UWtype) (u & (HIGH_WORD_COEFF - 1)); |
203b91b9 | 1100 | |
e5e809f4 | 1101 | return (SFtype) f; |
203b91b9 RS |
1102 | } |
1103 | #endif | |
1104 | ||
eaa4b44c | 1105 | #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 |
3f3d2ec8 JW |
1106 | /* Reenable the normal types, in case limits.h needs them. */ |
1107 | #undef char | |
1108 | #undef short | |
1109 | #undef int | |
1110 | #undef long | |
1111 | #undef unsigned | |
1112 | #undef float | |
1113 | #undef double | |
c07e26bd RK |
1114 | #undef MIN |
1115 | #undef MAX | |
a99598c9 | 1116 | #include <limits.h> |
e0799b34 | 1117 | |
996ed075 | 1118 | UWtype |
6da9c622 | 1119 | __fixunsxfSI (XFtype a) |
e0799b34 | 1120 | { |
5d0e6486 AO |
1121 | if (a >= - (DFtype) Wtype_MIN) |
1122 | return (Wtype) (a + Wtype_MIN) - Wtype_MIN; | |
996ed075 | 1123 | return (Wtype) a; |
e0799b34 RS |
1124 | } |
1125 | #endif | |
1126 | ||
203b91b9 | 1127 | #ifdef L_fixunsdfsi |
3f3d2ec8 JW |
1128 | /* Reenable the normal types, in case limits.h needs them. */ |
1129 | #undef char | |
1130 | #undef short | |
1131 | #undef int | |
1132 | #undef long | |
1133 | #undef unsigned | |
1134 | #undef float | |
1135 | #undef double | |
c07e26bd RK |
1136 | #undef MIN |
1137 | #undef MAX | |
a99598c9 | 1138 | #include <limits.h> |
203b91b9 | 1139 | |
996ed075 | 1140 | UWtype |
6da9c622 | 1141 | __fixunsdfSI (DFtype a) |
203b91b9 | 1142 | { |
5d0e6486 AO |
1143 | if (a >= - (DFtype) Wtype_MIN) |
1144 | return (Wtype) (a + Wtype_MIN) - Wtype_MIN; | |
996ed075 | 1145 | return (Wtype) a; |
203b91b9 RS |
1146 | } |
1147 | #endif | |
1148 | ||
1149 | #ifdef L_fixunssfsi | |
3f3d2ec8 JW |
1150 | /* Reenable the normal types, in case limits.h needs them. */ |
1151 | #undef char | |
1152 | #undef short | |
1153 | #undef int | |
1154 | #undef long | |
1155 | #undef unsigned | |
1156 | #undef float | |
1157 | #undef double | |
c07e26bd RK |
1158 | #undef MIN |
1159 | #undef MAX | |
a99598c9 | 1160 | #include <limits.h> |
203b91b9 | 1161 | |
996ed075 | 1162 | UWtype |
6da9c622 | 1163 | __fixunssfSI (SFtype a) |
203b91b9 | 1164 | { |
5d0e6486 AO |
1165 | if (a >= - (SFtype) Wtype_MIN) |
1166 | return (Wtype) (a + Wtype_MIN) - Wtype_MIN; | |
996ed075 | 1167 | return (Wtype) a; |
203b91b9 RS |
1168 | } |
1169 | #endif | |
1170 | \f | |
ab495388 RS |
1171 | /* From here on down, the routines use normal data types. */ |
1172 | ||
1173 | #define SItype bogus_type | |
1174 | #define USItype bogus_type | |
1175 | #define DItype bogus_type | |
1176 | #define UDItype bogus_type | |
1177 | #define SFtype bogus_type | |
1178 | #define DFtype bogus_type | |
996ed075 JJ |
1179 | #undef Wtype |
1180 | #undef UWtype | |
1181 | #undef HWtype | |
1182 | #undef UHWtype | |
1183 | #undef DWtype | |
1184 | #undef UDWtype | |
ab495388 RS |
1185 | |
1186 | #undef char | |
1187 | #undef short | |
1188 | #undef int | |
1189 | #undef long | |
1190 | #undef unsigned | |
1191 | #undef float | |
1192 | #undef double | |
9bd23d2c RS |
1193 | \f |
1194 | #ifdef L__gcc_bcmp | |
1195 | ||
1196 | /* Like bcmp except the sign is meaningful. | |
9faa82d8 | 1197 | Result is negative if S1 is less than S2, |
9bd23d2c RS |
1198 | positive if S1 is greater, 0 if S1 and S2 are equal. */ |
1199 | ||
1200 | int | |
299b83b7 | 1201 | __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size) |
9bd23d2c RS |
1202 | { |
1203 | while (size > 0) | |
1204 | { | |
78e33213 | 1205 | unsigned char c1 = *s1++, c2 = *s2++; |
9bd23d2c RS |
1206 | if (c1 != c2) |
1207 | return c1 - c2; | |
1208 | size--; | |
1209 | } | |
1210 | return 0; | |
1211 | } | |
ab495388 | 1212 | |
3fe68d0a ZW |
1213 | #endif |
1214 | \f | |
1215 | /* __eprintf used to be used by GCC's private version of <assert.h>. | |
1216 | We no longer provide that header, but this routine remains in libgcc.a | |
1217 | for binary backward compatibility. Note that it is not included in | |
1218 | the shared version of libgcc. */ | |
1219 | #ifdef L_eprintf | |
1220 | #ifndef inhibit_libc | |
1221 | ||
1222 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ | |
1223 | #include <stdio.h> | |
1224 | ||
1225 | void | |
1226 | __eprintf (const char *string, const char *expression, | |
1227 | unsigned int line, const char *filename) | |
1228 | { | |
1229 | fprintf (stderr, string, expression, line, filename); | |
1230 | fflush (stderr); | |
1231 | abort (); | |
1232 | } | |
1233 | ||
1234 | #endif | |
203b91b9 RS |
1235 | #endif |
1236 | ||
1237 | #ifdef L_bb | |
203b91b9 | 1238 | |
b7c9bf28 JH |
1239 | struct bb_function_info { |
1240 | long checksum; | |
1241 | int arc_count; | |
1242 | const char *name; | |
1243 | }; | |
b2aec5c0 | 1244 | |
92832bb5 | 1245 | /* Structure emitted by -a */ |
203b91b9 RS |
1246 | struct bb |
1247 | { | |
92832bb5 MM |
1248 | long zero_word; |
1249 | const char *filename; | |
b2aec5c0 | 1250 | gcov_type *counts; |
92832bb5 MM |
1251 | long ncounts; |
1252 | struct bb *next; | |
92832bb5 MM |
1253 | |
1254 | /* Older GCC's did not emit these fields. */ | |
2292e8fc | 1255 | long sizeof_bb; |
b7c9bf28 | 1256 | struct bb_function_info *function_infos; |
203b91b9 RS |
1257 | }; |
1258 | ||
c7544ff7 | 1259 | #ifndef inhibit_libc |
92832bb5 MM |
1260 | |
1261 | /* Simple minded basic block profiling output dumper for | |
9faa82d8 | 1262 | systems that don't provide tcov support. At present, |
92832bb5 MM |
1263 | it requires atexit and stdio. */ |
1264 | ||
ebd41309 | 1265 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
92832bb5 | 1266 | #include <stdio.h> |
203b91b9 | 1267 | |
8b7677be | 1268 | #include "gbl-ctors.h" |
65f7a653 | 1269 | #include "gcov-io.h" |
ac957f13 | 1270 | #include <string.h> |
e09d24ff R |
1271 | #ifdef TARGET_HAS_F_SETLKW |
1272 | #include <fcntl.h> | |
1273 | #include <errno.h> | |
1274 | #endif | |
92832bb5 | 1275 | |
b7c9bf28 JH |
1276 | #include <gthr.h> |
1277 | ||
7e6f1890 | 1278 | static struct bb *bb_head; |
92832bb5 | 1279 | |
b7c9bf28 JH |
1280 | int __global_counters = 0, __gthreads_active = 0; |
1281 | ||
543828ca | 1282 | void |
92832bb5 MM |
1283 | __bb_exit_func (void) |
1284 | { | |
114e78f8 | 1285 | FILE *da_file; |
114e78f8 | 1286 | struct bb *ptr; |
b7c9bf28 JH |
1287 | long n_counters_p = 0; |
1288 | gcov_type max_counter_p = 0; | |
1289 | gcov_type sum_counters_p = 0; | |
65f7a653 DE |
1290 | |
1291 | if (bb_head == 0) | |
1292 | return; | |
1293 | ||
b7c9bf28 | 1294 | /* Calculate overall "statistics". */ |
65f7a653 | 1295 | |
b7c9bf28 JH |
1296 | for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) |
1297 | { | |
1298 | int i; | |
1299 | ||
1300 | n_counters_p += ptr->ncounts; | |
1301 | ||
1302 | for (i = 0; i < ptr->ncounts; i++) | |
1303 | { | |
1304 | sum_counters_p += ptr->counts[i]; | |
1305 | ||
1306 | if (ptr->counts[i] > max_counter_p) | |
1307 | max_counter_p = ptr->counts[i]; | |
1308 | } | |
1309 | } | |
65f7a653 | 1310 | |
114e78f8 JH |
1311 | for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) |
1312 | { | |
b7c9bf28 JH |
1313 | gcov_type max_counter_o = 0; |
1314 | gcov_type sum_counters_o = 0; | |
1315 | int i; | |
1316 | ||
1317 | /* Calculate the per-object statistics. */ | |
114e78f8 | 1318 | |
b7c9bf28 JH |
1319 | for (i = 0; i < ptr->ncounts; i++) |
1320 | { | |
1321 | sum_counters_o += ptr->counts[i]; | |
114e78f8 | 1322 | |
b7c9bf28 JH |
1323 | if (ptr->counts[i] > max_counter_o) |
1324 | max_counter_o = ptr->counts[i]; | |
1325 | } | |
1326 | ||
1327 | /* open the file for appending, creating it if necessary. */ | |
1328 | da_file = fopen (ptr->filename, "ab"); | |
114e78f8 JH |
1329 | /* Some old systems might not allow the 'b' mode modifier. |
1330 | Therefore, try to open without it. This can lead to a race | |
1331 | condition so that when you delete and re-create the file, the | |
1332 | file might be opened in text mode, but then, you shouldn't | |
1333 | delete the file in the first place. */ | |
1334 | if (da_file == 0) | |
b7c9bf28 | 1335 | da_file = fopen (ptr->filename, "a"); |
114e78f8 | 1336 | if (da_file == 0) |
65f7a653 | 1337 | { |
114e78f8 JH |
1338 | fprintf (stderr, "arc profiling: Can't open output file %s.\n", |
1339 | ptr->filename); | |
1340 | continue; | |
1341 | } | |
e09d24ff | 1342 | |
114e78f8 JH |
1343 | /* After a fork, another process might try to read and/or write |
1344 | the same file simultanously. So if we can, lock the file to | |
1345 | avoid race conditions. */ | |
e09d24ff | 1346 | #if defined (TARGET_HAS_F_SETLKW) |
114e78f8 JH |
1347 | { |
1348 | struct flock s_flock; | |
1349 | ||
1350 | s_flock.l_type = F_WRLCK; | |
1351 | s_flock.l_whence = SEEK_SET; | |
1352 | s_flock.l_start = 0; | |
1353 | s_flock.l_len = 1; | |
1354 | s_flock.l_pid = getpid (); | |
1355 | ||
1356 | while (fcntl (fileno (da_file), F_SETLKW, &s_flock) | |
1357 | && errno == EINTR); | |
1358 | } | |
e09d24ff R |
1359 | #endif |
1360 | ||
b7c9bf28 | 1361 | if (__write_long (-123, da_file, 4) != 0) /* magic */ |
114e78f8 | 1362 | { |
b7c9bf28 JH |
1363 | fprintf (stderr, "arc profiling: Error writing output file %s.\n", |
1364 | ptr->filename); | |
114e78f8 JH |
1365 | } |
1366 | else | |
1367 | { | |
114e78f8 | 1368 | |
b7c9bf28 JH |
1369 | struct bb_function_info *fn_info; |
1370 | gcov_type *count_ptr = ptr->counts; | |
1371 | int i; | |
1372 | int count_functions = 0; | |
1373 | ||
1374 | for (fn_info = ptr->function_infos; fn_info->arc_count != -1; | |
1375 | fn_info++) | |
1376 | count_functions++; | |
1377 | ||
1378 | /* number of functions in this block. */ | |
1379 | __write_long (count_functions, da_file, 4); | |
1380 | ||
1381 | /* length of extra data in bytes. */ | |
1382 | __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4); | |
1383 | ||
e11e816e | 1384 | /* overall statistics. */ |
b7c9bf28 | 1385 | /* number of counters. */ |
e11e816e | 1386 | __write_long (n_counters_p, da_file, 4); |
b7c9bf28 | 1387 | /* sum of counters. */ |
e11e816e | 1388 | __write_gcov_type (sum_counters_p, da_file, 8); |
b7c9bf28 | 1389 | /* maximal counter. */ |
e11e816e | 1390 | __write_gcov_type (max_counter_p, da_file, 8); |
b7c9bf28 | 1391 | |
e11e816e | 1392 | /* per-object statistics. */ |
b7c9bf28 | 1393 | /* number of counters. */ |
e11e816e | 1394 | __write_long (ptr->ncounts, da_file, 4); |
b7c9bf28 | 1395 | /* sum of counters. */ |
e11e816e | 1396 | __write_gcov_type (sum_counters_o, da_file, 8); |
b7c9bf28 | 1397 | /* maximal counter. */ |
e11e816e | 1398 | __write_gcov_type (max_counter_o, da_file, 8); |
b7c9bf28 JH |
1399 | |
1400 | /* write execution counts for each function. */ | |
1401 | ||
1402 | for (fn_info = ptr->function_infos; fn_info->arc_count != -1; | |
1403 | fn_info++) | |
65f7a653 | 1404 | { |
b7c9bf28 JH |
1405 | /* new function. */ |
1406 | if (__write_gcov_string | |
1407 | (fn_info->name, strlen (fn_info->name), da_file, -1) != 0) | |
65f7a653 | 1408 | { |
b7c9bf28 JH |
1409 | fprintf (stderr, |
1410 | "arc profiling: Error writing output file %s.\n", | |
1411 | ptr->filename); | |
1412 | break; | |
65f7a653 | 1413 | } |
23190837 | 1414 | |
b7c9bf28 JH |
1415 | if (__write_long (fn_info->checksum, da_file, 4) != 0) |
1416 | { | |
1417 | fprintf (stderr, | |
1418 | "arc profiling: Error writing output file %s.\n", | |
1419 | ptr->filename); | |
1420 | break; | |
1421 | } | |
92832bb5 | 1422 | |
b7c9bf28 JH |
1423 | if (__write_long (fn_info->arc_count, da_file, 4) != 0) |
1424 | { | |
1425 | fprintf (stderr, | |
1426 | "arc profiling: Error writing output file %s.\n", | |
1427 | ptr->filename); | |
1428 | break; | |
1429 | } | |
92832bb5 | 1430 | |
b7c9bf28 JH |
1431 | for (i = fn_info->arc_count; i > 0; i--, count_ptr++) |
1432 | { | |
1433 | if (__write_gcov_type (*count_ptr, da_file, 8) != 0) | |
1434 | break; | |
1435 | } | |
92832bb5 | 1436 | |
b7c9bf28 | 1437 | if (i) /* there was an error */ |
92832bb5 | 1438 | { |
b7c9bf28 JH |
1439 | fprintf (stderr, |
1440 | "arc profiling: Error writing output file %s.\n", | |
1441 | ptr->filename); | |
114e78f8 | 1442 | break; |
92832bb5 MM |
1443 | } |
1444 | } | |
92832bb5 MM |
1445 | } |
1446 | ||
b7c9bf28 | 1447 | if (fclose (da_file) != 0) |
114e78f8 JH |
1448 | fprintf (stderr, "arc profiling: Error closing output file %s.\n", |
1449 | ptr->filename); | |
92832bb5 MM |
1450 | } |
1451 | } | |
1452 | ||
1453 | void | |
1454 | __bb_init_func (struct bb *blocks) | |
1455 | { | |
1456 | /* User is supposed to check whether the first word is non-0, | |
0f41302f | 1457 | but just in case.... */ |
92832bb5 MM |
1458 | |
1459 | if (blocks->zero_word) | |
1460 | return; | |
e11e816e | 1461 | |
b7c9bf28 | 1462 | /* Initialize destructor and per-thread data. */ |
92832bb5 | 1463 | if (!bb_head) |
c063dc98 | 1464 | atexit (__bb_exit_func); |
92832bb5 MM |
1465 | |
1466 | /* Set up linked list. */ | |
1467 | blocks->zero_word = 1; | |
1468 | blocks->next = bb_head; | |
1469 | bb_head = blocks; | |
1470 | } | |
1471 | ||
e09d24ff R |
1472 | /* Called before fork or exec - write out profile information gathered so |
1473 | far and reset it to zero. This avoids duplication or loss of the | |
1474 | profile information gathered so far. */ | |
e11e816e | 1475 | void |
e09d24ff R |
1476 | __bb_fork_func (void) |
1477 | { | |
1478 | struct bb *ptr; | |
1479 | ||
1480 | __bb_exit_func (); | |
1481 | for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) | |
1482 | { | |
1483 | long i; | |
1484 | for (i = ptr->ncounts - 1; i >= 0; i--) | |
1485 | ptr->counts[i] = 0; | |
1486 | } | |
1487 | } | |
1488 | ||
c7544ff7 | 1489 | #endif /* not inhibit_libc */ |
c7544ff7 | 1490 | #endif /* L_bb */ |
203b91b9 | 1491 | \f |
203b91b9 RS |
1492 | #ifdef L_clear_cache |
1493 | /* Clear part of an instruction cache. */ | |
1494 | ||
1495 | #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH) | |
1496 | ||
1497 | void | |
139fa6f8 MM |
1498 | __clear_cache (char *beg __attribute__((__unused__)), |
1499 | char *end __attribute__((__unused__))) | |
203b91b9 | 1500 | { |
23190837 | 1501 | #ifdef CLEAR_INSN_CACHE |
e1178973 KKT |
1502 | CLEAR_INSN_CACHE (beg, end); |
1503 | #else | |
203b91b9 RS |
1504 | #ifdef INSN_CACHE_SIZE |
1505 | static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH]; | |
7e6f1890 | 1506 | static int initialized; |
203b91b9 | 1507 | int offset; |
b6422cca RS |
1508 | void *start_addr |
1509 | void *end_addr; | |
3e7d8ef1 | 1510 | typedef (*function_ptr) (void); |
203b91b9 RS |
1511 | |
1512 | #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16 | |
1513 | /* It's cheaper to clear the whole cache. | |
1514 | Put in a series of jump instructions so that calling the beginning | |
1515 | of the cache will clear the whole thing. */ | |
1516 | ||
1517 | if (! initialized) | |
1518 | { | |
1519 | int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) | |
1520 | & -INSN_CACHE_LINE_WIDTH); | |
1521 | int end_ptr = ptr + INSN_CACHE_SIZE; | |
1522 | ||
1523 | while (ptr < end_ptr) | |
1524 | { | |
1525 | *(INSTRUCTION_TYPE *)ptr | |
1526 | = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH; | |
1527 | ptr += INSN_CACHE_LINE_WIDTH; | |
1528 | } | |
0f41302f | 1529 | *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION; |
203b91b9 RS |
1530 | |
1531 | initialized = 1; | |
1532 | } | |
1533 | ||
1534 | /* Call the beginning of the sequence. */ | |
1535 | (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1) | |
1536 | & -INSN_CACHE_LINE_WIDTH)) | |
1537 | ()); | |
1538 | ||
1539 | #else /* Cache is large. */ | |
1540 | ||
1541 | if (! initialized) | |
1542 | { | |
1543 | int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) | |
1544 | & -INSN_CACHE_LINE_WIDTH); | |
1545 | ||
1546 | while (ptr < (int) array + sizeof array) | |
1547 | { | |
1548 | *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION; | |
1549 | ptr += INSN_CACHE_LINE_WIDTH; | |
1550 | } | |
1551 | ||
1552 | initialized = 1; | |
1553 | } | |
1554 | ||
1555 | /* Find the location in array that occupies the same cache line as BEG. */ | |
1556 | ||
1557 | offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1); | |
1558 | start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1) | |
1559 | & -INSN_CACHE_PLANE_SIZE) | |
1560 | + offset); | |
1561 | ||
1562 | /* Compute the cache alignment of the place to stop clearing. */ | |
1563 | #if 0 /* This is not needed for gcc's purposes. */ | |
1564 | /* If the block to clear is bigger than a cache plane, | |
23190837 | 1565 | we clear the entire cache, and OFFSET is already correct. */ |
203b91b9 RS |
1566 | if (end < beg + INSN_CACHE_PLANE_SIZE) |
1567 | #endif | |
1568 | offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1) | |
1569 | & -INSN_CACHE_LINE_WIDTH) | |
1570 | & (INSN_CACHE_PLANE_SIZE - 1)); | |
1571 | ||
1572 | #if INSN_CACHE_DEPTH > 1 | |
1573 | end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset; | |
1574 | if (end_addr <= start_addr) | |
1575 | end_addr += INSN_CACHE_PLANE_SIZE; | |
1576 | ||
1577 | for (plane = 0; plane < INSN_CACHE_DEPTH; plane++) | |
1578 | { | |
1579 | int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE; | |
1580 | int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE; | |
1581 | ||
1582 | while (addr != stop) | |
1583 | { | |
1584 | /* Call the return instruction at ADDR. */ | |
1585 | ((function_ptr) addr) (); | |
1586 | ||
1587 | addr += INSN_CACHE_LINE_WIDTH; | |
1588 | } | |
1589 | } | |
1590 | #else /* just one plane */ | |
1591 | do | |
1592 | { | |
1593 | /* Call the return instruction at START_ADDR. */ | |
1594 | ((function_ptr) start_addr) (); | |
1595 | ||
1596 | start_addr += INSN_CACHE_LINE_WIDTH; | |
1597 | } | |
1598 | while ((start_addr % INSN_CACHE_SIZE) != offset); | |
1599 | #endif /* just one plane */ | |
1600 | #endif /* Cache is large */ | |
1601 | #endif /* Cache exists */ | |
e1178973 | 1602 | #endif /* CLEAR_INSN_CACHE */ |
203b91b9 RS |
1603 | } |
1604 | ||
1605 | #endif /* L_clear_cache */ | |
1606 | \f | |
1607 | #ifdef L_trampoline | |
1608 | ||
1609 | /* Jump to a trampoline, loading the static chain address. */ | |
1610 | ||
b27d2bd5 | 1611 | #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN) |
e3367a77 | 1612 | |
3e7d8ef1 KG |
1613 | long |
1614 | getpagesize (void) | |
f5ea9817 RK |
1615 | { |
1616 | #ifdef _ALPHA_ | |
1617 | return 8192; | |
1618 | #else | |
1619 | return 4096; | |
1620 | #endif | |
1621 | } | |
1622 | ||
d7ebf9ea | 1623 | #ifdef __i386__ |
e4b15106 RK |
1624 | extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall)); |
1625 | #endif | |
1626 | ||
272e2587 RK |
1627 | int |
1628 | mprotect (char *addr, int len, int prot) | |
f5ea9817 RK |
1629 | { |
1630 | int np, op; | |
1631 | ||
272e2587 RK |
1632 | if (prot == 7) |
1633 | np = 0x40; | |
1634 | else if (prot == 5) | |
1635 | np = 0x20; | |
1636 | else if (prot == 4) | |
1637 | np = 0x10; | |
1638 | else if (prot == 3) | |
1639 | np = 0x04; | |
1640 | else if (prot == 1) | |
1641 | np = 0x02; | |
1642 | else if (prot == 0) | |
1643 | np = 0x01; | |
f5ea9817 RK |
1644 | |
1645 | if (VirtualProtect (addr, len, np, &op)) | |
1646 | return 0; | |
1647 | else | |
1648 | return -1; | |
f5ea9817 RK |
1649 | } |
1650 | ||
b27d2bd5 | 1651 | #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */ |
f5ea9817 | 1652 | |
23190837 AJ |
1653 | #ifdef TRANSFER_FROM_TRAMPOLINE |
1654 | TRANSFER_FROM_TRAMPOLINE | |
203b91b9 RS |
1655 | #endif |
1656 | ||
c1381fd3 KKT |
1657 | #if defined (NeXT) && defined (__MACH__) |
1658 | ||
1659 | /* Make stack executable so we can call trampolines on stack. | |
1660 | This is called from INITIALIZE_TRAMPOLINE in next.h. */ | |
c5df463e RK |
1661 | #ifdef NeXTStep21 |
1662 | #include <mach.h> | |
1663 | #else | |
1664 | #include <mach/mach.h> | |
1665 | #endif | |
c1381fd3 KKT |
1666 | |
1667 | void | |
37ef1054 | 1668 | __enable_execute_stack (char *addr) |
c1381fd3 KKT |
1669 | { |
1670 | kern_return_t r; | |
1671 | char *eaddr = addr + TRAMPOLINE_SIZE; | |
1672 | vm_address_t a = (vm_address_t) addr; | |
1673 | ||
1674 | /* turn on execute access on stack */ | |
1675 | r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL); | |
1676 | if (r != KERN_SUCCESS) | |
1677 | { | |
1678 | mach_error("vm_protect VM_PROT_ALL", r); | |
1679 | exit(1); | |
1680 | } | |
1681 | ||
1682 | /* We inline the i-cache invalidation for speed */ | |
1683 | ||
1684 | #ifdef CLEAR_INSN_CACHE | |
1685 | CLEAR_INSN_CACHE (addr, eaddr); | |
1686 | #else | |
1687 | __clear_cache ((int) addr, (int) eaddr); | |
1688 | #endif | |
23190837 | 1689 | } |
c1381fd3 KKT |
1690 | |
1691 | #endif /* defined (NeXT) && defined (__MACH__) */ | |
1692 | ||
203b91b9 RS |
1693 | #ifdef __convex__ |
1694 | ||
1695 | /* Make stack executable so we can call trampolines on stack. | |
1696 | This is called from INITIALIZE_TRAMPOLINE in convex.h. */ | |
1697 | ||
1698 | #include <sys/mman.h> | |
1699 | #include <sys/vmparam.h> | |
1700 | #include <machine/machparam.h> | |
1701 | ||
1702 | void | |
3e7d8ef1 | 1703 | __enable_execute_stack (void) |
203b91b9 RS |
1704 | { |
1705 | int fp; | |
1706 | static unsigned lowest = USRSTACK; | |
1707 | unsigned current = (unsigned) &fp & -NBPG; | |
1708 | ||
1709 | if (lowest > current) | |
1710 | { | |
1711 | unsigned len = lowest - current; | |
1712 | mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); | |
1713 | lowest = current; | |
1714 | } | |
1715 | ||
0f41302f | 1716 | /* Clear instruction cache in case an old trampoline is in it. */ |
203b91b9 RS |
1717 | asm ("pich"); |
1718 | } | |
1719 | #endif /* __convex__ */ | |
b335c2cc | 1720 | |
db87ec0b | 1721 | #ifdef __sysV88__ |
0c8ae3d3 | 1722 | |
0f41302f | 1723 | /* Modified from the convex -code above. */ |
0c8ae3d3 RK |
1724 | |
1725 | #include <sys/param.h> | |
1726 | #include <errno.h> | |
1727 | #include <sys/m88kbcs.h> | |
1728 | ||
1729 | void | |
3e7d8ef1 | 1730 | __enable_execute_stack (void) |
0c8ae3d3 RK |
1731 | { |
1732 | int save_errno; | |
1733 | static unsigned long lowest = USRSTACK; | |
1734 | unsigned long current = (unsigned long) &save_errno & -NBPC; | |
23190837 | 1735 | |
0c8ae3d3 | 1736 | /* Ignore errno being set. memctl sets errno to EINVAL whenever the |
6d2f8887 | 1737 | address is seen as 'negative'. That is the case with the stack. */ |
0c8ae3d3 RK |
1738 | |
1739 | save_errno=errno; | |
1740 | if (lowest > current) | |
1741 | { | |
1742 | unsigned len=lowest-current; | |
1743 | memctl(current,len,MCT_TEXT); | |
1744 | lowest = current; | |
1745 | } | |
1746 | else | |
1747 | memctl(current,NBPC,MCT_TEXT); | |
1748 | errno=save_errno; | |
1749 | } | |
1750 | ||
db87ec0b | 1751 | #endif /* __sysV88__ */ |
0c8ae3d3 | 1752 | |
c85f7c16 JL |
1753 | #ifdef __sysV68__ |
1754 | ||
1755 | #include <sys/signal.h> | |
1756 | #include <errno.h> | |
1757 | ||
1758 | /* Motorola forgot to put memctl.o in the libp version of libc881.a, | |
1759 | so define it here, because we need it in __clear_insn_cache below */ | |
3698f44e MH |
1760 | /* On older versions of this OS, no memctl or MCT_TEXT are defined; |
1761 | hence we enable this stuff only if MCT_TEXT is #define'd. */ | |
c85f7c16 | 1762 | |
3698f44e | 1763 | #ifdef MCT_TEXT |
c85f7c16 JL |
1764 | asm("\n\ |
1765 | global memctl\n\ | |
1766 | memctl:\n\ | |
1767 | movq &75,%d0\n\ | |
1768 | trap &0\n\ | |
1769 | bcc.b noerror\n\ | |
1770 | jmp cerror%\n\ | |
1771 | noerror:\n\ | |
1772 | movq &0,%d0\n\ | |
1773 | rts"); | |
3698f44e | 1774 | #endif |
c85f7c16 JL |
1775 | |
1776 | /* Clear instruction cache so we can call trampolines on stack. | |
1777 | This is called from FINALIZE_TRAMPOLINE in mot3300.h. */ | |
1778 | ||
1779 | void | |
3e7d8ef1 | 1780 | __clear_insn_cache (void) |
c85f7c16 | 1781 | { |
3698f44e | 1782 | #ifdef MCT_TEXT |
c85f7c16 JL |
1783 | int save_errno; |
1784 | ||
1785 | /* Preserve errno, because users would be surprised to have | |
dc297297 | 1786 | errno changing without explicitly calling any system-call. */ |
c85f7c16 JL |
1787 | save_errno = errno; |
1788 | ||
23190837 | 1789 | /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache. |
dc297297 | 1790 | No need to use an address derived from _start or %sp, as 0 works also. */ |
c85f7c16 JL |
1791 | memctl(0, 4096, MCT_TEXT); |
1792 | errno = save_errno; | |
3698f44e | 1793 | #endif |
c85f7c16 JL |
1794 | } |
1795 | ||
1796 | #endif /* __sysV68__ */ | |
1797 | ||
b335c2cc TW |
1798 | #ifdef __pyr__ |
1799 | ||
98126ed6 | 1800 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
b335c2cc TW |
1801 | #include <stdio.h> |
1802 | #include <sys/mman.h> | |
1803 | #include <sys/types.h> | |
1804 | #include <sys/param.h> | |
1805 | #include <sys/vmmac.h> | |
1806 | ||
1807 | /* Modified from the convex -code above. | |
0f41302f | 1808 | mremap promises to clear the i-cache. */ |
b335c2cc TW |
1809 | |
1810 | void | |
3e7d8ef1 | 1811 | __enable_execute_stack (void) |
b335c2cc TW |
1812 | { |
1813 | int fp; | |
1814 | if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ, | |
1815 | PROT_READ|PROT_WRITE|PROT_EXEC)) | |
1816 | { | |
1817 | perror ("mprotect in __enable_execute_stack"); | |
1818 | fflush (stderr); | |
1819 | abort (); | |
1820 | } | |
1821 | } | |
1822 | #endif /* __pyr__ */ | |
7d41c411 RK |
1823 | |
1824 | #if defined (sony_news) && defined (SYSTYPE_BSD) | |
1825 | ||
1826 | #include <stdio.h> | |
1827 | #include <sys/types.h> | |
1828 | #include <sys/param.h> | |
1829 | #include <syscall.h> | |
1830 | #include <machine/sysnews.h> | |
1831 | ||
1832 | /* cacheflush function for NEWS-OS 4.2. | |
1833 | This function is called from trampoline-initialize code | |
1834 | defined in config/mips/mips.h. */ | |
1835 | ||
1836 | void | |
37ef1054 | 1837 | cacheflush (char *beg, int size, int flag) |
7d41c411 RK |
1838 | { |
1839 | if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE)) | |
1840 | { | |
1841 | perror ("cache_flush"); | |
1842 | fflush (stderr); | |
1843 | abort (); | |
1844 | } | |
1845 | } | |
1846 | ||
1847 | #endif /* sony_news */ | |
203b91b9 RS |
1848 | #endif /* L_trampoline */ |
1849 | \f | |
cae21ae8 | 1850 | #ifndef __CYGWIN__ |
203b91b9 RS |
1851 | #ifdef L__main |
1852 | ||
1853 | #include "gbl-ctors.h" | |
c06cff95 RS |
1854 | /* Some systems use __main in a way incompatible with its use in gcc, in these |
1855 | cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to | |
1856 | give the same symbol without quotes for an alternative entry point. You | |
0f41302f | 1857 | must define both, or neither. */ |
c06cff95 RS |
1858 | #ifndef NAME__MAIN |
1859 | #define NAME__MAIN "__main" | |
1860 | #define SYMBOL__MAIN __main | |
1861 | #endif | |
203b91b9 | 1862 | |
fe1fd353 JM |
1863 | #ifdef INIT_SECTION_ASM_OP |
1864 | #undef HAS_INIT_SECTION | |
1865 | #define HAS_INIT_SECTION | |
1866 | #endif | |
1867 | ||
1868 | #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF) | |
31cf0144 JM |
1869 | |
1870 | /* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this | |
1871 | code to run constructors. In that case, we need to handle EH here, too. */ | |
1872 | ||
540ceb67 | 1873 | #ifdef EH_FRAME_SECTION_NAME |
e4b776a6 | 1874 | #include "unwind-dw2-fde.h" |
31cf0144 JM |
1875 | extern unsigned char __EH_FRAME_BEGIN__[]; |
1876 | #endif | |
1877 | ||
203b91b9 RS |
1878 | /* Run all the global destructors on exit from the program. */ |
1879 | ||
1880 | void | |
3e7d8ef1 | 1881 | __do_global_dtors (void) |
203b91b9 | 1882 | { |
89cf554b RS |
1883 | #ifdef DO_GLOBAL_DTORS_BODY |
1884 | DO_GLOBAL_DTORS_BODY; | |
1885 | #else | |
b40b9d93 MS |
1886 | static func_ptr *p = __DTOR_LIST__ + 1; |
1887 | while (*p) | |
1888 | { | |
1889 | p++; | |
1890 | (*(p-1)) (); | |
1891 | } | |
89cf554b | 1892 | #endif |
540ceb67 | 1893 | #if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION) |
a4ebb0e6 GRK |
1894 | { |
1895 | static int completed = 0; | |
1896 | if (! completed) | |
1897 | { | |
1898 | completed = 1; | |
1899 | __deregister_frame_info (__EH_FRAME_BEGIN__); | |
1900 | } | |
1901 | } | |
31cf0144 | 1902 | #endif |
203b91b9 | 1903 | } |
68d69835 | 1904 | #endif |
203b91b9 | 1905 | |
fe1fd353 | 1906 | #ifndef HAS_INIT_SECTION |
203b91b9 RS |
1907 | /* Run all the global constructors on entry to the program. */ |
1908 | ||
203b91b9 | 1909 | void |
3e7d8ef1 | 1910 | __do_global_ctors (void) |
203b91b9 | 1911 | { |
540ceb67 | 1912 | #ifdef EH_FRAME_SECTION_NAME |
31cf0144 JM |
1913 | { |
1914 | static struct object object; | |
1915 | __register_frame_info (__EH_FRAME_BEGIN__, &object); | |
1916 | } | |
1917 | #endif | |
203b91b9 | 1918 | DO_GLOBAL_CTORS_BODY; |
a218d5ba | 1919 | atexit (__do_global_dtors); |
203b91b9 | 1920 | } |
fe1fd353 | 1921 | #endif /* no HAS_INIT_SECTION */ |
203b91b9 | 1922 | |
fe1fd353 | 1923 | #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main) |
203b91b9 RS |
1924 | /* Subroutine called automatically by `main'. |
1925 | Compiling a global function named `main' | |
1926 | produces an automatic call to this function at the beginning. | |
1927 | ||
1928 | For many systems, this routine calls __do_global_ctors. | |
1929 | For systems which support a .init section we use the .init section | |
1930 | to run __do_global_ctors, so we need not do anything here. */ | |
1931 | ||
1932 | void | |
c06cff95 | 1933 | SYMBOL__MAIN () |
203b91b9 RS |
1934 | { |
1935 | /* Support recursive calls to `main': run initializers just once. */ | |
7e6f1890 | 1936 | static int initialized; |
203b91b9 RS |
1937 | if (! initialized) |
1938 | { | |
1939 | initialized = 1; | |
1940 | __do_global_ctors (); | |
1941 | } | |
1942 | } | |
fe1fd353 | 1943 | #endif /* no HAS_INIT_SECTION or INVOKE__main */ |
203b91b9 RS |
1944 | |
1945 | #endif /* L__main */ | |
cae21ae8 | 1946 | #endif /* __CYGWIN__ */ |
203b91b9 | 1947 | \f |
ad38743d | 1948 | #ifdef L_ctors |
203b91b9 RS |
1949 | |
1950 | #include "gbl-ctors.h" | |
1951 | ||
1952 | /* Provide default definitions for the lists of constructors and | |
657be7af JL |
1953 | destructors, so that we don't get linker errors. These symbols are |
1954 | intentionally bss symbols, so that gld and/or collect will provide | |
1955 | the right values. */ | |
203b91b9 RS |
1956 | |
1957 | /* We declare the lists here with two elements each, | |
657be7af JL |
1958 | so that they are valid empty lists if no other definition is loaded. |
1959 | ||
1960 | If we are using the old "set" extensions to have the gnu linker | |
1961 | collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__ | |
1962 | must be in the bss/common section. | |
1963 | ||
1964 | Long term no port should use those extensions. But many still do. */ | |
b335c2cc | 1965 | #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY) |
aa6ad1a6 | 1966 | #if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2) |
d15d0264 RS |
1967 | func_ptr __CTOR_LIST__[2] = {0, 0}; |
1968 | func_ptr __DTOR_LIST__[2] = {0, 0}; | |
657be7af JL |
1969 | #else |
1970 | func_ptr __CTOR_LIST__[2]; | |
1971 | func_ptr __DTOR_LIST__[2]; | |
1972 | #endif | |
b335c2cc | 1973 | #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ |
ad38743d RS |
1974 | #endif /* L_ctors */ |
1975 | \f | |
1976 | #ifdef L_exit | |
1977 | ||
1978 | #include "gbl-ctors.h" | |
203b91b9 | 1979 | |
8b7677be | 1980 | #ifdef NEED_ATEXIT |
8b7677be | 1981 | |
f75e8946 | 1982 | #ifndef ON_EXIT |
203b91b9 | 1983 | |
8b7677be RK |
1984 | # include <errno.h> |
1985 | ||
920b13cc | 1986 | static func_ptr *atexit_chain = 0; |
8b7677be RK |
1987 | static long atexit_chain_length = 0; |
1988 | static volatile long last_atexit_chain_slot = -1; | |
1989 | ||
c063dc98 JM |
1990 | int |
1991 | atexit (func_ptr func) | |
8b7677be RK |
1992 | { |
1993 | if (++last_atexit_chain_slot == atexit_chain_length) | |
1994 | { | |
1995 | atexit_chain_length += 32; | |
1996 | if (atexit_chain) | |
a25cea96 RK |
1997 | atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length |
1998 | * sizeof (func_ptr)); | |
8b7677be | 1999 | else |
a25cea96 RK |
2000 | atexit_chain = (func_ptr *) malloc (atexit_chain_length |
2001 | * sizeof (func_ptr)); | |
8b7677be RK |
2002 | if (! atexit_chain) |
2003 | { | |
2004 | atexit_chain_length = 0; | |
2005 | last_atexit_chain_slot = -1; | |
2006 | errno = ENOMEM; | |
2007 | return (-1); | |
2008 | } | |
2009 | } | |
2010 | atexit_chain[last_atexit_chain_slot] = func; | |
2011 | return (0); | |
2012 | } | |
8b7677be | 2013 | |
3e7d8ef1 KG |
2014 | extern void _cleanup (void); |
2015 | extern void _exit (int) __attribute__ ((__noreturn__)); | |
203b91b9 | 2016 | |
23190837 | 2017 | void |
37ef1054 | 2018 | exit (int status) |
203b91b9 | 2019 | { |
8b7677be RK |
2020 | if (atexit_chain) |
2021 | { | |
2022 | for ( ; last_atexit_chain_slot-- >= 0; ) | |
2023 | { | |
2024 | (*atexit_chain[last_atexit_chain_slot + 1]) (); | |
920b13cc | 2025 | atexit_chain[last_atexit_chain_slot + 1] = 0; |
8b7677be RK |
2026 | } |
2027 | free (atexit_chain); | |
920b13cc | 2028 | atexit_chain = 0; |
8b7677be | 2029 | } |
203b91b9 RS |
2030 | #ifdef EXIT_BODY |
2031 | EXIT_BODY; | |
2032 | #else | |
2033 | _cleanup (); | |
2034 | #endif | |
2035 | _exit (status); | |
2036 | } | |
2037 | ||
f75e8946 | 2038 | #else /* ON_EXIT */ |
bceb30e7 | 2039 | |
c063dc98 JM |
2040 | /* Simple; we just need a wrapper for ON_EXIT. */ |
2041 | int | |
2042 | atexit (func_ptr func) | |
bceb30e7 | 2043 | { |
c063dc98 | 2044 | return ON_EXIT (func); |
bceb30e7 | 2045 | } |
c063dc98 | 2046 | |
f75e8946 | 2047 | #endif /* ON_EXIT */ |
c063dc98 | 2048 | #endif /* NEED_ATEXIT */ |
203b91b9 RS |
2049 | |
2050 | #endif /* L_exit */ |