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