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