1 | /* More subroutines needed by GCC output code on some machines. */ |
---|
2 | /* Compile this one with gcc. */ |
---|
3 | /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. |
---|
4 | |
---|
5 | This file is part of GNU CC. |
---|
6 | |
---|
7 | GNU CC is free software; you can redistribute it and/or modify |
---|
8 | it under the terms of the GNU General Public License as published by |
---|
9 | the Free Software Foundation; either version 2, or (at your option) |
---|
10 | any later version. |
---|
11 | |
---|
12 | GNU CC is distributed in the hope that it will be useful, |
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | GNU General Public License for more details. |
---|
16 | |
---|
17 | You should have received a copy of the GNU General Public License |
---|
18 | along with GNU CC; see the file COPYING. If not, write to |
---|
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
20 | Boston, MA 02111-1307, USA. */ |
---|
21 | |
---|
22 | /* As a special exception, if you link this library with other files, |
---|
23 | some of which are compiled with GCC, to produce an executable, |
---|
24 | this library does not by itself cause the resulting executable |
---|
25 | to be covered by the GNU General Public License. |
---|
26 | This exception does not however invalidate any other reasons why |
---|
27 | the executable file might be covered by the GNU General Public License. */ |
---|
28 | |
---|
29 | /* It is incorrect to include config.h here, because this file is being |
---|
30 | compiled for the target, and hence definitions concerning only the host |
---|
31 | do not apply. */ |
---|
32 | |
---|
33 | #include "tconfig.h" |
---|
34 | #include "machmode.h" |
---|
35 | #include "defaults.h" |
---|
36 | #ifndef L_trampoline |
---|
37 | #include <stddef.h> |
---|
38 | #endif |
---|
39 | |
---|
40 | /* Don't use `fancy_abort' here even if config.h says to use it. */ |
---|
41 | #ifdef abort |
---|
42 | #undef abort |
---|
43 | #endif |
---|
44 | |
---|
45 | #if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF) |
---|
46 | #define WEAK_ALIAS |
---|
47 | #endif |
---|
48 | |
---|
49 | /* Permit the tm.h file to select the endianness to use just for this |
---|
50 | file. This is used when the endianness is determined when the |
---|
51 | compiler is run. */ |
---|
52 | |
---|
53 | #ifndef LIBGCC2_WORDS_BIG_ENDIAN |
---|
54 | #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN |
---|
55 | #endif |
---|
56 | |
---|
57 | /* In the first part of this file, we are interfacing to calls generated |
---|
58 | by the compiler itself. These calls pass values into these routines |
---|
59 | which have very specific modes (rather than very specific types), and |
---|
60 | these compiler-generated calls also expect any return values to have |
---|
61 | very specific modes (rather than very specific types). Thus, we need |
---|
62 | to avoid using regular C language type names in this part of the file |
---|
63 | because the sizes for those types can be configured to be anything. |
---|
64 | Instead we use the following special type names. */ |
---|
65 | |
---|
66 | typedef unsigned int UQItype __attribute__ ((mode (QI))); |
---|
67 | typedef int SItype __attribute__ ((mode (SI))); |
---|
68 | typedef unsigned int USItype __attribute__ ((mode (SI))); |
---|
69 | typedef int DItype __attribute__ ((mode (DI))); |
---|
70 | typedef unsigned int UDItype __attribute__ ((mode (DI))); |
---|
71 | |
---|
72 | typedef float SFtype __attribute__ ((mode (SF))); |
---|
73 | typedef float DFtype __attribute__ ((mode (DF))); |
---|
74 | |
---|
75 | #if LONG_DOUBLE_TYPE_SIZE == 96 |
---|
76 | typedef float XFtype __attribute__ ((mode (XF))); |
---|
77 | #endif |
---|
78 | #if LONG_DOUBLE_TYPE_SIZE == 128 |
---|
79 | typedef float TFtype __attribute__ ((mode (TF))); |
---|
80 | #endif |
---|
81 | |
---|
82 | typedef int word_type __attribute__ ((mode (__word__))); |
---|
83 | |
---|
84 | /* Make sure that we don't accidentally use any normal C language built-in |
---|
85 | type names in the first part of this file. Instead we want to use *only* |
---|
86 | the type names defined above. The following macro definitions insure |
---|
87 | that if we *do* accidentally use some normal C language built-in type name, |
---|
88 | we will get a syntax error. */ |
---|
89 | |
---|
90 | #define char bogus_type |
---|
91 | #define short bogus_type |
---|
92 | #define int bogus_type |
---|
93 | #define long bogus_type |
---|
94 | #define unsigned bogus_type |
---|
95 | #define float bogus_type |
---|
96 | #define double bogus_type |
---|
97 | |
---|
98 | #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
99 | |
---|
100 | /* DIstructs are pairs of SItype values in the order determined by |
---|
101 | LIBGCC2_WORDS_BIG_ENDIAN. */ |
---|
102 | |
---|
103 | #if LIBGCC2_WORDS_BIG_ENDIAN |
---|
104 | struct DIstruct {SItype high, low;}; |
---|
105 | #else |
---|
106 | struct DIstruct {SItype low, high;}; |
---|
107 | #endif |
---|
108 | |
---|
109 | /* We need this union to unpack/pack DImode values, since we don't have |
---|
110 | any arithmetic yet. Incoming DImode parameters are stored into the |
---|
111 | `ll' field, and the unpacked result is read from the struct `s'. */ |
---|
112 | |
---|
113 | typedef union |
---|
114 | { |
---|
115 | struct DIstruct s; |
---|
116 | DItype ll; |
---|
117 | } DIunion; |
---|
118 | |
---|
119 | #if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\ |
---|
120 | || defined (L_divdi3) || defined (L_udivdi3) \ |
---|
121 | || defined (L_moddi3) || defined (L_umoddi3)) |
---|
122 | |
---|
123 | #include "longlong.h" |
---|
124 | |
---|
125 | #endif /* udiv or mul */ |
---|
126 | |
---|
127 | extern DItype __fixunssfdi (SFtype a); |
---|
128 | extern DItype __fixunsdfdi (DFtype a); |
---|
129 | #if LONG_DOUBLE_TYPE_SIZE == 96 |
---|
130 | extern DItype __fixunsxfdi (XFtype a); |
---|
131 | #endif |
---|
132 | #if LONG_DOUBLE_TYPE_SIZE == 128 |
---|
133 | extern DItype __fixunstfdi (TFtype a); |
---|
134 | #endif |
---|
135 | |
---|
136 | #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) |
---|
137 | #if defined (L_divdi3) || defined (L_moddi3) |
---|
138 | static inline |
---|
139 | #endif |
---|
140 | DItype |
---|
141 | __negdi2 (u) |
---|
142 | DItype u; |
---|
143 | { |
---|
144 | DIunion w; |
---|
145 | DIunion uu; |
---|
146 | |
---|
147 | uu.ll = u; |
---|
148 | |
---|
149 | w.s.low = -uu.s.low; |
---|
150 | w.s.high = -uu.s.high - ((USItype) w.s.low > 0); |
---|
151 | |
---|
152 | return w.ll; |
---|
153 | } |
---|
154 | #endif |
---|
155 | |
---|
156 | #ifdef L_lshrdi3 |
---|
157 | DItype |
---|
158 | __lshrdi3 (u, b) |
---|
159 | DItype u; |
---|
160 | word_type b; |
---|
161 | { |
---|
162 | DIunion w; |
---|
163 | word_type bm; |
---|
164 | DIunion uu; |
---|
165 | |
---|
166 | if (b == 0) |
---|
167 | return u; |
---|
168 | |
---|
169 | uu.ll = u; |
---|
170 | |
---|
171 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; |
---|
172 | if (bm <= 0) |
---|
173 | { |
---|
174 | w.s.high = 0; |
---|
175 | w.s.low = (USItype)uu.s.high >> -bm; |
---|
176 | } |
---|
177 | else |
---|
178 | { |
---|
179 | USItype carries = (USItype)uu.s.high << bm; |
---|
180 | w.s.high = (USItype)uu.s.high >> b; |
---|
181 | w.s.low = ((USItype)uu.s.low >> b) | carries; |
---|
182 | } |
---|
183 | |
---|
184 | return w.ll; |
---|
185 | } |
---|
186 | #endif |
---|
187 | |
---|
188 | #ifdef L_ashldi3 |
---|
189 | DItype |
---|
190 | __ashldi3 (u, b) |
---|
191 | DItype u; |
---|
192 | word_type b; |
---|
193 | { |
---|
194 | DIunion w; |
---|
195 | word_type bm; |
---|
196 | DIunion uu; |
---|
197 | |
---|
198 | if (b == 0) |
---|
199 | return u; |
---|
200 | |
---|
201 | uu.ll = u; |
---|
202 | |
---|
203 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; |
---|
204 | if (bm <= 0) |
---|
205 | { |
---|
206 | w.s.low = 0; |
---|
207 | w.s.high = (USItype)uu.s.low << -bm; |
---|
208 | } |
---|
209 | else |
---|
210 | { |
---|
211 | USItype carries = (USItype)uu.s.low >> bm; |
---|
212 | w.s.low = (USItype)uu.s.low << b; |
---|
213 | w.s.high = ((USItype)uu.s.high << b) | carries; |
---|
214 | } |
---|
215 | |
---|
216 | return w.ll; |
---|
217 | } |
---|
218 | #endif |
---|
219 | |
---|
220 | #ifdef L_ashrdi3 |
---|
221 | DItype |
---|
222 | __ashrdi3 (u, b) |
---|
223 | DItype u; |
---|
224 | word_type b; |
---|
225 | { |
---|
226 | DIunion w; |
---|
227 | word_type bm; |
---|
228 | DIunion uu; |
---|
229 | |
---|
230 | if (b == 0) |
---|
231 | return u; |
---|
232 | |
---|
233 | uu.ll = u; |
---|
234 | |
---|
235 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; |
---|
236 | if (bm <= 0) |
---|
237 | { |
---|
238 | /* w.s.high = 1..1 or 0..0 */ |
---|
239 | w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); |
---|
240 | w.s.low = uu.s.high >> -bm; |
---|
241 | } |
---|
242 | else |
---|
243 | { |
---|
244 | USItype carries = (USItype)uu.s.high << bm; |
---|
245 | w.s.high = uu.s.high >> b; |
---|
246 | w.s.low = ((USItype)uu.s.low >> b) | carries; |
---|
247 | } |
---|
248 | |
---|
249 | return w.ll; |
---|
250 | } |
---|
251 | #endif |
---|
252 | |
---|
253 | #ifdef L_ffsdi2 |
---|
254 | DItype |
---|
255 | __ffsdi2 (u) |
---|
256 | DItype u; |
---|
257 | { |
---|
258 | DIunion uu, w; |
---|
259 | uu.ll = u; |
---|
260 | w.s.high = 0; |
---|
261 | w.s.low = ffs (uu.s.low); |
---|
262 | if (w.s.low != 0) |
---|
263 | return w.ll; |
---|
264 | w.s.low = ffs (uu.s.high); |
---|
265 | if (w.s.low != 0) |
---|
266 | { |
---|
267 | w.s.low += BITS_PER_UNIT * sizeof (SItype); |
---|
268 | return w.ll; |
---|
269 | } |
---|
270 | return w.ll; |
---|
271 | } |
---|
272 | #endif |
---|
273 | |
---|
274 | #ifdef L_muldi3 |
---|
275 | DItype |
---|
276 | __muldi3 (u, v) |
---|
277 | DItype u, v; |
---|
278 | { |
---|
279 | DIunion w; |
---|
280 | DIunion uu, vv; |
---|
281 | |
---|
282 | uu.ll = u, |
---|
283 | vv.ll = v; |
---|
284 | |
---|
285 | w.ll = __umulsidi3 (uu.s.low, vv.s.low); |
---|
286 | w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high |
---|
287 | + (USItype) uu.s.high * (USItype) vv.s.low); |
---|
288 | |
---|
289 | return w.ll; |
---|
290 | } |
---|
291 | #endif |
---|
292 | |
---|
293 | #ifdef L_udiv_w_sdiv |
---|
294 | #if defined (sdiv_qrnnd) |
---|
295 | USItype |
---|
296 | __udiv_w_sdiv (rp, a1, a0, d) |
---|
297 | USItype *rp, a1, a0, d; |
---|
298 | { |
---|
299 | USItype q, r; |
---|
300 | USItype c0, c1, b1; |
---|
301 | |
---|
302 | if ((SItype) d >= 0) |
---|
303 | { |
---|
304 | if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1))) |
---|
305 | { |
---|
306 | /* dividend, divisor, and quotient are nonnegative */ |
---|
307 | sdiv_qrnnd (q, r, a1, a0, d); |
---|
308 | } |
---|
309 | else |
---|
310 | { |
---|
311 | /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ |
---|
312 | sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1)); |
---|
313 | /* Divide (c1*2^32 + c0) by d */ |
---|
314 | sdiv_qrnnd (q, r, c1, c0, d); |
---|
315 | /* Add 2^31 to quotient */ |
---|
316 | q += (USItype) 1 << (SI_TYPE_SIZE - 1); |
---|
317 | } |
---|
318 | } |
---|
319 | else |
---|
320 | { |
---|
321 | b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ |
---|
322 | c1 = a1 >> 1; /* A/2 */ |
---|
323 | c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1); |
---|
324 | |
---|
325 | if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ |
---|
326 | { |
---|
327 | sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ |
---|
328 | |
---|
329 | r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ |
---|
330 | if ((d & 1) != 0) |
---|
331 | { |
---|
332 | if (r >= q) |
---|
333 | r = r - q; |
---|
334 | else if (q - r <= d) |
---|
335 | { |
---|
336 | r = r - q + d; |
---|
337 | q--; |
---|
338 | } |
---|
339 | else |
---|
340 | { |
---|
341 | r = r - q + 2*d; |
---|
342 | q -= 2; |
---|
343 | } |
---|
344 | } |
---|
345 | } |
---|
346 | else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ |
---|
347 | { |
---|
348 | c1 = (b1 - 1) - c1; |
---|
349 | c0 = ~c0; /* logical NOT */ |
---|
350 | |
---|
351 | sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ |
---|
352 | |
---|
353 | q = ~q; /* (A/2)/b1 */ |
---|
354 | r = (b1 - 1) - r; |
---|
355 | |
---|
356 | r = 2*r + (a0 & 1); /* A/(2*b1) */ |
---|
357 | |
---|
358 | if ((d & 1) != 0) |
---|
359 | { |
---|
360 | if (r >= q) |
---|
361 | r = r - q; |
---|
362 | else if (q - r <= d) |
---|
363 | { |
---|
364 | r = r - q + d; |
---|
365 | q--; |
---|
366 | } |
---|
367 | else |
---|
368 | { |
---|
369 | r = r - q + 2*d; |
---|
370 | q -= 2; |
---|
371 | } |
---|
372 | } |
---|
373 | } |
---|
374 | else /* Implies c1 = b1 */ |
---|
375 | { /* Hence a1 = d - 1 = 2*b1 - 1 */ |
---|
376 | if (a0 >= -d) |
---|
377 | { |
---|
378 | q = -1; |
---|
379 | r = a0 + d; |
---|
380 | } |
---|
381 | else |
---|
382 | { |
---|
383 | q = -2; |
---|
384 | r = a0 + 2*d; |
---|
385 | } |
---|
386 | } |
---|
387 | } |
---|
388 | |
---|
389 | *rp = r; |
---|
390 | return q; |
---|
391 | } |
---|
392 | #else |
---|
393 | /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */ |
---|
394 | USItype |
---|
395 | __udiv_w_sdiv (rp, a1, a0, d) |
---|
396 | USItype *rp, a1, a0, d; |
---|
397 | {} |
---|
398 | #endif |
---|
399 | #endif |
---|
400 | |
---|
401 | #if (defined (L_udivdi3) || defined (L_divdi3) || \ |
---|
402 | defined (L_umoddi3) || defined (L_moddi3)) |
---|
403 | #define L_udivmoddi4 |
---|
404 | #endif |
---|
405 | |
---|
406 | #ifdef L_udivmoddi4 |
---|
407 | static const UQItype __clz_tab[] = |
---|
408 | { |
---|
409 | 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, |
---|
410 | 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, |
---|
411 | 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, |
---|
412 | 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, |
---|
413 | 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, |
---|
414 | 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, |
---|
415 | 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, |
---|
416 | 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, |
---|
417 | }; |
---|
418 | |
---|
419 | #if (defined (L_udivdi3) || defined (L_divdi3) || \ |
---|
420 | defined (L_umoddi3) || defined (L_moddi3)) |
---|
421 | static inline |
---|
422 | #endif |
---|
423 | UDItype |
---|
424 | __udivmoddi4 (n, d, rp) |
---|
425 | UDItype n, d; |
---|
426 | UDItype *rp; |
---|
427 | { |
---|
428 | DIunion ww; |
---|
429 | DIunion nn, dd; |
---|
430 | DIunion rr; |
---|
431 | USItype d0, d1, n0, n1, n2; |
---|
432 | USItype q0, q1; |
---|
433 | USItype b, bm; |
---|
434 | |
---|
435 | nn.ll = n; |
---|
436 | dd.ll = d; |
---|
437 | |
---|
438 | d0 = dd.s.low; |
---|
439 | d1 = dd.s.high; |
---|
440 | n0 = nn.s.low; |
---|
441 | n1 = nn.s.high; |
---|
442 | |
---|
443 | #if !UDIV_NEEDS_NORMALIZATION |
---|
444 | if (d1 == 0) |
---|
445 | { |
---|
446 | if (d0 > n1) |
---|
447 | { |
---|
448 | /* 0q = nn / 0D */ |
---|
449 | |
---|
450 | udiv_qrnnd (q0, n0, n1, n0, d0); |
---|
451 | q1 = 0; |
---|
452 | |
---|
453 | /* Remainder in n0. */ |
---|
454 | } |
---|
455 | else |
---|
456 | { |
---|
457 | /* qq = NN / 0d */ |
---|
458 | |
---|
459 | if (d0 == 0) |
---|
460 | d0 = 1 / d0; /* Divide intentionally by zero. */ |
---|
461 | |
---|
462 | udiv_qrnnd (q1, n1, 0, n1, d0); |
---|
463 | udiv_qrnnd (q0, n0, n1, n0, d0); |
---|
464 | |
---|
465 | /* Remainder in n0. */ |
---|
466 | } |
---|
467 | |
---|
468 | if (rp != 0) |
---|
469 | { |
---|
470 | rr.s.low = n0; |
---|
471 | rr.s.high = 0; |
---|
472 | *rp = rr.ll; |
---|
473 | } |
---|
474 | } |
---|
475 | |
---|
476 | #else /* UDIV_NEEDS_NORMALIZATION */ |
---|
477 | |
---|
478 | if (d1 == 0) |
---|
479 | { |
---|
480 | if (d0 > n1) |
---|
481 | { |
---|
482 | /* 0q = nn / 0D */ |
---|
483 | |
---|
484 | count_leading_zeros (bm, d0); |
---|
485 | |
---|
486 | if (bm != 0) |
---|
487 | { |
---|
488 | /* Normalize, i.e. make the most significant bit of the |
---|
489 | denominator set. */ |
---|
490 | |
---|
491 | d0 = d0 << bm; |
---|
492 | n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm)); |
---|
493 | n0 = n0 << bm; |
---|
494 | } |
---|
495 | |
---|
496 | udiv_qrnnd (q0, n0, n1, n0, d0); |
---|
497 | q1 = 0; |
---|
498 | |
---|
499 | /* Remainder in n0 >> bm. */ |
---|
500 | } |
---|
501 | else |
---|
502 | { |
---|
503 | /* qq = NN / 0d */ |
---|
504 | |
---|
505 | if (d0 == 0) |
---|
506 | d0 = 1 / d0; /* Divide intentionally by zero. */ |
---|
507 | |
---|
508 | count_leading_zeros (bm, d0); |
---|
509 | |
---|
510 | if (bm == 0) |
---|
511 | { |
---|
512 | /* From (n1 >= d0) /\ (the most significant bit of d0 is set), |
---|
513 | conclude (the most significant bit of n1 is set) /\ (the |
---|
514 | leading quotient digit q1 = 1). |
---|
515 | |
---|
516 | This special case is necessary, not an optimization. |
---|
517 | (Shifts counts of SI_TYPE_SIZE are undefined.) */ |
---|
518 | |
---|
519 | n1 -= d0; |
---|
520 | q1 = 1; |
---|
521 | } |
---|
522 | else |
---|
523 | { |
---|
524 | /* Normalize. */ |
---|
525 | |
---|
526 | b = SI_TYPE_SIZE - bm; |
---|
527 | |
---|
528 | d0 = d0 << bm; |
---|
529 | n2 = n1 >> b; |
---|
530 | n1 = (n1 << bm) | (n0 >> b); |
---|
531 | n0 = n0 << bm; |
---|
532 | |
---|
533 | udiv_qrnnd (q1, n1, n2, n1, d0); |
---|
534 | } |
---|
535 | |
---|
536 | /* n1 != d0... */ |
---|
537 | |
---|
538 | udiv_qrnnd (q0, n0, n1, n0, d0); |
---|
539 | |
---|
540 | /* Remainder in n0 >> bm. */ |
---|
541 | } |
---|
542 | |
---|
543 | if (rp != 0) |
---|
544 | { |
---|
545 | rr.s.low = n0 >> bm; |
---|
546 | rr.s.high = 0; |
---|
547 | *rp = rr.ll; |
---|
548 | } |
---|
549 | } |
---|
550 | #endif /* UDIV_NEEDS_NORMALIZATION */ |
---|
551 | |
---|
552 | else |
---|
553 | { |
---|
554 | if (d1 > n1) |
---|
555 | { |
---|
556 | /* 00 = nn / DD */ |
---|
557 | |
---|
558 | q0 = 0; |
---|
559 | q1 = 0; |
---|
560 | |
---|
561 | /* Remainder in n1n0. */ |
---|
562 | if (rp != 0) |
---|
563 | { |
---|
564 | rr.s.low = n0; |
---|
565 | rr.s.high = n1; |
---|
566 | *rp = rr.ll; |
---|
567 | } |
---|
568 | } |
---|
569 | else |
---|
570 | { |
---|
571 | /* 0q = NN / dd */ |
---|
572 | |
---|
573 | count_leading_zeros (bm, d1); |
---|
574 | if (bm == 0) |
---|
575 | { |
---|
576 | /* From (n1 >= d1) /\ (the most significant bit of d1 is set), |
---|
577 | conclude (the most significant bit of n1 is set) /\ (the |
---|
578 | quotient digit q0 = 0 or 1). |
---|
579 | |
---|
580 | This special case is necessary, not an optimization. */ |
---|
581 | |
---|
582 | /* The condition on the next line takes advantage of that |
---|
583 | n1 >= d1 (true due to program flow). */ |
---|
584 | if (n1 > d1 || n0 >= d0) |
---|
585 | { |
---|
586 | q0 = 1; |
---|
587 | sub_ddmmss (n1, n0, n1, n0, d1, d0); |
---|
588 | } |
---|
589 | else |
---|
590 | q0 = 0; |
---|
591 | |
---|
592 | q1 = 0; |
---|
593 | |
---|
594 | if (rp != 0) |
---|
595 | { |
---|
596 | rr.s.low = n0; |
---|
597 | rr.s.high = n1; |
---|
598 | *rp = rr.ll; |
---|
599 | } |
---|
600 | } |
---|
601 | else |
---|
602 | { |
---|
603 | USItype m1, m0; |
---|
604 | /* Normalize. */ |
---|
605 | |
---|
606 | b = SI_TYPE_SIZE - bm; |
---|
607 | |
---|
608 | d1 = (d1 << bm) | (d0 >> b); |
---|
609 | d0 = d0 << bm; |
---|
610 | n2 = n1 >> b; |
---|
611 | n1 = (n1 << bm) | (n0 >> b); |
---|
612 | n0 = n0 << bm; |
---|
613 | |
---|
614 | udiv_qrnnd (q0, n1, n2, n1, d1); |
---|
615 | umul_ppmm (m1, m0, q0, d0); |
---|
616 | |
---|
617 | if (m1 > n1 || (m1 == n1 && m0 > n0)) |
---|
618 | { |
---|
619 | q0--; |
---|
620 | sub_ddmmss (m1, m0, m1, m0, d1, d0); |
---|
621 | } |
---|
622 | |
---|
623 | q1 = 0; |
---|
624 | |
---|
625 | /* Remainder in (n1n0 - m1m0) >> bm. */ |
---|
626 | if (rp != 0) |
---|
627 | { |
---|
628 | sub_ddmmss (n1, n0, n1, n0, m1, m0); |
---|
629 | rr.s.low = (n1 << b) | (n0 >> bm); |
---|
630 | rr.s.high = n1 >> bm; |
---|
631 | *rp = rr.ll; |
---|
632 | } |
---|
633 | } |
---|
634 | } |
---|
635 | } |
---|
636 | |
---|
637 | ww.s.low = q0; |
---|
638 | ww.s.high = q1; |
---|
639 | return ww.ll; |
---|
640 | } |
---|
641 | #endif |
---|
642 | |
---|
643 | #ifdef L_divdi3 |
---|
644 | UDItype __udivmoddi4 (); |
---|
645 | |
---|
646 | DItype |
---|
647 | __divdi3 (u, v) |
---|
648 | DItype u, v; |
---|
649 | { |
---|
650 | word_type c = 0; |
---|
651 | DIunion uu, vv; |
---|
652 | DItype w; |
---|
653 | |
---|
654 | uu.ll = u; |
---|
655 | vv.ll = v; |
---|
656 | |
---|
657 | if (uu.s.high < 0) |
---|
658 | c = ~c, |
---|
659 | uu.ll = __negdi2 (uu.ll); |
---|
660 | if (vv.s.high < 0) |
---|
661 | c = ~c, |
---|
662 | vv.ll = __negdi2 (vv.ll); |
---|
663 | |
---|
664 | w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0); |
---|
665 | if (c) |
---|
666 | w = __negdi2 (w); |
---|
667 | |
---|
668 | return w; |
---|
669 | } |
---|
670 | #endif |
---|
671 | |
---|
672 | #ifdef L_moddi3 |
---|
673 | UDItype __udivmoddi4 (); |
---|
674 | DItype |
---|
675 | __moddi3 (u, v) |
---|
676 | DItype u, v; |
---|
677 | { |
---|
678 | word_type c = 0; |
---|
679 | DIunion uu, vv; |
---|
680 | DItype w; |
---|
681 | |
---|
682 | uu.ll = u; |
---|
683 | vv.ll = v; |
---|
684 | |
---|
685 | if (uu.s.high < 0) |
---|
686 | c = ~c, |
---|
687 | uu.ll = __negdi2 (uu.ll); |
---|
688 | if (vv.s.high < 0) |
---|
689 | vv.ll = __negdi2 (vv.ll); |
---|
690 | |
---|
691 | (void) __udivmoddi4 (uu.ll, vv.ll, &w); |
---|
692 | if (c) |
---|
693 | w = __negdi2 (w); |
---|
694 | |
---|
695 | return w; |
---|
696 | } |
---|
697 | #endif |
---|
698 | |
---|
699 | #ifdef L_umoddi3 |
---|
700 | UDItype __udivmoddi4 (); |
---|
701 | UDItype |
---|
702 | __umoddi3 (u, v) |
---|
703 | UDItype u, v; |
---|
704 | { |
---|
705 | UDItype w; |
---|
706 | |
---|
707 | (void) __udivmoddi4 (u, v, &w); |
---|
708 | |
---|
709 | return w; |
---|
710 | } |
---|
711 | #endif |
---|
712 | |
---|
713 | #ifdef L_udivdi3 |
---|
714 | UDItype __udivmoddi4 (); |
---|
715 | UDItype |
---|
716 | __udivdi3 (n, d) |
---|
717 | UDItype n, d; |
---|
718 | { |
---|
719 | return __udivmoddi4 (n, d, (UDItype *) 0); |
---|
720 | } |
---|
721 | #endif |
---|
722 | |
---|
723 | #ifdef L_cmpdi2 |
---|
724 | word_type |
---|
725 | __cmpdi2 (a, b) |
---|
726 | DItype a, b; |
---|
727 | { |
---|
728 | DIunion au, bu; |
---|
729 | |
---|
730 | au.ll = a, bu.ll = b; |
---|
731 | |
---|
732 | if (au.s.high < bu.s.high) |
---|
733 | return 0; |
---|
734 | else if (au.s.high > bu.s.high) |
---|
735 | return 2; |
---|
736 | if ((USItype) au.s.low < (USItype) bu.s.low) |
---|
737 | return 0; |
---|
738 | else if ((USItype) au.s.low > (USItype) bu.s.low) |
---|
739 | return 2; |
---|
740 | return 1; |
---|
741 | } |
---|
742 | #endif |
---|
743 | |
---|
744 | #ifdef L_ucmpdi2 |
---|
745 | word_type |
---|
746 | __ucmpdi2 (a, b) |
---|
747 | DItype a, b; |
---|
748 | { |
---|
749 | DIunion au, bu; |
---|
750 | |
---|
751 | au.ll = a, bu.ll = b; |
---|
752 | |
---|
753 | if ((USItype) au.s.high < (USItype) bu.s.high) |
---|
754 | return 0; |
---|
755 | else if ((USItype) au.s.high > (USItype) bu.s.high) |
---|
756 | return 2; |
---|
757 | if ((USItype) au.s.low < (USItype) bu.s.low) |
---|
758 | return 0; |
---|
759 | else if ((USItype) au.s.low > (USItype) bu.s.low) |
---|
760 | return 2; |
---|
761 | return 1; |
---|
762 | } |
---|
763 | #endif |
---|
764 | |
---|
765 | #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128) |
---|
766 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
767 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
768 | |
---|
769 | DItype |
---|
770 | __fixunstfdi (a) |
---|
771 | TFtype a; |
---|
772 | { |
---|
773 | TFtype b; |
---|
774 | UDItype v; |
---|
775 | |
---|
776 | if (a < 0) |
---|
777 | return 0; |
---|
778 | |
---|
779 | /* Compute high word of result, as a flonum. */ |
---|
780 | b = (a / HIGH_WORD_COEFF); |
---|
781 | /* Convert that to fixed (but not to DItype!), |
---|
782 | and shift it into the high word. */ |
---|
783 | v = (USItype) b; |
---|
784 | v <<= WORD_SIZE; |
---|
785 | /* Remove high part from the TFtype, leaving the low part as flonum. */ |
---|
786 | a -= (TFtype)v; |
---|
787 | /* Convert that to fixed (but not to DItype!) and add it in. |
---|
788 | Sometimes A comes out negative. This is significant, since |
---|
789 | A has more bits than a long int does. */ |
---|
790 | if (a < 0) |
---|
791 | v -= (USItype) (- a); |
---|
792 | else |
---|
793 | v += (USItype) a; |
---|
794 | return v; |
---|
795 | } |
---|
796 | #endif |
---|
797 | |
---|
798 | #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128) |
---|
799 | DItype |
---|
800 | __fixtfdi (a) |
---|
801 | TFtype a; |
---|
802 | { |
---|
803 | if (a < 0) |
---|
804 | return - __fixunstfdi (-a); |
---|
805 | return __fixunstfdi (a); |
---|
806 | } |
---|
807 | #endif |
---|
808 | |
---|
809 | #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96) |
---|
810 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
811 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
812 | |
---|
813 | DItype |
---|
814 | __fixunsxfdi (a) |
---|
815 | XFtype a; |
---|
816 | { |
---|
817 | XFtype b; |
---|
818 | UDItype v; |
---|
819 | |
---|
820 | if (a < 0) |
---|
821 | return 0; |
---|
822 | |
---|
823 | /* Compute high word of result, as a flonum. */ |
---|
824 | b = (a / HIGH_WORD_COEFF); |
---|
825 | /* Convert that to fixed (but not to DItype!), |
---|
826 | and shift it into the high word. */ |
---|
827 | v = (USItype) b; |
---|
828 | v <<= WORD_SIZE; |
---|
829 | /* Remove high part from the XFtype, leaving the low part as flonum. */ |
---|
830 | a -= (XFtype)v; |
---|
831 | /* Convert that to fixed (but not to DItype!) and add it in. |
---|
832 | Sometimes A comes out negative. This is significant, since |
---|
833 | A has more bits than a long int does. */ |
---|
834 | if (a < 0) |
---|
835 | v -= (USItype) (- a); |
---|
836 | else |
---|
837 | v += (USItype) a; |
---|
838 | return v; |
---|
839 | } |
---|
840 | #endif |
---|
841 | |
---|
842 | #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96) |
---|
843 | DItype |
---|
844 | __fixxfdi (a) |
---|
845 | XFtype a; |
---|
846 | { |
---|
847 | if (a < 0) |
---|
848 | return - __fixunsxfdi (-a); |
---|
849 | return __fixunsxfdi (a); |
---|
850 | } |
---|
851 | #endif |
---|
852 | |
---|
853 | #ifdef L_fixunsdfdi |
---|
854 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
855 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
856 | |
---|
857 | DItype |
---|
858 | __fixunsdfdi (a) |
---|
859 | DFtype a; |
---|
860 | { |
---|
861 | DFtype b; |
---|
862 | UDItype v; |
---|
863 | |
---|
864 | if (a < 0) |
---|
865 | return 0; |
---|
866 | |
---|
867 | /* Compute high word of result, as a flonum. */ |
---|
868 | b = (a / HIGH_WORD_COEFF); |
---|
869 | /* Convert that to fixed (but not to DItype!), |
---|
870 | and shift it into the high word. */ |
---|
871 | v = (USItype) b; |
---|
872 | v <<= WORD_SIZE; |
---|
873 | /* Remove high part from the DFtype, leaving the low part as flonum. */ |
---|
874 | a -= (DFtype)v; |
---|
875 | /* Convert that to fixed (but not to DItype!) and add it in. |
---|
876 | Sometimes A comes out negative. This is significant, since |
---|
877 | A has more bits than a long int does. */ |
---|
878 | if (a < 0) |
---|
879 | v -= (USItype) (- a); |
---|
880 | else |
---|
881 | v += (USItype) a; |
---|
882 | return v; |
---|
883 | } |
---|
884 | #endif |
---|
885 | |
---|
886 | #ifdef L_fixdfdi |
---|
887 | DItype |
---|
888 | __fixdfdi (a) |
---|
889 | DFtype a; |
---|
890 | { |
---|
891 | if (a < 0) |
---|
892 | return - __fixunsdfdi (-a); |
---|
893 | return __fixunsdfdi (a); |
---|
894 | } |
---|
895 | #endif |
---|
896 | |
---|
897 | #ifdef L_fixunssfdi |
---|
898 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
899 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
900 | |
---|
901 | DItype |
---|
902 | __fixunssfdi (SFtype original_a) |
---|
903 | { |
---|
904 | /* Convert the SFtype to a DFtype, because that is surely not going |
---|
905 | to lose any bits. Some day someone else can write a faster version |
---|
906 | that avoids converting to DFtype, and verify it really works right. */ |
---|
907 | DFtype a = original_a; |
---|
908 | DFtype b; |
---|
909 | UDItype v; |
---|
910 | |
---|
911 | if (a < 0) |
---|
912 | return 0; |
---|
913 | |
---|
914 | /* Compute high word of result, as a flonum. */ |
---|
915 | b = (a / HIGH_WORD_COEFF); |
---|
916 | /* Convert that to fixed (but not to DItype!), |
---|
917 | and shift it into the high word. */ |
---|
918 | v = (USItype) b; |
---|
919 | v <<= WORD_SIZE; |
---|
920 | /* Remove high part from the DFtype, leaving the low part as flonum. */ |
---|
921 | a -= (DFtype)v; |
---|
922 | /* Convert that to fixed (but not to DItype!) and add it in. |
---|
923 | Sometimes A comes out negative. This is significant, since |
---|
924 | A has more bits than a long int does. */ |
---|
925 | if (a < 0) |
---|
926 | v -= (USItype) (- a); |
---|
927 | else |
---|
928 | v += (USItype) a; |
---|
929 | return v; |
---|
930 | } |
---|
931 | #endif |
---|
932 | |
---|
933 | #ifdef L_fixsfdi |
---|
934 | DItype |
---|
935 | __fixsfdi (SFtype a) |
---|
936 | { |
---|
937 | if (a < 0) |
---|
938 | return - __fixunssfdi (-a); |
---|
939 | return __fixunssfdi (a); |
---|
940 | } |
---|
941 | #endif |
---|
942 | |
---|
943 | #if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96) |
---|
944 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
945 | #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) |
---|
946 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
947 | |
---|
948 | XFtype |
---|
949 | __floatdixf (u) |
---|
950 | DItype u; |
---|
951 | { |
---|
952 | XFtype d; |
---|
953 | SItype negate = 0; |
---|
954 | |
---|
955 | if (u < 0) |
---|
956 | u = -u, negate = 1; |
---|
957 | |
---|
958 | d = (USItype) (u >> WORD_SIZE); |
---|
959 | d *= HIGH_HALFWORD_COEFF; |
---|
960 | d *= HIGH_HALFWORD_COEFF; |
---|
961 | d += (USItype) (u & (HIGH_WORD_COEFF - 1)); |
---|
962 | |
---|
963 | return (negate ? -d : d); |
---|
964 | } |
---|
965 | #endif |
---|
966 | |
---|
967 | #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128) |
---|
968 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
969 | #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) |
---|
970 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
971 | |
---|
972 | TFtype |
---|
973 | __floatditf (u) |
---|
974 | DItype u; |
---|
975 | { |
---|
976 | TFtype d; |
---|
977 | SItype negate = 0; |
---|
978 | |
---|
979 | if (u < 0) |
---|
980 | u = -u, negate = 1; |
---|
981 | |
---|
982 | d = (USItype) (u >> WORD_SIZE); |
---|
983 | d *= HIGH_HALFWORD_COEFF; |
---|
984 | d *= HIGH_HALFWORD_COEFF; |
---|
985 | d += (USItype) (u & (HIGH_WORD_COEFF - 1)); |
---|
986 | |
---|
987 | return (negate ? -d : d); |
---|
988 | } |
---|
989 | #endif |
---|
990 | |
---|
991 | #ifdef L_floatdidf |
---|
992 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
993 | #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) |
---|
994 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
995 | |
---|
996 | DFtype |
---|
997 | __floatdidf (u) |
---|
998 | DItype u; |
---|
999 | { |
---|
1000 | DFtype d; |
---|
1001 | SItype negate = 0; |
---|
1002 | |
---|
1003 | if (u < 0) |
---|
1004 | u = -u, negate = 1; |
---|
1005 | |
---|
1006 | d = (USItype) (u >> WORD_SIZE); |
---|
1007 | d *= HIGH_HALFWORD_COEFF; |
---|
1008 | d *= HIGH_HALFWORD_COEFF; |
---|
1009 | d += (USItype) (u & (HIGH_WORD_COEFF - 1)); |
---|
1010 | |
---|
1011 | return (negate ? -d : d); |
---|
1012 | } |
---|
1013 | #endif |
---|
1014 | |
---|
1015 | #ifdef L_floatdisf |
---|
1016 | #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) |
---|
1017 | #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) |
---|
1018 | #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) |
---|
1019 | #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT) |
---|
1020 | |
---|
1021 | /* Define codes for all the float formats that we know of. Note |
---|
1022 | that this is copied from real.h. */ |
---|
1023 | |
---|
1024 | #define UNKNOWN_FLOAT_FORMAT 0 |
---|
1025 | #define IEEE_FLOAT_FORMAT 1 |
---|
1026 | #define VAX_FLOAT_FORMAT 2 |
---|
1027 | #define IBM_FLOAT_FORMAT 3 |
---|
1028 | |
---|
1029 | /* Default to IEEE float if not specified. Nearly all machines use it. */ |
---|
1030 | #ifndef HOST_FLOAT_FORMAT |
---|
1031 | #define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT |
---|
1032 | #endif |
---|
1033 | |
---|
1034 | #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT |
---|
1035 | #define DF_SIZE 53 |
---|
1036 | #define SF_SIZE 24 |
---|
1037 | #endif |
---|
1038 | |
---|
1039 | #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT |
---|
1040 | #define DF_SIZE 56 |
---|
1041 | #define SF_SIZE 24 |
---|
1042 | #endif |
---|
1043 | |
---|
1044 | #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT |
---|
1045 | #define DF_SIZE 56 |
---|
1046 | #define SF_SIZE 24 |
---|
1047 | #endif |
---|
1048 | |
---|
1049 | SFtype |
---|
1050 | __floatdisf (u) |
---|
1051 | DItype u; |
---|
1052 | { |
---|
1053 | /* Do the calculation in DFmode |
---|
1054 | so that we don't lose any of the precision of the high word |
---|
1055 | while multiplying it. */ |
---|
1056 | DFtype f; |
---|
1057 | SItype negate = 0; |
---|
1058 | |
---|
1059 | if (u < 0) |
---|
1060 | u = -u, negate = 1; |
---|
1061 | |
---|
1062 | /* Protect against double-rounding error. |
---|
1063 | Represent any low-order bits, that might be truncated in DFmode, |
---|
1064 | by a bit that won't be lost. The bit can go in anywhere below the |
---|
1065 | rounding position of the SFmode. A fixed mask and bit position |
---|
1066 | handles all usual configurations. It doesn't handle the case |
---|
1067 | of 128-bit DImode, however. */ |
---|
1068 | if (DF_SIZE < DI_SIZE |
---|
1069 | && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) |
---|
1070 | { |
---|
1071 | #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE)) |
---|
1072 | if (u >= ((UDItype) 1 << DF_SIZE)) |
---|
1073 | { |
---|
1074 | if ((USItype) u & (REP_BIT - 1)) |
---|
1075 | u |= REP_BIT; |
---|
1076 | } |
---|
1077 | } |
---|
1078 | f = (USItype) (u >> WORD_SIZE); |
---|
1079 | f *= HIGH_HALFWORD_COEFF; |
---|
1080 | f *= HIGH_HALFWORD_COEFF; |
---|
1081 | f += (USItype) (u & (HIGH_WORD_COEFF - 1)); |
---|
1082 | |
---|
1083 | return (SFtype) (negate ? -f : f); |
---|
1084 | } |
---|
1085 | #endif |
---|
1086 | |
---|
1087 | #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96 |
---|
1088 | /* Reenable the normal types, in case limits.h needs them. */ |
---|
1089 | #undef char |
---|
1090 | #undef short |
---|
1091 | #undef int |
---|
1092 | #undef long |
---|
1093 | #undef unsigned |
---|
1094 | #undef float |
---|
1095 | #undef double |
---|
1096 | #undef MIN |
---|
1097 | #undef MAX |
---|
1098 | #include <limits.h> |
---|
1099 | |
---|
1100 | USItype |
---|
1101 | __fixunsxfsi (a) |
---|
1102 | XFtype a; |
---|
1103 | { |
---|
1104 | if (a >= - (DFtype) LONG_MIN) |
---|
1105 | return (SItype) (a + LONG_MIN) - LONG_MIN; |
---|
1106 | return (SItype) a; |
---|
1107 | } |
---|
1108 | #endif |
---|
1109 | |
---|
1110 | #ifdef L_fixunsdfsi |
---|
1111 | /* Reenable the normal types, in case limits.h needs them. */ |
---|
1112 | #undef char |
---|
1113 | #undef short |
---|
1114 | #undef int |
---|
1115 | #undef long |
---|
1116 | #undef unsigned |
---|
1117 | #undef float |
---|
1118 | #undef double |
---|
1119 | #undef MIN |
---|
1120 | #undef MAX |
---|
1121 | #include <limits.h> |
---|
1122 | |
---|
1123 | USItype |
---|
1124 | __fixunsdfsi (a) |
---|
1125 | DFtype a; |
---|
1126 | { |
---|
1127 | if (a >= - (DFtype) LONG_MIN) |
---|
1128 | return (SItype) (a + LONG_MIN) - LONG_MIN; |
---|
1129 | return (SItype) a; |
---|
1130 | } |
---|
1131 | #endif |
---|
1132 | |
---|
1133 | #ifdef L_fixunssfsi |
---|
1134 | /* Reenable the normal types, in case limits.h needs them. */ |
---|
1135 | #undef char |
---|
1136 | #undef short |
---|
1137 | #undef int |
---|
1138 | #undef long |
---|
1139 | #undef unsigned |
---|
1140 | #undef float |
---|
1141 | #undef double |
---|
1142 | #undef MIN |
---|
1143 | #undef MAX |
---|
1144 | #include <limits.h> |
---|
1145 | |
---|
1146 | USItype |
---|
1147 | __fixunssfsi (SFtype a) |
---|
1148 | { |
---|
1149 | if (a >= - (SFtype) LONG_MIN) |
---|
1150 | return (SItype) (a + LONG_MIN) - LONG_MIN; |
---|
1151 | return (SItype) a; |
---|
1152 | } |
---|
1153 | #endif |
---|
1154 | |
---|
1155 | /* From here on down, the routines use normal data types. */ |
---|
1156 | |
---|
1157 | #define SItype bogus_type |
---|
1158 | #define USItype bogus_type |
---|
1159 | #define DItype bogus_type |
---|
1160 | #define UDItype bogus_type |
---|
1161 | #define SFtype bogus_type |
---|
1162 | #define DFtype bogus_type |
---|
1163 | |
---|
1164 | #undef char |
---|
1165 | #undef short |
---|
1166 | #undef int |
---|
1167 | #undef long |
---|
1168 | #undef unsigned |
---|
1169 | #undef float |
---|
1170 | #undef double |
---|
1171 | |
---|
1172 | #ifdef L__gcc_bcmp |
---|
1173 | |
---|
1174 | /* Like bcmp except the sign is meaningful. |
---|
1175 | Result is negative if S1 is less than S2, |
---|
1176 | positive if S1 is greater, 0 if S1 and S2 are equal. */ |
---|
1177 | |
---|
1178 | int |
---|
1179 | __gcc_bcmp (s1, s2, size) |
---|
1180 | unsigned char *s1, *s2; |
---|
1181 | size_t size; |
---|
1182 | { |
---|
1183 | while (size > 0) |
---|
1184 | { |
---|
1185 | unsigned char c1 = *s1++, c2 = *s2++; |
---|
1186 | if (c1 != c2) |
---|
1187 | return c1 - c2; |
---|
1188 | size--; |
---|
1189 | } |
---|
1190 | return 0; |
---|
1191 | } |
---|
1192 | |
---|
1193 | #endif |
---|
1194 | |
---|
1195 | #ifdef L_varargs |
---|
1196 | #ifdef __i860__ |
---|
1197 | #if defined(__svr4__) || defined(__alliant__) |
---|
1198 | asm (" .text"); |
---|
1199 | asm (" .align 4"); |
---|
1200 | |
---|
1201 | /* The Alliant needs the added underscore. */ |
---|
1202 | asm (".globl __builtin_saveregs"); |
---|
1203 | asm ("__builtin_saveregs:"); |
---|
1204 | asm (".globl ___builtin_saveregs"); |
---|
1205 | asm ("___builtin_saveregs:"); |
---|
1206 | |
---|
1207 | asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */ |
---|
1208 | asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save |
---|
1209 | area and also for a new va_list |
---|
1210 | structure */ |
---|
1211 | /* Save all argument registers in the arg reg save area. The |
---|
1212 | arg reg save area must have the following layout (according |
---|
1213 | to the svr4 ABI): |
---|
1214 | |
---|
1215 | struct { |
---|
1216 | union { |
---|
1217 | float freg[8]; |
---|
1218 | double dreg[4]; |
---|
1219 | } float_regs; |
---|
1220 | long ireg[12]; |
---|
1221 | }; |
---|
1222 | */ |
---|
1223 | |
---|
1224 | asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */ |
---|
1225 | asm (" fst.q %f12,16(%sp)"); |
---|
1226 | |
---|
1227 | asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */ |
---|
1228 | asm (" st.l %r17,36(%sp)"); |
---|
1229 | asm (" st.l %r18,40(%sp)"); |
---|
1230 | asm (" st.l %r19,44(%sp)"); |
---|
1231 | asm (" st.l %r20,48(%sp)"); |
---|
1232 | asm (" st.l %r21,52(%sp)"); |
---|
1233 | asm (" st.l %r22,56(%sp)"); |
---|
1234 | asm (" st.l %r23,60(%sp)"); |
---|
1235 | asm (" st.l %r24,64(%sp)"); |
---|
1236 | asm (" st.l %r25,68(%sp)"); |
---|
1237 | asm (" st.l %r26,72(%sp)"); |
---|
1238 | asm (" st.l %r27,76(%sp)"); |
---|
1239 | |
---|
1240 | asm (" adds 80,%sp,%r16"); /* compute the address of the new |
---|
1241 | va_list structure. Put in into |
---|
1242 | r16 so that it will be returned |
---|
1243 | to the caller. */ |
---|
1244 | |
---|
1245 | /* Initialize all fields of the new va_list structure. This |
---|
1246 | structure looks like: |
---|
1247 | |
---|
1248 | typedef struct { |
---|
1249 | unsigned long ireg_used; |
---|
1250 | unsigned long freg_used; |
---|
1251 | long *reg_base; |
---|
1252 | long *mem_ptr; |
---|
1253 | } va_list; |
---|
1254 | */ |
---|
1255 | |
---|
1256 | asm (" st.l %r0, 0(%r16)"); /* nfixed */ |
---|
1257 | asm (" st.l %r0, 4(%r16)"); /* nfloating */ |
---|
1258 | asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */ |
---|
1259 | asm (" bri %r1"); /* delayed return */ |
---|
1260 | asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */ |
---|
1261 | |
---|
1262 | #else /* not __svr4__ */ |
---|
1263 | #if defined(__PARAGON__) |
---|
1264 | /* |
---|
1265 | * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax, |
---|
1266 | * and we stand a better chance of hooking into libraries |
---|
1267 | * compiled by PGI. [andyp@ssd.intel.com] |
---|
1268 | */ |
---|
1269 | asm (" .text"); |
---|
1270 | asm (" .align 4"); |
---|
1271 | asm (".globl __builtin_saveregs"); |
---|
1272 | asm ("__builtin_saveregs:"); |
---|
1273 | asm (".globl ___builtin_saveregs"); |
---|
1274 | asm ("___builtin_saveregs:"); |
---|
1275 | |
---|
1276 | asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */ |
---|
1277 | asm (" adds -96,sp,sp"); /* allocate stack space for reg save |
---|
1278 | area and also for a new va_list |
---|
1279 | structure */ |
---|
1280 | /* Save all argument registers in the arg reg save area. The |
---|
1281 | arg reg save area must have the following layout (according |
---|
1282 | to the svr4 ABI): |
---|
1283 | |
---|
1284 | struct { |
---|
1285 | union { |
---|
1286 | float freg[8]; |
---|
1287 | double dreg[4]; |
---|
1288 | } float_regs; |
---|
1289 | long ireg[12]; |
---|
1290 | }; |
---|
1291 | */ |
---|
1292 | |
---|
1293 | asm (" fst.q f8, 0(sp)"); |
---|
1294 | asm (" fst.q f12,16(sp)"); |
---|
1295 | asm (" st.l r16,32(sp)"); |
---|
1296 | asm (" st.l r17,36(sp)"); |
---|
1297 | asm (" st.l r18,40(sp)"); |
---|
1298 | asm (" st.l r19,44(sp)"); |
---|
1299 | asm (" st.l r20,48(sp)"); |
---|
1300 | asm (" st.l r21,52(sp)"); |
---|
1301 | asm (" st.l r22,56(sp)"); |
---|
1302 | asm (" st.l r23,60(sp)"); |
---|
1303 | asm (" st.l r24,64(sp)"); |
---|
1304 | asm (" st.l r25,68(sp)"); |
---|
1305 | asm (" st.l r26,72(sp)"); |
---|
1306 | asm (" st.l r27,76(sp)"); |
---|
1307 | |
---|
1308 | asm (" adds 80,sp,r16"); /* compute the address of the new |
---|
1309 | va_list structure. Put in into |
---|
1310 | r16 so that it will be returned |
---|
1311 | to the caller. */ |
---|
1312 | |
---|
1313 | /* Initialize all fields of the new va_list structure. This |
---|
1314 | structure looks like: |
---|
1315 | |
---|
1316 | typedef struct { |
---|
1317 | unsigned long ireg_used; |
---|
1318 | unsigned long freg_used; |
---|
1319 | long *reg_base; |
---|
1320 | long *mem_ptr; |
---|
1321 | } va_list; |
---|
1322 | */ |
---|
1323 | |
---|
1324 | asm (" st.l r0, 0(r16)"); /* nfixed */ |
---|
1325 | asm (" st.l r0, 4(r16)"); /* nfloating */ |
---|
1326 | asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */ |
---|
1327 | asm (" bri r1"); /* delayed return */ |
---|
1328 | asm (" st.l r28,12(r16)"); /* pointer to overflow args */ |
---|
1329 | #else /* not __PARAGON__ */ |
---|
1330 | asm (" .text"); |
---|
1331 | asm (" .align 4"); |
---|
1332 | |
---|
1333 | asm (".globl ___builtin_saveregs"); |
---|
1334 | asm ("___builtin_saveregs:"); |
---|
1335 | asm (" mov sp,r30"); |
---|
1336 | asm (" andnot 0x0f,sp,sp"); |
---|
1337 | asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */ |
---|
1338 | |
---|
1339 | /* Fill in the __va_struct. */ |
---|
1340 | asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */ |
---|
1341 | asm (" st.l r17, 4(sp)"); /* int fixed[12] */ |
---|
1342 | asm (" st.l r18, 8(sp)"); |
---|
1343 | asm (" st.l r19,12(sp)"); |
---|
1344 | asm (" st.l r20,16(sp)"); |
---|
1345 | asm (" st.l r21,20(sp)"); |
---|
1346 | asm (" st.l r22,24(sp)"); |
---|
1347 | asm (" st.l r23,28(sp)"); |
---|
1348 | asm (" st.l r24,32(sp)"); |
---|
1349 | asm (" st.l r25,36(sp)"); |
---|
1350 | asm (" st.l r26,40(sp)"); |
---|
1351 | asm (" st.l r27,44(sp)"); |
---|
1352 | |
---|
1353 | asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */ |
---|
1354 | asm (" fst.q f12,64(sp)"); /* int floating[8] */ |
---|
1355 | |
---|
1356 | /* Fill in the __va_ctl. */ |
---|
1357 | asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */ |
---|
1358 | asm (" st.l r28,84(sp)"); /* pointer to more args */ |
---|
1359 | asm (" st.l r0, 88(sp)"); /* nfixed */ |
---|
1360 | asm (" st.l r0, 92(sp)"); /* nfloating */ |
---|
1361 | |
---|
1362 | asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */ |
---|
1363 | asm (" bri r1"); |
---|
1364 | asm (" mov r30,sp"); |
---|
1365 | /* recover stack and pass address to start |
---|
1366 | of data. */ |
---|
1367 | #endif /* not __PARAGON__ */ |
---|
1368 | #endif /* not __svr4__ */ |
---|
1369 | #else /* not __i860__ */ |
---|
1370 | #ifdef __sparc__ |
---|
1371 | asm (".global __builtin_saveregs"); |
---|
1372 | asm ("__builtin_saveregs:"); |
---|
1373 | asm (".global ___builtin_saveregs"); |
---|
1374 | asm ("___builtin_saveregs:"); |
---|
1375 | #ifdef NEED_PROC_COMMAND |
---|
1376 | asm (".proc 020"); |
---|
1377 | #endif |
---|
1378 | asm ("st %i0,[%fp+68]"); |
---|
1379 | asm ("st %i1,[%fp+72]"); |
---|
1380 | asm ("st %i2,[%fp+76]"); |
---|
1381 | asm ("st %i3,[%fp+80]"); |
---|
1382 | asm ("st %i4,[%fp+84]"); |
---|
1383 | asm ("retl"); |
---|
1384 | asm ("st %i5,[%fp+88]"); |
---|
1385 | #ifdef NEED_TYPE_COMMAND |
---|
1386 | asm (".type __builtin_saveregs,#function"); |
---|
1387 | asm (".size __builtin_saveregs,.-__builtin_saveregs"); |
---|
1388 | #endif |
---|
1389 | #else /* not __sparc__ */ |
---|
1390 | #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__) |
---|
1391 | |
---|
1392 | asm (" .text"); |
---|
1393 | asm (" .ent __builtin_saveregs"); |
---|
1394 | asm (" .globl __builtin_saveregs"); |
---|
1395 | asm ("__builtin_saveregs:"); |
---|
1396 | asm (" sw $4,0($30)"); |
---|
1397 | asm (" sw $5,4($30)"); |
---|
1398 | asm (" sw $6,8($30)"); |
---|
1399 | asm (" sw $7,12($30)"); |
---|
1400 | asm (" j $31"); |
---|
1401 | asm (" .end __builtin_saveregs"); |
---|
1402 | #else /* not __mips__, etc. */ |
---|
1403 | |
---|
1404 | void * |
---|
1405 | __builtin_saveregs () |
---|
1406 | { |
---|
1407 | abort (); |
---|
1408 | } |
---|
1409 | |
---|
1410 | #endif /* not __mips__ */ |
---|
1411 | #endif /* not __sparc__ */ |
---|
1412 | #endif /* not __i860__ */ |
---|
1413 | #endif |
---|
1414 | |
---|
1415 | #ifdef L_eprintf |
---|
1416 | #ifndef inhibit_libc |
---|
1417 | |
---|
1418 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
---|
1419 | #include <stdio.h> |
---|
1420 | /* This is used by the `assert' macro. */ |
---|
1421 | void |
---|
1422 | __eprintf (string, expression, line, filename) |
---|
1423 | const char *string; |
---|
1424 | const char *expression; |
---|
1425 | int line; |
---|
1426 | const char *filename; |
---|
1427 | { |
---|
1428 | fprintf (stderr, string, expression, line, filename); |
---|
1429 | fflush (stderr); |
---|
1430 | abort (); |
---|
1431 | } |
---|
1432 | |
---|
1433 | #endif |
---|
1434 | #endif |
---|
1435 | |
---|
1436 | #ifdef L_bb |
---|
1437 | |
---|
1438 | /* Structure emitted by -a */ |
---|
1439 | struct bb |
---|
1440 | { |
---|
1441 | long zero_word; |
---|
1442 | const char *filename; |
---|
1443 | long *counts; |
---|
1444 | long ncounts; |
---|
1445 | struct bb *next; |
---|
1446 | const unsigned long *addresses; |
---|
1447 | |
---|
1448 | /* Older GCC's did not emit these fields. */ |
---|
1449 | long nwords; |
---|
1450 | const char **functions; |
---|
1451 | const long *line_nums; |
---|
1452 | const char **filenames; |
---|
1453 | }; |
---|
1454 | |
---|
1455 | #ifdef BLOCK_PROFILER_CODE |
---|
1456 | BLOCK_PROFILER_CODE |
---|
1457 | #else |
---|
1458 | #ifndef inhibit_libc |
---|
1459 | |
---|
1460 | /* Simple minded basic block profiling output dumper for |
---|
1461 | systems that don't provide tcov support. At present, |
---|
1462 | it requires atexit and stdio. */ |
---|
1463 | |
---|
1464 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
---|
1465 | #include <stdio.h> |
---|
1466 | char *ctime (); |
---|
1467 | |
---|
1468 | #ifdef HAVE_ATEXIT |
---|
1469 | #ifdef WINNT |
---|
1470 | extern int atexit (void (*) (void)); |
---|
1471 | #else |
---|
1472 | extern void atexit (void (*) (void)); |
---|
1473 | #endif |
---|
1474 | #define ON_EXIT(FUNC,ARG) atexit ((FUNC)) |
---|
1475 | #else |
---|
1476 | #ifdef sun |
---|
1477 | extern void on_exit (void*, void*); |
---|
1478 | #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG)) |
---|
1479 | #endif |
---|
1480 | #endif |
---|
1481 | |
---|
1482 | static struct bb *bb_head; |
---|
1483 | |
---|
1484 | /* Return the number of digits needed to print a value */ |
---|
1485 | /* __inline__ */ static int num_digits (long value, int base) |
---|
1486 | { |
---|
1487 | int minus = (value < 0 && base != 16); |
---|
1488 | unsigned long v = (minus) ? -value : value; |
---|
1489 | int ret = minus; |
---|
1490 | |
---|
1491 | do |
---|
1492 | { |
---|
1493 | v /= base; |
---|
1494 | ret++; |
---|
1495 | } |
---|
1496 | while (v); |
---|
1497 | |
---|
1498 | return ret; |
---|
1499 | } |
---|
1500 | |
---|
1501 | void |
---|
1502 | __bb_exit_func (void) |
---|
1503 | { |
---|
1504 | FILE *file = fopen ("bb.out", "a"); |
---|
1505 | long time_value; |
---|
1506 | |
---|
1507 | if (!file) |
---|
1508 | perror ("bb.out"); |
---|
1509 | |
---|
1510 | else |
---|
1511 | { |
---|
1512 | struct bb *ptr; |
---|
1513 | |
---|
1514 | /* This is somewhat type incorrect, but it avoids worrying about |
---|
1515 | exactly where time.h is included from. It should be ok unless |
---|
1516 | a void * differs from other pointer formats, or if sizeof(long) |
---|
1517 | is < sizeof (time_t). It would be nice if we could assume the |
---|
1518 | use of rationale standards here. */ |
---|
1519 | |
---|
1520 | time((void *) &time_value); |
---|
1521 | fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value)); |
---|
1522 | |
---|
1523 | /* We check the length field explicitly in order to allow compatibility |
---|
1524 | with older GCC's which did not provide it. */ |
---|
1525 | |
---|
1526 | for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next) |
---|
1527 | { |
---|
1528 | int i; |
---|
1529 | int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000); |
---|
1530 | int line_p = (func_p && ptr->line_nums); |
---|
1531 | int file_p = (func_p && ptr->filenames); |
---|
1532 | long ncounts = ptr->ncounts; |
---|
1533 | long cnt_max = 0; |
---|
1534 | long line_max = 0; |
---|
1535 | long addr_max = 0; |
---|
1536 | int file_len = 0; |
---|
1537 | int func_len = 0; |
---|
1538 | int blk_len = num_digits (ncounts, 10); |
---|
1539 | int cnt_len; |
---|
1540 | int line_len; |
---|
1541 | int addr_len; |
---|
1542 | |
---|
1543 | fprintf (file, "File %s, %ld basic blocks \n\n", |
---|
1544 | ptr->filename, ncounts); |
---|
1545 | |
---|
1546 | /* Get max values for each field. */ |
---|
1547 | for (i = 0; i < ncounts; i++) |
---|
1548 | { |
---|
1549 | const char *p; |
---|
1550 | int len; |
---|
1551 | |
---|
1552 | if (cnt_max < ptr->counts[i]) |
---|
1553 | cnt_max = ptr->counts[i]; |
---|
1554 | |
---|
1555 | if (addr_max < ptr->addresses[i]) |
---|
1556 | addr_max = ptr->addresses[i]; |
---|
1557 | |
---|
1558 | if (line_p && line_max < ptr->line_nums[i]) |
---|
1559 | line_max = ptr->line_nums[i]; |
---|
1560 | |
---|
1561 | if (func_p) |
---|
1562 | { |
---|
1563 | p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>"; |
---|
1564 | len = strlen (p); |
---|
1565 | if (func_len < len) |
---|
1566 | func_len = len; |
---|
1567 | } |
---|
1568 | |
---|
1569 | if (file_p) |
---|
1570 | { |
---|
1571 | p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>"; |
---|
1572 | len = strlen (p); |
---|
1573 | if (file_len < len) |
---|
1574 | file_len = len; |
---|
1575 | } |
---|
1576 | } |
---|
1577 | |
---|
1578 | addr_len = num_digits (addr_max, 16); |
---|
1579 | cnt_len = num_digits (cnt_max, 10); |
---|
1580 | line_len = num_digits (line_max, 10); |
---|
1581 | |
---|
1582 | /* Now print out the basic block information. */ |
---|
1583 | for (i = 0; i < ncounts; i++) |
---|
1584 | { |
---|
1585 | fprintf (file, |
---|
1586 | " Block #%*d: executed %*ld time(s) address= 0x%.*lx", |
---|
1587 | blk_len, i+1, |
---|
1588 | cnt_len, ptr->counts[i], |
---|
1589 | addr_len, ptr->addresses[i]); |
---|
1590 | |
---|
1591 | if (func_p) |
---|
1592 | fprintf (file, " function= %-*s", func_len, |
---|
1593 | (ptr->functions[i]) ? ptr->functions[i] : "<none>"); |
---|
1594 | |
---|
1595 | if (line_p) |
---|
1596 | fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]); |
---|
1597 | |
---|
1598 | if (file_p) |
---|
1599 | fprintf (file, " file= %s", |
---|
1600 | (ptr->filenames[i]) ? ptr->filenames[i] : "<none>"); |
---|
1601 | |
---|
1602 | fprintf (file, "\n"); |
---|
1603 | } |
---|
1604 | |
---|
1605 | fprintf (file, "\n"); |
---|
1606 | fflush (file); |
---|
1607 | } |
---|
1608 | |
---|
1609 | fprintf (file, "\n\n"); |
---|
1610 | fclose (file); |
---|
1611 | } |
---|
1612 | } |
---|
1613 | |
---|
1614 | void |
---|
1615 | __bb_init_func (struct bb *blocks) |
---|
1616 | { |
---|
1617 | /* User is supposed to check whether the first word is non-0, |
---|
1618 | but just in case.... */ |
---|
1619 | |
---|
1620 | if (blocks->zero_word) |
---|
1621 | return; |
---|
1622 | |
---|
1623 | #ifdef ON_EXIT |
---|
1624 | /* Initialize destructor. */ |
---|
1625 | if (!bb_head) |
---|
1626 | ON_EXIT (__bb_exit_func, 0); |
---|
1627 | #endif |
---|
1628 | |
---|
1629 | /* Set up linked list. */ |
---|
1630 | blocks->zero_word = 1; |
---|
1631 | blocks->next = bb_head; |
---|
1632 | bb_head = blocks; |
---|
1633 | } |
---|
1634 | |
---|
1635 | #endif /* not inhibit_libc */ |
---|
1636 | #endif /* not BLOCK_PROFILER_CODE */ |
---|
1637 | #endif /* L_bb */ |
---|
1638 | |
---|
1639 | /* Default free-store management functions for C++, per sections 12.5 and |
---|
1640 | 17.3.3 of the Working Paper. */ |
---|
1641 | |
---|
1642 | #ifdef L_op_new |
---|
1643 | /* operator new (size_t), described in 17.3.3.5. This function is used by |
---|
1644 | C++ programs to allocate a block of memory to hold a single object. */ |
---|
1645 | |
---|
1646 | typedef void (*vfp)(void); |
---|
1647 | extern vfp __new_handler; |
---|
1648 | extern void __default_new_handler (void); |
---|
1649 | |
---|
1650 | #ifdef WEAK_ALIAS |
---|
1651 | void * __builtin_new (size_t sz) |
---|
1652 | __attribute__ ((weak, alias ("___builtin_new"))); |
---|
1653 | void * |
---|
1654 | ___builtin_new (size_t sz) |
---|
1655 | #else |
---|
1656 | void * |
---|
1657 | __builtin_new (size_t sz) |
---|
1658 | #endif |
---|
1659 | { |
---|
1660 | void *p; |
---|
1661 | vfp handler = (__new_handler) ? __new_handler : __default_new_handler; |
---|
1662 | |
---|
1663 | /* malloc (0) is unpredictable; avoid it. */ |
---|
1664 | if (sz == 0) |
---|
1665 | sz = 1; |
---|
1666 | p = (void *) malloc (sz); |
---|
1667 | while (p == 0) |
---|
1668 | { |
---|
1669 | (*handler) (); |
---|
1670 | p = (void *) malloc (sz); |
---|
1671 | } |
---|
1672 | |
---|
1673 | return p; |
---|
1674 | } |
---|
1675 | #endif /* L_op_new */ |
---|
1676 | |
---|
1677 | #ifdef L_op_vnew |
---|
1678 | /* void * operator new [] (size_t), described in 17.3.3.6. This function |
---|
1679 | is used by C++ programs to allocate a block of memory for an array. */ |
---|
1680 | |
---|
1681 | extern void * __builtin_new (size_t); |
---|
1682 | |
---|
1683 | #ifdef WEAK_ALIAS |
---|
1684 | void * __builtin_vec_new (size_t sz) |
---|
1685 | __attribute__ ((weak, alias ("___builtin_vec_new"))); |
---|
1686 | void * |
---|
1687 | ___builtin_vec_new (size_t sz) |
---|
1688 | #else |
---|
1689 | void * |
---|
1690 | __builtin_vec_new (size_t sz) |
---|
1691 | #endif |
---|
1692 | { |
---|
1693 | return __builtin_new (sz); |
---|
1694 | } |
---|
1695 | #endif /* L_op_vnew */ |
---|
1696 | |
---|
1697 | #ifdef L_new_handler |
---|
1698 | /* set_new_handler (fvoid_t *) and the default new handler, described in |
---|
1699 | 17.3.3.2 and 17.3.3.5. These functions define the result of a failure |
---|
1700 | to allocate the amount of memory requested from operator new or new []. */ |
---|
1701 | |
---|
1702 | #ifndef inhibit_libc |
---|
1703 | /* This gets us __GNU_LIBRARY__. */ |
---|
1704 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
---|
1705 | #include <stdio.h> |
---|
1706 | |
---|
1707 | #ifdef __GNU_LIBRARY__ |
---|
1708 | /* Avoid forcing the library's meaning of `write' on the user program |
---|
1709 | by using the "internal" name (for use within the library) */ |
---|
1710 | #define write(fd, buf, n) __write((fd), (buf), (n)) |
---|
1711 | #endif |
---|
1712 | #endif /* inhibit_libc */ |
---|
1713 | |
---|
1714 | typedef void (*vfp)(void); |
---|
1715 | void __default_new_handler (void); |
---|
1716 | |
---|
1717 | vfp __new_handler = (vfp)0; |
---|
1718 | |
---|
1719 | vfp |
---|
1720 | set_new_handler (vfp handler) |
---|
1721 | { |
---|
1722 | vfp prev_handler; |
---|
1723 | |
---|
1724 | prev_handler = __new_handler; |
---|
1725 | if (handler == 0) handler = __default_new_handler; |
---|
1726 | __new_handler = handler; |
---|
1727 | return prev_handler; |
---|
1728 | } |
---|
1729 | |
---|
1730 | #define MESSAGE "Virtual memory exceeded in `new'\n" |
---|
1731 | |
---|
1732 | void |
---|
1733 | __default_new_handler () |
---|
1734 | { |
---|
1735 | #ifndef inhibit_libc |
---|
1736 | /* don't use fprintf (stderr, ...) because it may need to call malloc. */ |
---|
1737 | /* This should really print the name of the program, but that is hard to |
---|
1738 | do. We need a standard, clean way to get at the name. */ |
---|
1739 | write (2, MESSAGE, sizeof (MESSAGE)); |
---|
1740 | #endif |
---|
1741 | /* don't call exit () because that may call global destructors which |
---|
1742 | may cause a loop. */ |
---|
1743 | _exit (-1); |
---|
1744 | } |
---|
1745 | #endif |
---|
1746 | |
---|
1747 | #ifdef L_op_delete |
---|
1748 | /* operator delete (void *), described in 17.3.3.3. This function is used |
---|
1749 | by C++ programs to return to the free store a block of memory allocated |
---|
1750 | as a single object. */ |
---|
1751 | |
---|
1752 | #ifdef WEAK_ALIAS |
---|
1753 | void __builtin_delete (void *ptr) |
---|
1754 | __attribute__ ((weak, alias ("___builtin_delete"))); |
---|
1755 | void |
---|
1756 | ___builtin_delete (void *ptr) |
---|
1757 | #else |
---|
1758 | void |
---|
1759 | __builtin_delete (void *ptr) |
---|
1760 | #endif |
---|
1761 | { |
---|
1762 | if (ptr) |
---|
1763 | free (ptr); |
---|
1764 | } |
---|
1765 | #endif |
---|
1766 | |
---|
1767 | #ifdef L_op_vdel |
---|
1768 | /* operator delete [] (void *), described in 17.3.3.4. This function is |
---|
1769 | used by C++ programs to return to the free store a block of memory |
---|
1770 | allocated as an array. */ |
---|
1771 | |
---|
1772 | extern void __builtin_delete (void *); |
---|
1773 | |
---|
1774 | #ifdef WEAK_ALIAS |
---|
1775 | void __builtin_vec_delete (void *ptr) |
---|
1776 | __attribute__ ((weak, alias ("___builtin_vec_delete"))); |
---|
1777 | void |
---|
1778 | ___builtin_vec_delete (void *ptr) |
---|
1779 | #else |
---|
1780 | void |
---|
1781 | __builtin_vec_delete (void *ptr) |
---|
1782 | #endif |
---|
1783 | { |
---|
1784 | __builtin_delete (ptr); |
---|
1785 | } |
---|
1786 | #endif |
---|
1787 | |
---|
1788 | /* End of C++ free-store management functions */ |
---|
1789 | |
---|
1790 | #ifdef L_shtab |
---|
1791 | unsigned int __shtab[] = { |
---|
1792 | 0x00000001, 0x00000002, 0x00000004, 0x00000008, |
---|
1793 | 0x00000010, 0x00000020, 0x00000040, 0x00000080, |
---|
1794 | 0x00000100, 0x00000200, 0x00000400, 0x00000800, |
---|
1795 | 0x00001000, 0x00002000, 0x00004000, 0x00008000, |
---|
1796 | 0x00010000, 0x00020000, 0x00040000, 0x00080000, |
---|
1797 | 0x00100000, 0x00200000, 0x00400000, 0x00800000, |
---|
1798 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, |
---|
1799 | 0x10000000, 0x20000000, 0x40000000, 0x80000000 |
---|
1800 | }; |
---|
1801 | #endif |
---|
1802 | |
---|
1803 | #ifdef L_clear_cache |
---|
1804 | /* Clear part of an instruction cache. */ |
---|
1805 | |
---|
1806 | #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH) |
---|
1807 | |
---|
1808 | void |
---|
1809 | __clear_cache (beg, end) |
---|
1810 | char *beg, *end; |
---|
1811 | { |
---|
1812 | #ifdef CLEAR_INSN_CACHE |
---|
1813 | CLEAR_INSN_CACHE (beg, end); |
---|
1814 | #else |
---|
1815 | #ifdef INSN_CACHE_SIZE |
---|
1816 | static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH]; |
---|
1817 | static int initialized; |
---|
1818 | int offset; |
---|
1819 | void *start_addr |
---|
1820 | void *end_addr; |
---|
1821 | typedef (*function_ptr) (); |
---|
1822 | |
---|
1823 | #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16 |
---|
1824 | /* It's cheaper to clear the whole cache. |
---|
1825 | Put in a series of jump instructions so that calling the beginning |
---|
1826 | of the cache will clear the whole thing. */ |
---|
1827 | |
---|
1828 | if (! initialized) |
---|
1829 | { |
---|
1830 | int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) |
---|
1831 | & -INSN_CACHE_LINE_WIDTH); |
---|
1832 | int end_ptr = ptr + INSN_CACHE_SIZE; |
---|
1833 | |
---|
1834 | while (ptr < end_ptr) |
---|
1835 | { |
---|
1836 | *(INSTRUCTION_TYPE *)ptr |
---|
1837 | = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH; |
---|
1838 | ptr += INSN_CACHE_LINE_WIDTH; |
---|
1839 | } |
---|
1840 | *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION; |
---|
1841 | |
---|
1842 | initialized = 1; |
---|
1843 | } |
---|
1844 | |
---|
1845 | /* Call the beginning of the sequence. */ |
---|
1846 | (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1) |
---|
1847 | & -INSN_CACHE_LINE_WIDTH)) |
---|
1848 | ()); |
---|
1849 | |
---|
1850 | #else /* Cache is large. */ |
---|
1851 | |
---|
1852 | if (! initialized) |
---|
1853 | { |
---|
1854 | int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) |
---|
1855 | & -INSN_CACHE_LINE_WIDTH); |
---|
1856 | |
---|
1857 | while (ptr < (int) array + sizeof array) |
---|
1858 | { |
---|
1859 | *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION; |
---|
1860 | ptr += INSN_CACHE_LINE_WIDTH; |
---|
1861 | } |
---|
1862 | |
---|
1863 | initialized = 1; |
---|
1864 | } |
---|
1865 | |
---|
1866 | /* Find the location in array that occupies the same cache line as BEG. */ |
---|
1867 | |
---|
1868 | offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1); |
---|
1869 | start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1) |
---|
1870 | & -INSN_CACHE_PLANE_SIZE) |
---|
1871 | + offset); |
---|
1872 | |
---|
1873 | /* Compute the cache alignment of the place to stop clearing. */ |
---|
1874 | #if 0 /* This is not needed for gcc's purposes. */ |
---|
1875 | /* If the block to clear is bigger than a cache plane, |
---|
1876 | we clear the entire cache, and OFFSET is already correct. */ |
---|
1877 | if (end < beg + INSN_CACHE_PLANE_SIZE) |
---|
1878 | #endif |
---|
1879 | offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1) |
---|
1880 | & -INSN_CACHE_LINE_WIDTH) |
---|
1881 | & (INSN_CACHE_PLANE_SIZE - 1)); |
---|
1882 | |
---|
1883 | #if INSN_CACHE_DEPTH > 1 |
---|
1884 | end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset; |
---|
1885 | if (end_addr <= start_addr) |
---|
1886 | end_addr += INSN_CACHE_PLANE_SIZE; |
---|
1887 | |
---|
1888 | for (plane = 0; plane < INSN_CACHE_DEPTH; plane++) |
---|
1889 | { |
---|
1890 | int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE; |
---|
1891 | int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE; |
---|
1892 | |
---|
1893 | while (addr != stop) |
---|
1894 | { |
---|
1895 | /* Call the return instruction at ADDR. */ |
---|
1896 | ((function_ptr) addr) (); |
---|
1897 | |
---|
1898 | addr += INSN_CACHE_LINE_WIDTH; |
---|
1899 | } |
---|
1900 | } |
---|
1901 | #else /* just one plane */ |
---|
1902 | do |
---|
1903 | { |
---|
1904 | /* Call the return instruction at START_ADDR. */ |
---|
1905 | ((function_ptr) start_addr) (); |
---|
1906 | |
---|
1907 | start_addr += INSN_CACHE_LINE_WIDTH; |
---|
1908 | } |
---|
1909 | while ((start_addr % INSN_CACHE_SIZE) != offset); |
---|
1910 | #endif /* just one plane */ |
---|
1911 | #endif /* Cache is large */ |
---|
1912 | #endif /* Cache exists */ |
---|
1913 | #endif /* CLEAR_INSN_CACHE */ |
---|
1914 | } |
---|
1915 | |
---|
1916 | #endif /* L_clear_cache */ |
---|
1917 | |
---|
1918 | #ifdef L_trampoline |
---|
1919 | |
---|
1920 | /* Jump to a trampoline, loading the static chain address. */ |
---|
1921 | |
---|
1922 | #ifdef WINNT |
---|
1923 | |
---|
1924 | long getpagesize() |
---|
1925 | { |
---|
1926 | #ifdef _ALPHA_ |
---|
1927 | return 8192; |
---|
1928 | #else |
---|
1929 | return 4096; |
---|
1930 | #endif |
---|
1931 | } |
---|
1932 | |
---|
1933 | int mprotect(addr, len, prot) |
---|
1934 | char *addr; |
---|
1935 | int len, prot; |
---|
1936 | { |
---|
1937 | int np, op; |
---|
1938 | |
---|
1939 | if (prot == 7) np = 0x40; |
---|
1940 | else if (prot == 5) np = 0x20; |
---|
1941 | else if (prot == 4) np = 0x10; |
---|
1942 | else if (prot == 3) np = 0x04; |
---|
1943 | else if (prot == 1) np = 0x02; |
---|
1944 | else if (prot == 0) np = 0x01; |
---|
1945 | |
---|
1946 | if (VirtualProtect (addr, len, np, &op)) |
---|
1947 | return 0; |
---|
1948 | else |
---|
1949 | return -1; |
---|
1950 | |
---|
1951 | } |
---|
1952 | |
---|
1953 | #endif |
---|
1954 | |
---|
1955 | #ifdef TRANSFER_FROM_TRAMPOLINE |
---|
1956 | TRANSFER_FROM_TRAMPOLINE |
---|
1957 | #endif |
---|
1958 | |
---|
1959 | #if defined (NeXT) && defined (__MACH__) |
---|
1960 | |
---|
1961 | /* Make stack executable so we can call trampolines on stack. |
---|
1962 | This is called from INITIALIZE_TRAMPOLINE in next.h. */ |
---|
1963 | #ifdef NeXTStep21 |
---|
1964 | #include <mach.h> |
---|
1965 | #else |
---|
1966 | #include <mach/mach.h> |
---|
1967 | #endif |
---|
1968 | |
---|
1969 | void |
---|
1970 | __enable_execute_stack (addr) |
---|
1971 | char *addr; |
---|
1972 | { |
---|
1973 | kern_return_t r; |
---|
1974 | char *eaddr = addr + TRAMPOLINE_SIZE; |
---|
1975 | vm_address_t a = (vm_address_t) addr; |
---|
1976 | |
---|
1977 | /* turn on execute access on stack */ |
---|
1978 | r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL); |
---|
1979 | if (r != KERN_SUCCESS) |
---|
1980 | { |
---|
1981 | mach_error("vm_protect VM_PROT_ALL", r); |
---|
1982 | exit(1); |
---|
1983 | } |
---|
1984 | |
---|
1985 | /* We inline the i-cache invalidation for speed */ |
---|
1986 | |
---|
1987 | #ifdef CLEAR_INSN_CACHE |
---|
1988 | CLEAR_INSN_CACHE (addr, eaddr); |
---|
1989 | #else |
---|
1990 | __clear_cache ((int) addr, (int) eaddr); |
---|
1991 | #endif |
---|
1992 | } |
---|
1993 | |
---|
1994 | #endif /* defined (NeXT) && defined (__MACH__) */ |
---|
1995 | |
---|
1996 | #ifdef __convex__ |
---|
1997 | |
---|
1998 | /* Make stack executable so we can call trampolines on stack. |
---|
1999 | This is called from INITIALIZE_TRAMPOLINE in convex.h. */ |
---|
2000 | |
---|
2001 | #include <sys/mman.h> |
---|
2002 | #include <sys/vmparam.h> |
---|
2003 | #include <machine/machparam.h> |
---|
2004 | |
---|
2005 | void |
---|
2006 | __enable_execute_stack () |
---|
2007 | { |
---|
2008 | int fp; |
---|
2009 | static unsigned lowest = USRSTACK; |
---|
2010 | unsigned current = (unsigned) &fp & -NBPG; |
---|
2011 | |
---|
2012 | if (lowest > current) |
---|
2013 | { |
---|
2014 | unsigned len = lowest - current; |
---|
2015 | mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); |
---|
2016 | lowest = current; |
---|
2017 | } |
---|
2018 | |
---|
2019 | /* Clear instruction cache in case an old trampoline is in it. */ |
---|
2020 | asm ("pich"); |
---|
2021 | } |
---|
2022 | #endif /* __convex__ */ |
---|
2023 | |
---|
2024 | #ifdef __DOLPHIN__ |
---|
2025 | |
---|
2026 | /* Modified from the convex -code above. */ |
---|
2027 | |
---|
2028 | #include <sys/param.h> |
---|
2029 | #include <errno.h> |
---|
2030 | #include <sys/m88kbcs.h> |
---|
2031 | |
---|
2032 | void |
---|
2033 | __enable_execute_stack () |
---|
2034 | { |
---|
2035 | int save_errno; |
---|
2036 | static unsigned long lowest = USRSTACK; |
---|
2037 | unsigned long current = (unsigned long) &save_errno & -NBPC; |
---|
2038 | |
---|
2039 | /* Ignore errno being set. memctl sets errno to EINVAL whenever the |
---|
2040 | address is seen as 'negative'. That is the case with the stack. */ |
---|
2041 | |
---|
2042 | save_errno=errno; |
---|
2043 | if (lowest > current) |
---|
2044 | { |
---|
2045 | unsigned len=lowest-current; |
---|
2046 | memctl(current,len,MCT_TEXT); |
---|
2047 | lowest = current; |
---|
2048 | } |
---|
2049 | else |
---|
2050 | memctl(current,NBPC,MCT_TEXT); |
---|
2051 | errno=save_errno; |
---|
2052 | } |
---|
2053 | |
---|
2054 | #endif /* __DOLPHIN__ */ |
---|
2055 | |
---|
2056 | #ifdef __pyr__ |
---|
2057 | |
---|
2058 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
---|
2059 | #include <stdio.h> |
---|
2060 | #include <sys/mman.h> |
---|
2061 | #include <sys/types.h> |
---|
2062 | #include <sys/param.h> |
---|
2063 | #include <sys/vmmac.h> |
---|
2064 | |
---|
2065 | /* Modified from the convex -code above. |
---|
2066 | mremap promises to clear the i-cache. */ |
---|
2067 | |
---|
2068 | void |
---|
2069 | __enable_execute_stack () |
---|
2070 | { |
---|
2071 | int fp; |
---|
2072 | if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ, |
---|
2073 | PROT_READ|PROT_WRITE|PROT_EXEC)) |
---|
2074 | { |
---|
2075 | perror ("mprotect in __enable_execute_stack"); |
---|
2076 | fflush (stderr); |
---|
2077 | abort (); |
---|
2078 | } |
---|
2079 | } |
---|
2080 | #endif /* __pyr__ */ |
---|
2081 | #endif /* L_trampoline */ |
---|
2082 | |
---|
2083 | #ifdef L__main |
---|
2084 | |
---|
2085 | #include "gbl-ctors.h" |
---|
2086 | /* Some systems use __main in a way incompatible with its use in gcc, in these |
---|
2087 | cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to |
---|
2088 | give the same symbol without quotes for an alternative entry point. You |
---|
2089 | must define both, or neither. */ |
---|
2090 | #ifndef NAME__MAIN |
---|
2091 | #define NAME__MAIN "__main" |
---|
2092 | #define SYMBOL__MAIN __main |
---|
2093 | #endif |
---|
2094 | |
---|
2095 | #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) |
---|
2096 | /* Run all the global destructors on exit from the program. */ |
---|
2097 | |
---|
2098 | void |
---|
2099 | __do_global_dtors () |
---|
2100 | { |
---|
2101 | #ifdef DO_GLOBAL_DTORS_BODY |
---|
2102 | DO_GLOBAL_DTORS_BODY; |
---|
2103 | #else |
---|
2104 | func_ptr *p; |
---|
2105 | for (p = __DTOR_LIST__ + 1; *p; ) |
---|
2106 | (*p++) (); |
---|
2107 | #endif |
---|
2108 | } |
---|
2109 | #endif |
---|
2110 | |
---|
2111 | #ifndef INIT_SECTION_ASM_OP |
---|
2112 | /* Run all the global constructors on entry to the program. */ |
---|
2113 | |
---|
2114 | #ifndef ON_EXIT |
---|
2115 | #define ON_EXIT(a, b) |
---|
2116 | #else |
---|
2117 | /* Make sure the exit routine is pulled in to define the globals as |
---|
2118 | bss symbols, just in case the linker does not automatically pull |
---|
2119 | bss definitions from the library. */ |
---|
2120 | |
---|
2121 | extern int _exit_dummy_decl; |
---|
2122 | int *_exit_dummy_ref = &_exit_dummy_decl; |
---|
2123 | #endif /* ON_EXIT */ |
---|
2124 | |
---|
2125 | void |
---|
2126 | __do_global_ctors () |
---|
2127 | { |
---|
2128 | DO_GLOBAL_CTORS_BODY; |
---|
2129 | ON_EXIT (__do_global_dtors, 0); |
---|
2130 | } |
---|
2131 | #endif /* no INIT_SECTION_ASM_OP */ |
---|
2132 | |
---|
2133 | #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main) |
---|
2134 | /* Subroutine called automatically by `main'. |
---|
2135 | Compiling a global function named `main' |
---|
2136 | produces an automatic call to this function at the beginning. |
---|
2137 | |
---|
2138 | For many systems, this routine calls __do_global_ctors. |
---|
2139 | For systems which support a .init section we use the .init section |
---|
2140 | to run __do_global_ctors, so we need not do anything here. */ |
---|
2141 | |
---|
2142 | void |
---|
2143 | SYMBOL__MAIN () |
---|
2144 | { |
---|
2145 | /* Support recursive calls to `main': run initializers just once. */ |
---|
2146 | static int initialized; |
---|
2147 | if (! initialized) |
---|
2148 | { |
---|
2149 | initialized = 1; |
---|
2150 | __do_global_ctors (); |
---|
2151 | } |
---|
2152 | } |
---|
2153 | #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */ |
---|
2154 | |
---|
2155 | #endif /* L__main */ |
---|
2156 | |
---|
2157 | #ifdef L_ctors |
---|
2158 | |
---|
2159 | #include "gbl-ctors.h" |
---|
2160 | |
---|
2161 | /* Provide default definitions for the lists of constructors and |
---|
2162 | destructors, so that we don't get linker errors. These symbols are |
---|
2163 | intentionally bss symbols, so that gld and/or collect will provide |
---|
2164 | the right values. */ |
---|
2165 | |
---|
2166 | /* We declare the lists here with two elements each, |
---|
2167 | so that they are valid empty lists if no other definition is loaded. */ |
---|
2168 | #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY) |
---|
2169 | #if defined(__NeXT__) || defined(_AIX) |
---|
2170 | /* After 2.3, try this definition on all systems. */ |
---|
2171 | func_ptr __CTOR_LIST__[2] = {0, 0}; |
---|
2172 | func_ptr __DTOR_LIST__[2] = {0, 0}; |
---|
2173 | #else |
---|
2174 | func_ptr __CTOR_LIST__[2]; |
---|
2175 | func_ptr __DTOR_LIST__[2]; |
---|
2176 | #endif |
---|
2177 | #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ |
---|
2178 | #endif /* L_ctors */ |
---|
2179 | |
---|
2180 | #ifdef L_exit |
---|
2181 | |
---|
2182 | #include "gbl-ctors.h" |
---|
2183 | |
---|
2184 | #ifndef ON_EXIT |
---|
2185 | |
---|
2186 | /* If we have no known way of registering our own __do_global_dtors |
---|
2187 | routine so that it will be invoked at program exit time, then we |
---|
2188 | have to define our own exit routine which will get this to happen. */ |
---|
2189 | |
---|
2190 | extern void __do_global_dtors (); |
---|
2191 | extern void _cleanup (); |
---|
2192 | extern void _exit () __attribute__ ((noreturn)); |
---|
2193 | |
---|
2194 | void |
---|
2195 | exit (status) |
---|
2196 | int status; |
---|
2197 | { |
---|
2198 | #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) |
---|
2199 | __do_global_dtors (); |
---|
2200 | #endif |
---|
2201 | #ifdef EXIT_BODY |
---|
2202 | EXIT_BODY; |
---|
2203 | #else |
---|
2204 | _cleanup (); |
---|
2205 | #endif |
---|
2206 | _exit (status); |
---|
2207 | } |
---|
2208 | |
---|
2209 | #else |
---|
2210 | int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */ |
---|
2211 | #endif |
---|
2212 | |
---|
2213 | #endif /* L_exit */ |
---|
2214 | |
---|
2215 | #ifdef L_eh |
---|
2216 | typedef struct { |
---|
2217 | void *start; |
---|
2218 | void *end; |
---|
2219 | void *exception_handler; |
---|
2220 | } exception_table; |
---|
2221 | |
---|
2222 | struct exception_table_node { |
---|
2223 | exception_table *table; |
---|
2224 | void *start; |
---|
2225 | void *end; |
---|
2226 | struct exception_table_node *next; |
---|
2227 | }; |
---|
2228 | |
---|
2229 | static int except_table_pos; |
---|
2230 | static void *except_pc; |
---|
2231 | static struct exception_table_node *exception_table_list; |
---|
2232 | |
---|
2233 | static exception_table * |
---|
2234 | find_exception_table (pc) |
---|
2235 | void* pc; |
---|
2236 | { |
---|
2237 | register struct exception_table_node *table = exception_table_list; |
---|
2238 | for ( ; table != 0; table = table->next) |
---|
2239 | { |
---|
2240 | if (table->start <= pc && table->end > pc) |
---|
2241 | return table->table; |
---|
2242 | } |
---|
2243 | return 0; |
---|
2244 | } |
---|
2245 | |
---|
2246 | /* this routine takes a pc, and the address of the exception handler associated |
---|
2247 | with the closest exception table handler entry associated with that PC, |
---|
2248 | or 0 if there are no table entries the PC fits in. The algorithm works |
---|
2249 | something like this: |
---|
2250 | |
---|
2251 | while(current_entry exists) { |
---|
2252 | if(current_entry.start < pc ) |
---|
2253 | current_entry = next_entry; |
---|
2254 | else { |
---|
2255 | if(prev_entry.start <= pc && prev_entry.end > pc) { |
---|
2256 | save pointer to prev_entry; |
---|
2257 | return prev_entry.exception_handler; |
---|
2258 | } |
---|
2259 | else return 0; |
---|
2260 | } |
---|
2261 | } |
---|
2262 | return 0; |
---|
2263 | |
---|
2264 | Assuming a correctly sorted table (ascending order) this routine should |
---|
2265 | return the tightest match... |
---|
2266 | |
---|
2267 | In the advent of a tie, we have to give the last entry, as it represents |
---|
2268 | an inner block. |
---|
2269 | */ |
---|
2270 | |
---|
2271 | |
---|
2272 | void * |
---|
2273 | __find_first_exception_table_match(pc) |
---|
2274 | void *pc; |
---|
2275 | { |
---|
2276 | exception_table *table = find_exception_table (pc); |
---|
2277 | int pos = 0; |
---|
2278 | int best = 0; |
---|
2279 | if (table == 0) |
---|
2280 | return (void*)0; |
---|
2281 | #if 0 |
---|
2282 | printf("find_first_exception_table_match(): pc = %x!\n",pc); |
---|
2283 | #endif |
---|
2284 | |
---|
2285 | except_pc = pc; |
---|
2286 | |
---|
2287 | #if 0 |
---|
2288 | /* We can't do this yet, as we don't know that the table is sorted. */ |
---|
2289 | do { |
---|
2290 | ++pos; |
---|
2291 | if (table[pos].start > except_pc) |
---|
2292 | /* found the first table[pos].start > except_pc, so the previous |
---|
2293 | entry better be the one we want! */ |
---|
2294 | break; |
---|
2295 | } while(table[pos].exception_handler != (void*)-1); |
---|
2296 | |
---|
2297 | --pos; |
---|
2298 | if (table[pos].start <= except_pc && table[pos].end > except_pc) |
---|
2299 | { |
---|
2300 | except_table_pos = pos; |
---|
2301 | #if 0 |
---|
2302 | printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler); |
---|
2303 | #endif |
---|
2304 | return table[pos].exception_handler; |
---|
2305 | } |
---|
2306 | #else |
---|
2307 | while (table[++pos].exception_handler != (void*)-1) { |
---|
2308 | if (table[pos].start <= except_pc && table[pos].end > except_pc) |
---|
2309 | { |
---|
2310 | /* This can apply. Make sure it is better or as good as the previous |
---|
2311 | best. */ |
---|
2312 | /* The best one ends first. */ |
---|
2313 | if (best == 0 || (table[pos].end <= table[best].end |
---|
2314 | /* The best one starts last. */ |
---|
2315 | && table[pos].start >= table[best].start)) |
---|
2316 | best = pos; |
---|
2317 | } |
---|
2318 | } |
---|
2319 | if (best != 0) |
---|
2320 | return table[best].exception_handler; |
---|
2321 | #endif |
---|
2322 | |
---|
2323 | #if 0 |
---|
2324 | printf("find_first_eh_table_match(): else: returning NULL!\n"); |
---|
2325 | #endif |
---|
2326 | return (void*)0; |
---|
2327 | } |
---|
2328 | |
---|
2329 | void * |
---|
2330 | __throw_type_match (void *catch_type, void *throw_type, void* obj) |
---|
2331 | { |
---|
2332 | #if 0 |
---|
2333 | printf("__throw_type_match (): catch_type = %s, throw_type = %s\n", |
---|
2334 | catch_type, throw_type); |
---|
2335 | #endif |
---|
2336 | if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0) |
---|
2337 | return obj; |
---|
2338 | return 0; |
---|
2339 | } |
---|
2340 | |
---|
2341 | void |
---|
2342 | __register_exceptions (exception_table *table) |
---|
2343 | { |
---|
2344 | struct exception_table_node *node; |
---|
2345 | exception_table *range = table + 1; |
---|
2346 | |
---|
2347 | if (range->start == (void*)-1) |
---|
2348 | return; |
---|
2349 | |
---|
2350 | node = (struct exception_table_node*) |
---|
2351 | malloc (sizeof (struct exception_table_node)); |
---|
2352 | node->table = table; |
---|
2353 | |
---|
2354 | /* This look can be optimized away either if the table |
---|
2355 | is sorted, or if we pass in extra parameters. */ |
---|
2356 | node->start = range->start; |
---|
2357 | node->end = range->end; |
---|
2358 | for (range++ ; range->start != (void*)(-1); range++) |
---|
2359 | { |
---|
2360 | if (range->start < node->start) |
---|
2361 | node->start = range->start; |
---|
2362 | if (range->end > node->end) |
---|
2363 | node->end = range->end; |
---|
2364 | } |
---|
2365 | |
---|
2366 | node->next = exception_table_list; |
---|
2367 | exception_table_list = node; |
---|
2368 | } |
---|
2369 | |
---|
2370 | #if #machine(i386) |
---|
2371 | void |
---|
2372 | __unwind_function(void *ptr) |
---|
2373 | { |
---|
2374 | asm("movl 8(%esp),%ecx"); |
---|
2375 | /* Undo current frame */ |
---|
2376 | asm("movl %ebp,%esp"); |
---|
2377 | asm("popl %ebp"); |
---|
2378 | /* like ret, but stay here */ |
---|
2379 | asm("addl $4,%esp"); |
---|
2380 | |
---|
2381 | /* Now, undo previous frame. */ |
---|
2382 | /* This is a test routine, as we have to dynamically probe to find out |
---|
2383 | what to pop for certain, this is just a guess. */ |
---|
2384 | asm("leal -16(%ebp),%esp"); |
---|
2385 | asm("pop %ebx"); |
---|
2386 | asm("pop %esi"); |
---|
2387 | asm("pop %edi"); |
---|
2388 | asm("movl %ebp,%esp"); |
---|
2389 | asm("popl %ebp"); |
---|
2390 | |
---|
2391 | asm("movl %ecx,0(%esp)"); |
---|
2392 | asm("ret"); |
---|
2393 | } |
---|
2394 | #elif #machine(rs6000) |
---|
2395 | __unwind_function(void *ptr) |
---|
2396 | { |
---|
2397 | asm("mr 31,1"); |
---|
2398 | asm("l 1,0(1)"); |
---|
2399 | asm("l 31,-4(1)"); |
---|
2400 | asm("# br"); |
---|
2401 | |
---|
2402 | asm("mr 31,1"); |
---|
2403 | asm("l 1,0(1)"); |
---|
2404 | /* use 31 as a scratch register to restore the link register. */ |
---|
2405 | asm("l 31, 8(1);mtlr 31 # l lr,8(1)"); |
---|
2406 | asm("l 31,-4(1)"); |
---|
2407 | asm("# br"); |
---|
2408 | asm("mtctr 3;bctr # b 3"); |
---|
2409 | } |
---|
2410 | #elif #machine(powerpc) |
---|
2411 | __unwind_function(void *ptr) |
---|
2412 | { |
---|
2413 | asm("mr 31,1"); |
---|
2414 | asm("lwz 1,0(1)"); |
---|
2415 | asm("lwz 31,-4(1)"); |
---|
2416 | asm("# br"); |
---|
2417 | |
---|
2418 | asm("mr 31,1"); |
---|
2419 | asm("lwz 1,0(1)"); |
---|
2420 | /* use 31 as a scratch register to restore the link register. */ |
---|
2421 | asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)"); |
---|
2422 | asm("lwz 31,-4(1)"); |
---|
2423 | asm("# br"); |
---|
2424 | asm("mtctr 3;bctr # b 3"); |
---|
2425 | } |
---|
2426 | #elif #machine(vax) |
---|
2427 | __unwind_function(void *ptr) |
---|
2428 | { |
---|
2429 | __label__ return_again; |
---|
2430 | |
---|
2431 | /* Replace our frame's return address with the label below. |
---|
2432 | During execution, we will first return here instead of to |
---|
2433 | caller, then second return takes caller's frame off the stack. |
---|
2434 | Two returns matches two actual calls, so is less likely to |
---|
2435 | confuse debuggers. `16' corresponds to RETURN_ADDRESS_OFFSET. */ |
---|
2436 | __asm ("movl %0,16(fp)" : : "p" (&& return_again)); |
---|
2437 | return; |
---|
2438 | |
---|
2439 | return_again: |
---|
2440 | return; |
---|
2441 | } |
---|
2442 | #else |
---|
2443 | __unwind_function(void *ptr) |
---|
2444 | { |
---|
2445 | abort (); |
---|
2446 | } |
---|
2447 | #endif /* powerpc */ |
---|
2448 | #endif /* L_eh */ |
---|
2449 | |
---|
2450 | #ifdef L_pure |
---|
2451 | #ifndef inhibit_libc |
---|
2452 | /* This gets us __GNU_LIBRARY__. */ |
---|
2453 | #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ |
---|
2454 | #include <stdio.h> |
---|
2455 | |
---|
2456 | #ifdef __GNU_LIBRARY__ |
---|
2457 | /* Avoid forcing the library's meaning of `write' on the user program |
---|
2458 | by using the "internal" name (for use within the library) */ |
---|
2459 | #define write(fd, buf, n) __write((fd), (buf), (n)) |
---|
2460 | #endif |
---|
2461 | #endif /* inhibit_libc */ |
---|
2462 | |
---|
2463 | #define MESSAGE "pure virtual method called\n" |
---|
2464 | |
---|
2465 | void |
---|
2466 | __pure_virtual () |
---|
2467 | { |
---|
2468 | #ifndef inhibit_libc |
---|
2469 | write (2, MESSAGE, sizeof (MESSAGE) - 1); |
---|
2470 | #endif |
---|
2471 | _exit (-1); |
---|
2472 | } |
---|
2473 | #endif |
---|