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