|
|
1.1 ! root 1: /* More subroutines needed by GCC output code on some machines. */ ! 2: /* Compile this one with gcc. */ ! 3: /* Copyright (C) 1989, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 20: ! 21: /* As a special exception, if you link this library with files ! 22: compiled with GCC to produce an executable, this does not cause ! 23: the resulting executable to be covered by the GNU General Public License. ! 24: This exception does not however invalidate any other reasons why ! 25: the executable file might be covered by the GNU General Public License. */ ! 26: ! 27: /* It is incorrect to include config.h here, because this file is being ! 28: compiled for the target, and hence definitions concerning only the host ! 29: do not apply. */ ! 30: ! 31: #include "tm.h" ! 32: #include "gstddef.h" ! 33: ! 34: /* Don't use `fancy_abort' here even if config.h says to use it. */ ! 35: #ifdef abort ! 36: #undef abort ! 37: #endif ! 38: ! 39: /* Need to undef this because LONG_TYPE_SIZE may rely upon GCC's ! 40: internal `target_flags' variable. */ ! 41: #undef LONG_TYPE_SIZE ! 42: ! 43: #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT) ! 44: ! 45: #ifndef SItype ! 46: #define SItype long int ! 47: #endif ! 48: ! 49: /* long long ints are pairs of long ints in the order determined by ! 50: WORDS_BIG_ENDIAN. */ ! 51: ! 52: #if WORDS_BIG_ENDIAN ! 53: struct longlong {long high, low;}; ! 54: #else ! 55: struct longlong {long low, high;}; ! 56: #endif ! 57: ! 58: /* We need this union to unpack/pack longlongs, since we don't have ! 59: any arithmetic yet. Incoming long long parameters are stored ! 60: into the `ll' field, and the unpacked result is read from the struct ! 61: longlong. */ ! 62: ! 63: typedef union ! 64: { ! 65: struct longlong s; ! 66: long long ll; ! 67: } long_long; ! 68: ! 69: #if defined (L_udivmoddi4) || defined (L_muldi3) ! 70: ! 71: #include "longlong.h" ! 72: ! 73: #endif /* udiv or mul */ ! 74: ! 75: extern long long __fixunssfdi (float a); ! 76: extern long long __fixunsdfdi (double a); ! 77: ! 78: #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) ! 79: #if defined (L_divdi3) || defined (L_moddi3) ! 80: static inline ! 81: #endif ! 82: long long ! 83: __negdi2 (u) ! 84: long long u; ! 85: { ! 86: long_long w; ! 87: long_long uu; ! 88: ! 89: uu.ll = u; ! 90: ! 91: w.s.low = -uu.s.low; ! 92: w.s.high = -uu.s.high - ((unsigned long) w.s.low > 0); ! 93: ! 94: return w.ll; ! 95: } ! 96: #endif ! 97: ! 98: #ifdef L_lshldi3 ! 99: long long ! 100: __lshldi3 (u, b) ! 101: long long u; ! 102: int b; ! 103: { ! 104: long_long w; ! 105: long bm; ! 106: long_long uu; ! 107: ! 108: if (b == 0) ! 109: return u; ! 110: ! 111: uu.ll = u; ! 112: ! 113: bm = (sizeof (long) * BITS_PER_UNIT) - b; ! 114: if (bm <= 0) ! 115: { ! 116: w.s.low = 0; ! 117: w.s.high = (unsigned long)uu.s.low << -bm; ! 118: } ! 119: else ! 120: { ! 121: unsigned long carries = (unsigned long)uu.s.low >> bm; ! 122: w.s.low = (unsigned long)uu.s.low << b; ! 123: w.s.high = ((unsigned long)uu.s.high << b) | carries; ! 124: } ! 125: ! 126: return w.ll; ! 127: } ! 128: #endif ! 129: ! 130: #ifdef L_lshrdi3 ! 131: long long ! 132: __lshrdi3 (u, b) ! 133: long long u; ! 134: int b; ! 135: { ! 136: long_long w; ! 137: long bm; ! 138: long_long uu; ! 139: ! 140: if (b == 0) ! 141: return u; ! 142: ! 143: uu.ll = u; ! 144: ! 145: bm = (sizeof (long) * BITS_PER_UNIT) - b; ! 146: if (bm <= 0) ! 147: { ! 148: w.s.high = 0; ! 149: w.s.low = (unsigned long)uu.s.high >> -bm; ! 150: } ! 151: else ! 152: { ! 153: unsigned long carries = (unsigned long)uu.s.high << bm; ! 154: w.s.high = (unsigned long)uu.s.high >> b; ! 155: w.s.low = ((unsigned long)uu.s.low >> b) | carries; ! 156: } ! 157: ! 158: return w.ll; ! 159: } ! 160: #endif ! 161: ! 162: #ifdef L_ashldi3 ! 163: long long ! 164: __ashldi3 (u, b) ! 165: long long u; ! 166: int b; ! 167: { ! 168: long_long w; ! 169: long bm; ! 170: long_long uu; ! 171: ! 172: if (b == 0) ! 173: return u; ! 174: ! 175: uu.ll = u; ! 176: ! 177: bm = (sizeof (long) * BITS_PER_UNIT) - b; ! 178: if (bm <= 0) ! 179: { ! 180: w.s.low = 0; ! 181: w.s.high = (unsigned long)uu.s.low << -bm; ! 182: } ! 183: else ! 184: { ! 185: unsigned long carries = (unsigned long)uu.s.low >> bm; ! 186: w.s.low = (unsigned long)uu.s.low << b; ! 187: w.s.high = ((unsigned long)uu.s.high << b) | carries; ! 188: } ! 189: ! 190: return w.ll; ! 191: } ! 192: #endif ! 193: ! 194: #ifdef L_ashrdi3 ! 195: long long ! 196: __ashrdi3 (u, b) ! 197: long long u; ! 198: int b; ! 199: { ! 200: long_long w; ! 201: long bm; ! 202: long_long uu; ! 203: ! 204: if (b == 0) ! 205: return u; ! 206: ! 207: uu.ll = u; ! 208: ! 209: bm = (sizeof (long) * BITS_PER_UNIT) - b; ! 210: if (bm <= 0) ! 211: { ! 212: /* w.s.high = 1..1 or 0..0 */ ! 213: w.s.high = uu.s.high >> (sizeof (long) * BITS_PER_UNIT - 1); ! 214: w.s.low = uu.s.high >> -bm; ! 215: } ! 216: else ! 217: { ! 218: unsigned long carries = (unsigned long)uu.s.high << bm; ! 219: w.s.high = uu.s.high >> b; ! 220: w.s.low = ((unsigned long)uu.s.low >> b) | carries; ! 221: } ! 222: ! 223: return w.ll; ! 224: } ! 225: #endif ! 226: ! 227: #ifdef L_muldi3 ! 228: long long ! 229: __muldi3 (u, v) ! 230: long long u, v; ! 231: { ! 232: long_long w; ! 233: long_long uu, vv; ! 234: ! 235: uu.ll = u, ! 236: vv.ll = v; ! 237: ! 238: w.ll = __umulsidi3 (uu.s.low, vv.s.low); ! 239: w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high ! 240: + (unsigned long) uu.s.high * (unsigned long) vv.s.low); ! 241: ! 242: return w.ll; ! 243: } ! 244: #endif ! 245: ! 246: #ifdef L_udivmoddi4 ! 247: static const unsigned char __clz_tab[] = ! 248: { ! 249: 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, ! 250: 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, ! 251: 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, ! 252: 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, ! 253: 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, ! 254: 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, ! 255: 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, ! 256: 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, ! 257: }; ! 258: ! 259: unsigned long long ! 260: __udivmoddi4 (n, d, rp) ! 261: unsigned long long n, d; ! 262: unsigned long long int *rp; ! 263: { ! 264: long_long ww; ! 265: long_long nn, dd; ! 266: long_long rr; ! 267: unsigned long d0, d1, n0, n1, n2; ! 268: unsigned long q0, q1; ! 269: unsigned b, bm; ! 270: ! 271: nn.ll = n; ! 272: dd.ll = d; ! 273: ! 274: d0 = dd.s.low; ! 275: d1 = dd.s.high; ! 276: n0 = nn.s.low; ! 277: n1 = nn.s.high; ! 278: ! 279: #if !UDIV_NEEDS_NORMALIZATION ! 280: if (d1 == 0) ! 281: { ! 282: if (d0 > n1) ! 283: { ! 284: /* 0q = nn / 0D */ ! 285: ! 286: udiv_qrnnd (q0, n0, n1, n0, d0); ! 287: q1 = 0; ! 288: ! 289: /* Remainder in n0. */ ! 290: } ! 291: else ! 292: { ! 293: /* qq = NN / 0d */ ! 294: ! 295: if (d0 == 0) ! 296: d0 = 1 / d0; /* Divide intentionally by zero. */ ! 297: ! 298: udiv_qrnnd (q1, n1, 0, n1, d0); ! 299: udiv_qrnnd (q0, n0, n1, n0, d0); ! 300: ! 301: /* Remainder in n0. */ ! 302: } ! 303: ! 304: if (rp != 0) ! 305: { ! 306: rr.s.low = n0; ! 307: rr.s.high = 0; ! 308: *rp = rr.ll; ! 309: } ! 310: } ! 311: ! 312: #else /* UDIV_NEEDS_NORMALIZATION */ ! 313: ! 314: if (d1 == 0) ! 315: { ! 316: if (d0 > n1) ! 317: { ! 318: /* 0q = nn / 0D */ ! 319: ! 320: count_leading_zeros (bm, d0); ! 321: ! 322: if (bm != 0) ! 323: { ! 324: /* Normalize, i.e. make the most significant bit of the ! 325: denominator set. */ ! 326: ! 327: d0 = d0 << bm; ! 328: n1 = (n1 << bm) | (n0 >> (LONG_TYPE_SIZE - bm)); ! 329: n0 = n0 << bm; ! 330: } ! 331: ! 332: udiv_qrnnd (q0, n0, n1, n0, d0); ! 333: q1 = 0; ! 334: ! 335: /* Remainder in n0 >> bm. */ ! 336: } ! 337: else ! 338: { ! 339: /* qq = NN / 0d */ ! 340: ! 341: if (d0 == 0) ! 342: d0 = 1 / d0; /* Divide intentionally by zero. */ ! 343: ! 344: count_leading_zeros (bm, d0); ! 345: ! 346: if (bm == 0) ! 347: { ! 348: /* From (n1 >= d0) /\ (the most significant bit of d0 is set), ! 349: conclude (the most significant bit of n1 is set) /\ (the ! 350: leading quotient digit q1 = 1). ! 351: ! 352: This special case is necessary, not an optimization. ! 353: (Shifts counts of LONG_TYPE_SIZE are undefined.) */ ! 354: ! 355: n1 -= d0; ! 356: q1 = 1; ! 357: } ! 358: else ! 359: { ! 360: /* Normalize. */ ! 361: ! 362: b = LONG_TYPE_SIZE - bm; ! 363: ! 364: d0 = d0 << bm; ! 365: n2 = n1 >> b; ! 366: n1 = (n1 << bm) | (n0 >> b); ! 367: n0 = n0 << bm; ! 368: ! 369: udiv_qrnnd (q1, n1, n2, n1, d0); ! 370: } ! 371: ! 372: /* n1 != d0... */ ! 373: ! 374: udiv_qrnnd (q0, n0, n1, n0, d0); ! 375: ! 376: /* Remainder in n0 >> bm. */ ! 377: } ! 378: ! 379: if (rp != 0) ! 380: { ! 381: rr.s.low = n0 >> bm; ! 382: rr.s.high = 0; ! 383: *rp = rr.ll; ! 384: } ! 385: } ! 386: #endif /* UDIV_NEEDS_NORMALIZATION */ ! 387: ! 388: else ! 389: { ! 390: if (d1 > n1) ! 391: { ! 392: /* 00 = nn / DD */ ! 393: ! 394: q0 = 0; ! 395: q1 = 0; ! 396: ! 397: /* Remainder in n1n0. */ ! 398: if (rp != 0) ! 399: { ! 400: rr.s.low = n0; ! 401: rr.s.high = n1; ! 402: *rp = rr.ll; ! 403: } ! 404: } ! 405: else ! 406: { ! 407: /* 0q = NN / dd */ ! 408: ! 409: count_leading_zeros (bm, d1); ! 410: if (bm == 0) ! 411: { ! 412: /* From (n1 >= d1) /\ (the most significant bit of d1 is set), ! 413: conclude (the most significant bit of n1 is set) /\ (the ! 414: quotient digit q0 = 0 or 1). ! 415: ! 416: This special case is necessary, not an optimization. */ ! 417: ! 418: /* The condition on the next line takes advantage of that ! 419: n1 >= d1 (true due to program flow). */ ! 420: if (n1 > d1 || n0 >= d0) ! 421: { ! 422: q0 = 1; ! 423: sub_ddmmss (n1, n0, n1, n0, d1, d0); ! 424: } ! 425: else ! 426: q0 = 0; ! 427: ! 428: q1 = 0; ! 429: ! 430: if (rp != 0) ! 431: { ! 432: rr.s.low = n0; ! 433: rr.s.high = n1; ! 434: *rp = rr.ll; ! 435: } ! 436: } ! 437: else ! 438: { ! 439: unsigned long m1, m0; ! 440: /* Normalize. */ ! 441: ! 442: b = LONG_TYPE_SIZE - bm; ! 443: ! 444: d1 = (d1 << bm) | (d0 >> b); ! 445: d0 = d0 << bm; ! 446: n2 = n1 >> b; ! 447: n1 = (n1 << bm) | (n0 >> b); ! 448: n0 = n0 << bm; ! 449: ! 450: udiv_qrnnd (q0, n1, n2, n1, d1); ! 451: umul_ppmm (m1, m0, q0, d0); ! 452: ! 453: if (m1 > n1 || (m1 == n1 && m0 > n0)) ! 454: { ! 455: q0--; ! 456: sub_ddmmss (m1, m0, m1, m0, d1, d0); ! 457: } ! 458: ! 459: q1 = 0; ! 460: ! 461: /* Remainder in (n1n0 - m1m0) >> bm. */ ! 462: if (rp != 0) ! 463: { ! 464: sub_ddmmss (n1, n0, n1, n0, m1, m0); ! 465: rr.s.low = (n1 << b) | (n0 >> bm); ! 466: rr.s.high = n1 >> bm; ! 467: *rp = rr.ll; ! 468: } ! 469: } ! 470: } ! 471: } ! 472: ! 473: ww.s.low = q0; ! 474: ww.s.high = q1; ! 475: return ww.ll; ! 476: } ! 477: #endif ! 478: ! 479: #ifdef L_divdi3 ! 480: unsigned long long __udivmoddi4 (); ! 481: long long ! 482: __divdi3 (u, v) ! 483: long long u, v; ! 484: { ! 485: int c = 0; ! 486: long_long uu, vv; ! 487: long long w; ! 488: ! 489: uu.ll = u; ! 490: vv.ll = v; ! 491: ! 492: if (uu.s.high < 0) ! 493: c = ~c, ! 494: uu.ll = __negdi2 (uu.ll); ! 495: if (vv.s.high < 0) ! 496: c = ~c, ! 497: vv.ll = __negdi2 (vv.ll); ! 498: ! 499: w = __udivmoddi4 (uu.ll, vv.ll, (unsigned long long *) 0); ! 500: if (c) ! 501: w = __negdi2 (w); ! 502: ! 503: return w; ! 504: } ! 505: #endif ! 506: ! 507: #ifdef L_moddi3 ! 508: unsigned long long __udivmoddi4 (); ! 509: long long ! 510: __moddi3 (u, v) ! 511: long long u, v; ! 512: { ! 513: int c = 0; ! 514: long_long uu, vv; ! 515: long long w; ! 516: ! 517: uu.ll = u; ! 518: vv.ll = v; ! 519: ! 520: if (uu.s.high < 0) ! 521: c = ~c, ! 522: uu.ll = __negdi2 (uu.ll); ! 523: if (vv.s.high < 0) ! 524: vv.ll = __negdi2 (vv.ll); ! 525: ! 526: (void) __udivmoddi4 (uu.ll, vv.ll, &w); ! 527: if (c) ! 528: w = __negdi2 (w); ! 529: ! 530: return w; ! 531: } ! 532: #endif ! 533: ! 534: #ifdef L_umoddi3 ! 535: unsigned long long __udivmoddi4 (); ! 536: unsigned long long ! 537: __umoddi3 (u, v) ! 538: unsigned long long u, v; ! 539: { ! 540: long long w; ! 541: ! 542: (void) __udivmoddi4 (u, v, &w); ! 543: ! 544: return w; ! 545: } ! 546: #endif ! 547: ! 548: #ifdef L_udivdi3 ! 549: unsigned long long __udivmoddi4 (); ! 550: unsigned long long ! 551: __udivdi3 (n, d) ! 552: unsigned long long n, d; ! 553: { ! 554: return __udivmoddi4 (n, d, (unsigned long long *) 0); ! 555: } ! 556: #endif ! 557: ! 558: #ifdef L_cmpdi2 ! 559: SItype ! 560: __cmpdi2 (a, b) ! 561: long long a, b; ! 562: { ! 563: long_long au, bu; ! 564: ! 565: au.ll = a, bu.ll = b; ! 566: ! 567: if (au.s.high < bu.s.high) ! 568: return 0; ! 569: else if (au.s.high > bu.s.high) ! 570: return 2; ! 571: if ((unsigned long) au.s.low < (unsigned long) bu.s.low) ! 572: return 0; ! 573: else if ((unsigned long) au.s.low > (unsigned long) bu.s.low) ! 574: return 2; ! 575: return 1; ! 576: } ! 577: #endif ! 578: ! 579: #ifdef L_ucmpdi2 ! 580: SItype ! 581: __ucmpdi2 (a, b) ! 582: long long a, b; ! 583: { ! 584: long_long au, bu; ! 585: ! 586: au.ll = a, bu.ll = b; ! 587: ! 588: if ((unsigned long) au.s.high < (unsigned long) bu.s.high) ! 589: return 0; ! 590: else if ((unsigned long) au.s.high > (unsigned long) bu.s.high) ! 591: return 2; ! 592: if ((unsigned long) au.s.low < (unsigned long) bu.s.low) ! 593: return 0; ! 594: else if ((unsigned long) au.s.low > (unsigned long) bu.s.low) ! 595: return 2; ! 596: return 1; ! 597: } ! 598: #endif ! 599: ! 600: #ifdef L_fixunsdfdi ! 601: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! 602: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! 603: ! 604: long long ! 605: __fixunsdfdi (a) ! 606: double a; ! 607: { ! 608: double b; ! 609: unsigned long long v; ! 610: ! 611: if (a < 0) ! 612: return 0; ! 613: ! 614: /* Compute high word of result, as a flonum. */ ! 615: b = (a / HIGH_WORD_COEFF); ! 616: /* Convert that to fixed (but not to long long!), ! 617: and shift it into the high word. */ ! 618: v = (unsigned long int) b; ! 619: v <<= WORD_SIZE; ! 620: /* Remove high part from the double, leaving the low part as flonum. */ ! 621: a -= (double)v; ! 622: /* Convert that to fixed (but not to long long!) and add it in. ! 623: Sometimes A comes out negative. This is significant, since ! 624: A has more bits than a long int does. */ ! 625: if (a < 0) ! 626: v -= (unsigned long int) (- a); ! 627: else ! 628: v += (unsigned long int) a; ! 629: return v; ! 630: } ! 631: #endif ! 632: ! 633: #ifdef L_fixdfdi ! 634: long long ! 635: __fixdfdi (a) ! 636: double a; ! 637: { ! 638: if (a < 0) ! 639: return - __fixunsdfdi (-a); ! 640: return __fixunsdfdi (a); ! 641: } ! 642: #endif ! 643: ! 644: #ifdef L_fixunssfdi ! 645: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! 646: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! 647: ! 648: long long ! 649: __fixunssfdi (float original_a) ! 650: { ! 651: /* Convert the float to a double, because that is surely not going ! 652: to lose any bits. Some day someone else can write a faster version ! 653: that avoids converting to double, and verify it really works right. */ ! 654: double a = original_a; ! 655: double b; ! 656: unsigned long long v; ! 657: ! 658: if (a < 0) ! 659: return 0; ! 660: ! 661: /* Compute high word of result, as a flonum. */ ! 662: b = (a / HIGH_WORD_COEFF); ! 663: /* Convert that to fixed (but not to long long!), ! 664: and shift it into the high word. */ ! 665: v = (unsigned long int) b; ! 666: v <<= WORD_SIZE; ! 667: /* Remove high part from the double, leaving the low part as flonum. */ ! 668: a -= (double)v; ! 669: /* Convert that to fixed (but not to long long!) and add it in. ! 670: Sometimes A comes out negative. This is significant, since ! 671: A has more bits than a long int does. */ ! 672: if (a < 0) ! 673: v -= (unsigned long int) (- a); ! 674: else ! 675: v += (unsigned long int) a; ! 676: return v; ! 677: } ! 678: #endif ! 679: ! 680: #ifdef L_fixsfdi ! 681: long long ! 682: __fixsfdi (float a) ! 683: { ! 684: if (a < 0) ! 685: return - __fixunssfdi (-a); ! 686: return __fixunssfdi (a); ! 687: } ! 688: #endif ! 689: ! 690: #ifdef L_floatdidf ! 691: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! 692: #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2)) ! 693: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! 694: ! 695: double ! 696: __floatdidf (u) ! 697: long long u; ! 698: { ! 699: double d; ! 700: int negate = 0; ! 701: ! 702: if (u < 0) ! 703: u = -u, negate = 1; ! 704: ! 705: d = (unsigned int) (u >> WORD_SIZE); ! 706: d *= HIGH_HALFWORD_COEFF; ! 707: d *= HIGH_HALFWORD_COEFF; ! 708: d += (unsigned int) (u & (HIGH_WORD_COEFF - 1)); ! 709: ! 710: return (negate ? -d : d); ! 711: } ! 712: #endif ! 713: ! 714: #ifdef L_floatdisf ! 715: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! 716: #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2)) ! 717: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! 718: ! 719: float ! 720: __floatdisf (u) ! 721: long long u; ! 722: { ! 723: float f; ! 724: int negate = 0; ! 725: ! 726: if (u < 0) ! 727: u = -u, negate = 1; ! 728: ! 729: f = (unsigned int) (u >> WORD_SIZE); ! 730: f *= HIGH_HALFWORD_COEFF; ! 731: f *= HIGH_HALFWORD_COEFF; ! 732: f += (unsigned int) (u & (HIGH_WORD_COEFF - 1)); ! 733: ! 734: return (negate ? -f : f); ! 735: } ! 736: #endif ! 737: ! 738: #ifdef L_fixunsdfsi ! 739: #include "limits.h" ! 740: ! 741: unsigned SItype ! 742: __fixunsdfsi (a) ! 743: double a; ! 744: { ! 745: if (a >= - (double) LONG_MIN) ! 746: return (SItype) (a + LONG_MIN) - LONG_MIN; ! 747: return (SItype) a; ! 748: } ! 749: #endif ! 750: ! 751: #ifdef L_fixunssfsi ! 752: #include "limits.h" ! 753: ! 754: unsigned SItype ! 755: __fixunssfsi (float a) ! 756: { ! 757: if (a >= - (float) LONG_MIN) ! 758: return (SItype) (a + LONG_MIN) - LONG_MIN; ! 759: return (SItype) a; ! 760: } ! 761: #endif ! 762: ! 763: #ifdef L_varargs ! 764: #ifdef __i860__ ! 765: #ifdef SVR4 ! 766: asm (" .text"); ! 767: asm (" .align 4"); ! 768: ! 769: asm (".globl __builtin_saveregs"); ! 770: asm ("__builtin_saveregs:"); ! 771: asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */ ! 772: asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save ! 773: area and also for a new va_list ! 774: structure */ ! 775: /* Save all argument registers in the arg reg save area. The ! 776: arg reg save area must have the following layout (according ! 777: to the svr4 ABI): ! 778: ! 779: struct { ! 780: union { ! 781: float freg[8]; ! 782: double dreg[4]; ! 783: } float_regs; ! 784: long ireg[12]; ! 785: }; ! 786: */ ! 787: ! 788: asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */ ! 789: asm (" fst.q %f12,16(%sp)"); ! 790: ! 791: asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */ ! 792: asm (" st.l %r17,36(%sp)"); ! 793: asm (" st.l %r18,40(%sp)"); ! 794: asm (" st.l %r19,44(%sp)"); ! 795: asm (" st.l %r20,48(%sp)"); ! 796: asm (" st.l %r21,52(%sp)"); ! 797: asm (" st.l %r22,56(%sp)"); ! 798: asm (" st.l %r23,60(%sp)"); ! 799: asm (" st.l %r24,64(%sp)"); ! 800: asm (" st.l %r25,68(%sp)"); ! 801: asm (" st.l %r26,72(%sp)"); ! 802: asm (" st.l %r27,76(%sp)"); ! 803: ! 804: asm (" adds 80,%sp,%r16"); /* compute the address of the new ! 805: va_list structure. Put in into ! 806: r16 so that it will be returned ! 807: to the caller. */ ! 808: ! 809: /* Initialize all fields of the new va_list structure. This ! 810: structure looks like: ! 811: ! 812: typedef struct { ! 813: unsigned long ireg_used; ! 814: unsigned long freg_used; ! 815: long *reg_base; ! 816: long *mem_ptr; ! 817: } va_list; ! 818: */ ! 819: ! 820: asm (" st.l %r0, 0(%r16)"); /* nfixed */ ! 821: asm (" st.l %r0, 4(%r16)"); /* nfloating */ ! 822: asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */ ! 823: asm (" bri %r1"); /* delayed return */ ! 824: asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */ ! 825: ! 826: #else /* not SVR4 */ ! 827: asm (" .text"); ! 828: asm (" .align 4"); ! 829: ! 830: asm (".globl ___builtin_saveregs"); ! 831: asm ("___builtin_saveregs:"); ! 832: asm (" mov sp,r30"); ! 833: asm (" andnot 0x0f,sp,sp"); ! 834: asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */ ! 835: ! 836: /* Fill in the __va_struct. */ ! 837: asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */ ! 838: asm (" st.l r17, 4(sp)"); /* int fixed[12] */ ! 839: asm (" st.l r18, 8(sp)"); ! 840: asm (" st.l r19,12(sp)"); ! 841: asm (" st.l r20,16(sp)"); ! 842: asm (" st.l r21,20(sp)"); ! 843: asm (" st.l r22,24(sp)"); ! 844: asm (" st.l r23,28(sp)"); ! 845: asm (" st.l r24,32(sp)"); ! 846: asm (" st.l r25,36(sp)"); ! 847: asm (" st.l r26,40(sp)"); ! 848: asm (" st.l r27,44(sp)"); ! 849: ! 850: asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */ ! 851: asm (" fst.q f12,64(sp)"); /* int floating[8] */ ! 852: ! 853: /* Fill in the __va_ctl. */ ! 854: asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */ ! 855: asm (" st.l r28,84(sp)"); /* pointer to more args */ ! 856: asm (" st.l r0, 88(sp)"); /* nfixed */ ! 857: asm (" st.l r0, 92(sp)"); /* nfloating */ ! 858: ! 859: asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */ ! 860: asm (" bri r1"); ! 861: asm (" mov r30,sp"); ! 862: /* recover stack and pass address to start ! 863: of data. */ ! 864: #endif /* not SVR4 */ ! 865: #else /* not __i860__ */ ! 866: #ifdef __sparc__ ! 867: asm (".global ___builtin_saveregs"); ! 868: asm ("___builtin_saveregs:"); ! 869: asm ("st %i0,[%fp+68]"); ! 870: asm ("st %i1,[%fp+72]"); ! 871: asm ("st %i2,[%fp+76]"); ! 872: asm ("st %i3,[%fp+80]"); ! 873: asm ("st %i4,[%fp+84]"); ! 874: asm ("retl"); ! 875: asm ("st %i5,[%fp+88]"); ! 876: #else /* not __sparc__ */ ! 877: #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__) ! 878: ! 879: asm (" .text"); ! 880: asm (" .ent __builtin_saveregs"); ! 881: asm (" .globl __builtin_saveregs"); ! 882: asm ("__builtin_saveregs:"); ! 883: asm (" sw $4,0($30)"); ! 884: asm (" sw $5,4($30)"); ! 885: asm (" sw $6,8($30)"); ! 886: asm (" sw $7,12($30)"); ! 887: asm (" j $31"); ! 888: asm (" .end __builtin_saveregs"); ! 889: #else /* not __mips__, etc. */ ! 890: __builtin_saveregs () ! 891: { ! 892: abort (); ! 893: } ! 894: #endif /* not __mips__ */ ! 895: #endif /* not __sparc__ */ ! 896: #endif /* not __i860__ */ ! 897: #endif ! 898: ! 899: #ifdef L_eprintf ! 900: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ ! 901: #include <stdio.h> ! 902: /* This is used by the `assert' macro. */ ! 903: void ! 904: __eprintf (string, expression, line, filename) ! 905: char *string; ! 906: char *expression; ! 907: int line; ! 908: char *filename; ! 909: { ! 910: fprintf (stderr, string, expression, line, filename); ! 911: fflush (stderr); ! 912: abort (); ! 913: } ! 914: #endif ! 915: ! 916: #ifdef L_bb ! 917: /* Avoid warning from ranlib about empty object file. */ ! 918: void ! 919: __bb_avoid_warning () ! 920: {} ! 921: ! 922: #if defined (__sun__) && defined (__mc68000__) ! 923: struct bb ! 924: { ! 925: int initialized; ! 926: char *filename; ! 927: int *counts; ! 928: int ncounts; ! 929: int zero_word; ! 930: int *addresses; ! 931: }; ! 932: ! 933: extern int ___tcov_init; ! 934: ! 935: __bb_init_func (blocks) ! 936: struct bb *blocks; ! 937: { ! 938: if (! ___tcov_init) ! 939: ___tcov_init_func (); ! 940: ! 941: ___bb_link (blocks->filename, blocks->counts, blocks->ncounts); ! 942: } ! 943: ! 944: #endif ! 945: #endif ! 946: ! 947: /* frills for C++ */ ! 948: ! 949: #ifdef L_builtin_new ! 950: typedef void (*vfp)(void); ! 951: ! 952: extern vfp __new_handler; ! 953: ! 954: void * ! 955: __builtin_new (sz) ! 956: long sz; ! 957: { ! 958: void *p; ! 959: ! 960: p = (void *) malloc (sz); ! 961: if (p == 0) ! 962: (*__new_handler) (); ! 963: return p; ! 964: } ! 965: #endif ! 966: ! 967: #ifdef L_builtin_New ! 968: typedef void (*vfp)(void); ! 969: ! 970: static void default_new_handler (); ! 971: ! 972: vfp __new_handler = default_new_handler; ! 973: ! 974: void * ! 975: __builtin_vec_new (p, maxindex, size, ctor) ! 976: void *p; ! 977: int maxindex, size; ! 978: void (*ctor)(void *); ! 979: { ! 980: int i, nelts = maxindex + 1; ! 981: void *rval; ! 982: ! 983: if (p == 0) ! 984: p = (void *)__builtin_new (nelts * size); ! 985: ! 986: rval = p; ! 987: ! 988: for (i = 0; i < nelts; i++) ! 989: { ! 990: (*ctor) (p); ! 991: p += size; ! 992: } ! 993: ! 994: return rval; ! 995: } ! 996: ! 997: vfp ! 998: __set_new_handler (handler) ! 999: vfp handler; ! 1000: { ! 1001: vfp prev_handler; ! 1002: ! 1003: prev_handler = __new_handler; ! 1004: if (handler == 0) handler = default_new_handler; ! 1005: __new_handler = handler; ! 1006: return prev_handler; ! 1007: } ! 1008: ! 1009: vfp ! 1010: set_new_handler (handler) ! 1011: vfp handler; ! 1012: { ! 1013: return __set_new_handler (handler); ! 1014: } ! 1015: ! 1016: static void ! 1017: default_new_handler () ! 1018: { ! 1019: /* don't use fprintf (stderr, ...) because it may need to call malloc. */ ! 1020: /* This should really print the name of the program, but that is hard to ! 1021: do. We need a standard, clean way to get at the name. */ ! 1022: write (2, "Virtual memory exceeded in `new'\n", 33); ! 1023: /* don't call exit () because that may call global destructors which ! 1024: may cause a loop. */ ! 1025: _exit (-1); ! 1026: } ! 1027: #endif ! 1028: ! 1029: #ifdef L_builtin_del ! 1030: typedef void (*vfp)(void); ! 1031: ! 1032: void ! 1033: __builtin_delete (ptr) ! 1034: void *ptr; ! 1035: { ! 1036: if (ptr) ! 1037: free (ptr); ! 1038: } ! 1039: ! 1040: void ! 1041: __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete) ! 1042: void *ptr; ! 1043: int maxindex, size; ! 1044: void (*dtor)(); ! 1045: int auto_delete; ! 1046: { ! 1047: int i, nelts = maxindex + 1; ! 1048: void *p = ptr; ! 1049: ! 1050: ptr += nelts * size; ! 1051: ! 1052: for (i = 0; i < nelts; i++) ! 1053: { ! 1054: ptr -= size; ! 1055: (*dtor) (ptr, auto_delete); ! 1056: } ! 1057: ! 1058: if (auto_delete_vec) ! 1059: __builtin_delete (p); ! 1060: } ! 1061: ! 1062: #endif ! 1063: ! 1064: #ifdef L_shtab ! 1065: unsigned int __shtab[] = { ! 1066: 0x00000001, 0x00000002, 0x00000004, 0x00000008, ! 1067: 0x00000010, 0x00000020, 0x00000040, 0x00000080, ! 1068: 0x00000100, 0x00000200, 0x00000400, 0x00000800, ! 1069: 0x00001000, 0x00002000, 0x00004000, 0x00008000, ! 1070: 0x00010000, 0x00020000, 0x00040000, 0x00080000, ! 1071: 0x00100000, 0x00200000, 0x00400000, 0x00800000, ! 1072: 0x01000000, 0x02000000, 0x04000000, 0x08000000, ! 1073: 0x10000000, 0x20000000, 0x40000000, 0x80000000 ! 1074: }; ! 1075: #endif ! 1076: ! 1077: #ifdef L_clear_cache ! 1078: /* Clear part of an instruction cache. */ ! 1079: ! 1080: #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH) ! 1081: ! 1082: void ! 1083: __clear_cache (beg, end) ! 1084: char *beg, *end; ! 1085: { ! 1086: #ifdef INSN_CACHE_SIZE ! 1087: static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH]; ! 1088: static int initialized = 0; ! 1089: int offset; ! 1090: unsigned int start_addr, end_addr; ! 1091: typedef (*function_ptr) (); ! 1092: ! 1093: #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16 ! 1094: /* It's cheaper to clear the whole cache. ! 1095: Put in a series of jump instructions so that calling the beginning ! 1096: of the cache will clear the whole thing. */ ! 1097: ! 1098: if (! initialized) ! 1099: { ! 1100: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) ! 1101: & -INSN_CACHE_LINE_WIDTH); ! 1102: int end_ptr = ptr + INSN_CACHE_SIZE; ! 1103: ! 1104: while (ptr < end_ptr) ! 1105: { ! 1106: *(INSTRUCTION_TYPE *)ptr ! 1107: = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH; ! 1108: ptr += INSN_CACHE_LINE_WIDTH; ! 1109: } ! 1110: *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION; ! 1111: ! 1112: initialized = 1; ! 1113: } ! 1114: ! 1115: /* Call the beginning of the sequence. */ ! 1116: (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1) ! 1117: & -INSN_CACHE_LINE_WIDTH)) ! 1118: ()); ! 1119: ! 1120: #else /* Cache is large. */ ! 1121: ! 1122: if (! initialized) ! 1123: { ! 1124: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1) ! 1125: & -INSN_CACHE_LINE_WIDTH); ! 1126: ! 1127: while (ptr < (int) array + sizeof array) ! 1128: { ! 1129: *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION; ! 1130: ptr += INSN_CACHE_LINE_WIDTH; ! 1131: } ! 1132: ! 1133: initialized = 1; ! 1134: } ! 1135: ! 1136: /* Find the location in array that occupies the same cache line as BEG. */ ! 1137: ! 1138: offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1); ! 1139: start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1) ! 1140: & -INSN_CACHE_PLANE_SIZE) ! 1141: + offset); ! 1142: ! 1143: /* Compute the cache alignment of the place to stop clearing. */ ! 1144: #if 0 /* This is not needed for gcc's purposes. */ ! 1145: /* If the block to clear is bigger than a cache plane, ! 1146: we clear the entire cache, and OFFSET is already correct. */ ! 1147: if (end < beg + INSN_CACHE_PLANE_SIZE) ! 1148: #endif ! 1149: offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1) ! 1150: & -INSN_CACHE_LINE_WIDTH) ! 1151: & (INSN_CACHE_PLANE_SIZE - 1)); ! 1152: ! 1153: #if INSN_CACHE_DEPTH > 1 ! 1154: end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset; ! 1155: if (end_addr <= start_addr) ! 1156: end_addr += INSN_CACHE_PLANE_SIZE; ! 1157: ! 1158: for (plane = 0; plane < INSN_CACHE_DEPTH; plane++) ! 1159: { ! 1160: int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE; ! 1161: int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE; ! 1162: ! 1163: while (addr != stop) ! 1164: { ! 1165: /* Call the return instruction at ADDR. */ ! 1166: ((function_ptr) addr) (); ! 1167: ! 1168: addr += INSN_CACHE_LINE_WIDTH; ! 1169: } ! 1170: } ! 1171: #else /* just one plane */ ! 1172: do ! 1173: { ! 1174: /* Call the return instruction at START_ADDR. */ ! 1175: ((function_ptr) start_addr) (); ! 1176: ! 1177: start_addr += INSN_CACHE_LINE_WIDTH; ! 1178: } ! 1179: while ((start_addr % INSN_CACHE_SIZE) != offset); ! 1180: #endif /* just one plane */ ! 1181: #endif /* Cache is large */ ! 1182: #endif /* Cache exists */ ! 1183: } ! 1184: ! 1185: #endif /* L_clear_cache */ ! 1186: ! 1187: #ifdef L_trampoline ! 1188: ! 1189: /* Jump to a trampoline, loading the static chain address. */ ! 1190: ! 1191: #ifdef TRANSFER_FROM_TRAMPOLINE ! 1192: TRANSFER_FROM_TRAMPOLINE ! 1193: #endif ! 1194: ! 1195: #ifdef __convex__ ! 1196: ! 1197: /* Make stack executable so we can call trampolines on stack. ! 1198: This is called from INITIALIZE_TRAMPOLINE in convex.h. */ ! 1199: ! 1200: #include <sys/mman.h> ! 1201: #include <sys/vmparam.h> ! 1202: #include <machine/machparam.h> ! 1203: ! 1204: void ! 1205: __enable_execute_stack () ! 1206: { ! 1207: int fp; ! 1208: static unsigned lowest = USRSTACK; ! 1209: unsigned current = (unsigned) &fp & -NBPG; ! 1210: ! 1211: if (lowest > current) ! 1212: { ! 1213: unsigned len = lowest - current; ! 1214: mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); ! 1215: lowest = current; ! 1216: } ! 1217: ! 1218: /* Clear instruction cache in case an old trampoline is in it. */ ! 1219: asm ("pich"); ! 1220: } ! 1221: #endif /* __convex__ */ ! 1222: #endif /* L_trampoline */ ! 1223: ! 1224: #ifdef L__main ! 1225: ! 1226: #include "gbl-ctors.h" ! 1227: ! 1228: /* Run all the global destructors on exit from the program. */ ! 1229: ! 1230: void ! 1231: __do_global_dtors () ! 1232: { ! 1233: #ifdef DO_GLOBAL_DTORS_BODY ! 1234: DO_GLOBAL_DTORS_BODY; ! 1235: #else ! 1236: int nptrs = *(int *)__DTOR_LIST__; ! 1237: int i; ! 1238: ! 1239: /* Some systems place the number of pointers ! 1240: in the first word of the table. ! 1241: On other systems, that word is -1. ! 1242: In all cases, the table is null-terminated. */ ! 1243: ! 1244: /* If the length is not recorded, count up to the null. */ ! 1245: if (nptrs == -1) ! 1246: for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); ! 1247: ! 1248: /* GNU LD format. */ ! 1249: for (i = nptrs; i >= 1; i--) ! 1250: __DTOR_LIST__[i] (); ! 1251: #endif ! 1252: } ! 1253: ! 1254: #ifndef INIT_SECTION_ASM_OP ! 1255: /* Run all the global constructors on entry to the program. */ ! 1256: ! 1257: #ifndef ON_EXIT /* DO_GLOBAL_CTORS_BODY uses ON_EXIT */ ! 1258: #define ON_EXIT(a, b) ! 1259: #else ! 1260: /* Make sure the exit routine is pulled in to define the globals as ! 1261: bss symbols, just in case the linker does not automatically pull ! 1262: bss definitions from the library. */ ! 1263: ! 1264: extern int _exit_dummy_decl; ! 1265: int *_exit_dummy_ref = &_exit_dummy_decl; ! 1266: #endif /* ON_EXIT */ ! 1267: ! 1268: void ! 1269: __do_global_ctors () ! 1270: { ! 1271: DO_GLOBAL_CTORS_BODY; ! 1272: } ! 1273: ! 1274: /* Subroutine called automatically by `main'. ! 1275: Compiling a global function named `main' ! 1276: produces an automatic call to this function at the beginning. ! 1277: ! 1278: For many systems, this routine calls __do_global_ctors. ! 1279: For systems which support a .init section we use the .init section ! 1280: to run __do_global_ctors, so we need not do anything here. */ ! 1281: ! 1282: void ! 1283: __main () ! 1284: { ! 1285: /* Support recursive calls to `main': run initializers just once. */ ! 1286: static initialized = 0; ! 1287: if (! initialized) ! 1288: { ! 1289: initialized = 1; ! 1290: __do_global_ctors (); ! 1291: } ! 1292: } ! 1293: #endif /* no INIT_SECTION_ASM_OP */ ! 1294: ! 1295: #endif /* L__main */ ! 1296: ! 1297: #ifdef L_exit ! 1298: ! 1299: #include "gbl-ctors.h" ! 1300: ! 1301: /* Provide default definitions for the lists of constructors and ! 1302: destructors, so that we don't get linker errors. These symbols are ! 1303: intentionally bss symbols, so that gld and/or collect will provide ! 1304: the right values. */ ! 1305: ! 1306: /* We declare the lists here with two elements each, ! 1307: so that they are valid empty lists if no other definition is loaded. */ ! 1308: #ifndef INIT_SECTION_ASM_OP ! 1309: func_ptr __CTOR_LIST__[2]; ! 1310: func_ptr __DTOR_LIST__[2]; ! 1311: #endif /* INIT_SECTION_ASM_OP */ ! 1312: ! 1313: #ifndef ON_EXIT ! 1314: ! 1315: /* If we have no known way of registering our own __do_global_dtors ! 1316: routine so that it will be invoked at program exit time, then we ! 1317: have to define our own exit routine which will get this to happen. */ ! 1318: ! 1319: extern void __do_global_dtors (); ! 1320: extern void _cleanup (); ! 1321: extern void _exit (); ! 1322: ! 1323: void ! 1324: exit (status) ! 1325: int status; ! 1326: { ! 1327: __do_global_dtors (); ! 1328: #ifdef EXIT_BODY ! 1329: EXIT_BODY; ! 1330: #else ! 1331: _cleanup (); ! 1332: #endif ! 1333: _exit (status); ! 1334: } ! 1335: ! 1336: #else ! 1337: int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */ ! 1338: #endif ! 1339: ! 1340: #endif /* L_exit */ ! 1341: ! 1342: /* In a.out systems, we need to have these dummy constructor and destructor ! 1343: lists in the library. ! 1344: ! 1345: When using `collect', the first link will resolve __CTOR_LIST__ ! 1346: and __DTOR_LIST__ to these symbols. We will then run "nm" on the ! 1347: result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink. ! 1348: Since we don't do the second link if no constructors existed, these ! 1349: dummies must be fully functional empty lists. ! 1350: ! 1351: When using `gnu ld', these symbols will be used if there are no ! 1352: constructors. If there are constructors, the N_SETV symbol defined ! 1353: by the linker from the N_SETT's in input files will define __CTOR_LIST__ ! 1354: and __DTOR_LIST__ rather than its being allocated as common storage ! 1355: by the definitions below. ! 1356: ! 1357: When using a linker that supports constructor and destructor segments, ! 1358: these definitions will not be used, since crtbegin.o and crtend.o ! 1359: (from crtstuff.c) will have already defined __CTOR_LIST__ and ! 1360: __DTOR_LIST__. The crt*.o files are passed directly to the linker ! 1361: on its command line, by gcc. */ ! 1362: ! 1363: /* The list needs two elements: one is ignored (the old count); the ! 1364: second is the terminating zero. Since both values are zero, this ! 1365: declaration is not initialized, and it becomes `common'. */ ! 1366: ! 1367: #ifdef L_ctor_list ! 1368: #include "gbl-ctors.h" ! 1369: func_ptr __CTOR_LIST__[2]; ! 1370: #endif ! 1371: ! 1372: #ifdef L_dtor_list ! 1373: #include "gbl-ctors.h" ! 1374: func_ptr __DTOR_LIST__[2]; ! 1375: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.