|
|
1.1 ! root 1: /* Subroutines used for code generation on IBM RS/6000. ! 2: Copyright (C) 1991, 1993 Free Software Foundation, Inc. ! 3: Contributed by Richard Kenner ([email protected]) ! 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: #include <stdio.h> ! 22: #include "config.h" ! 23: #include "rtl.h" ! 24: #include "regs.h" ! 25: #include "hard-reg-set.h" ! 26: #include "real.h" ! 27: #include "insn-config.h" ! 28: #include "conditions.h" ! 29: #include "insn-flags.h" ! 30: #include "output.h" ! 31: #include "insn-attr.h" ! 32: #include "flags.h" ! 33: #include "recog.h" ! 34: #include "expr.h" ! 35: #include "obstack.h" ! 36: #include "tree.h" ! 37: ! 38: extern char *language_string; ! 39: ! 40: #define min(A,B) ((A) < (B) ? (A) : (B)) ! 41: #define max(A,B) ((A) > (B) ? (A) : (B)) ! 42: ! 43: /* Set to non-zero by "fix" operation to indicate that itrunc and ! 44: uitrunc must be defined. */ ! 45: ! 46: int rs6000_trunc_used; ! 47: ! 48: /* Set to non-zero once they have been defined. */ ! 49: ! 50: static int trunc_defined; ! 51: ! 52: /* Save information from a "cmpxx" operation until the branch or scc is ! 53: emitted. */ ! 54: ! 55: rtx rs6000_compare_op0, rs6000_compare_op1; ! 56: int rs6000_compare_fp_p; ! 57: ! 58: /* Return non-zero if this function is known to have a null epilogue. */ ! 59: ! 60: int ! 61: direct_return () ! 62: { ! 63: return (reload_completed ! 64: && first_reg_to_save () == 32 ! 65: && first_fp_reg_to_save () == 64 ! 66: && ! regs_ever_live[65] ! 67: && ! rs6000_pushes_stack ()); ! 68: } ! 69: ! 70: /* Returns 1 always. */ ! 71: ! 72: int ! 73: any_operand (op, mode) ! 74: register rtx op; ! 75: enum machine_mode mode; ! 76: { ! 77: return 1; ! 78: } ! 79: ! 80: /* Return 1 if OP is a constant that can fit in a D field. */ ! 81: ! 82: int ! 83: short_cint_operand (op, mode) ! 84: register rtx op; ! 85: enum machine_mode mode; ! 86: { ! 87: return (GET_CODE (op) == CONST_INT ! 88: && (unsigned) (INTVAL (op) + 0x8000) < 0x10000); ! 89: } ! 90: ! 91: /* Similar for a unsigned D field. */ ! 92: ! 93: int ! 94: u_short_cint_operand (op, mode) ! 95: register rtx op; ! 96: enum machine_mode mode; ! 97: { ! 98: return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0); ! 99: } ! 100: ! 101: /* Return 1 if OP is a CONST_INT that cannot fit in a signed D field. */ ! 102: ! 103: int ! 104: non_short_cint_operand (op, mode) ! 105: register rtx op; ! 106: enum machine_mode mode; ! 107: { ! 108: return (GET_CODE (op) == CONST_INT ! 109: && (unsigned) (INTVAL (op) + 0x8000) >= 0x10000); ! 110: } ! 111: ! 112: /* Returns 1 if OP is a register that is not special (i.e., not MQ, ! 113: ctr, or lr). */ ! 114: ! 115: int ! 116: gpc_reg_operand (op, mode) ! 117: register rtx op; ! 118: enum machine_mode mode; ! 119: { ! 120: return (register_operand (op, mode) ! 121: && (GET_CODE (op) != REG || REGNO (op) >= 67 || REGNO (op) < 64)); ! 122: } ! 123: ! 124: /* Returns 1 if OP is either a pseudo-register or a register denoting a ! 125: CR field. */ ! 126: ! 127: int ! 128: cc_reg_operand (op, mode) ! 129: register rtx op; ! 130: enum machine_mode mode; ! 131: { ! 132: return (register_operand (op, mode) ! 133: && (GET_CODE (op) != REG ! 134: || REGNO (op) >= FIRST_PSEUDO_REGISTER ! 135: || CR_REGNO_P (REGNO (op)))); ! 136: } ! 137: ! 138: /* Returns 1 if OP is either a constant integer valid for a D-field or a ! 139: non-special register. If a register, it must be in the proper mode unless ! 140: MODE is VOIDmode. */ ! 141: ! 142: int ! 143: reg_or_short_operand (op, mode) ! 144: register rtx op; ! 145: enum machine_mode mode; ! 146: { ! 147: if (GET_CODE (op) == CONST_INT) ! 148: return short_cint_operand (op, mode); ! 149: ! 150: return gpc_reg_operand (op, mode); ! 151: } ! 152: ! 153: /* Similar, except check if the negation of the constant would be valid for ! 154: a D-field. */ ! 155: ! 156: int ! 157: reg_or_neg_short_operand (op, mode) ! 158: register rtx op; ! 159: enum machine_mode mode; ! 160: { ! 161: if (GET_CODE (op) == CONST_INT) ! 162: return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'); ! 163: ! 164: return gpc_reg_operand (op, mode); ! 165: } ! 166: ! 167: /* Return 1 if the operand is either a register or an integer whose high-order ! 168: 16 bits are zero. */ ! 169: ! 170: int ! 171: reg_or_u_short_operand (op, mode) ! 172: register rtx op; ! 173: enum machine_mode mode; ! 174: { ! 175: if (GET_CODE (op) == CONST_INT ! 176: && (INTVAL (op) & 0xffff0000) == 0) ! 177: return 1; ! 178: ! 179: return gpc_reg_operand (op, mode); ! 180: } ! 181: ! 182: /* Return 1 is the operand is either a non-special register or ANY ! 183: constant integer. */ ! 184: ! 185: int ! 186: reg_or_cint_operand (op, mode) ! 187: register rtx op; ! 188: enum machine_mode mode; ! 189: { ! 190: return GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode); ! 191: } ! 192: ! 193: /* Return 1 if the operand is a CONST_DOUBLE and it can be put into a ! 194: register with one instruction per word. For SFmode, this means that ! 195: the low 16-bits are zero. For DFmode, it means the low 16-bits of ! 196: the first word are zero and the high 16 bits of the second word ! 197: are zero (usually all bits in the low-order word will be zero). ! 198: ! 199: We only do this if we can safely read CONST_DOUBLE_{LOW,HIGH}. */ ! 200: ! 201: int ! 202: easy_fp_constant (op, mode) ! 203: register rtx op; ! 204: register enum machine_mode mode; ! 205: { ! 206: rtx low, high; ! 207: ! 208: if (GET_CODE (op) != CONST_DOUBLE ! 209: || GET_MODE (op) != mode ! 210: || GET_MODE_CLASS (mode) != MODE_FLOAT) ! 211: return 0; ! 212: ! 213: high = operand_subword (op, 0, 0, mode); ! 214: low = operand_subword (op, 1, 0, mode); ! 215: ! 216: if (high == 0 || GET_CODE (high) != CONST_INT || (INTVAL (high) & 0xffff)) ! 217: return 0; ! 218: ! 219: return (mode == SFmode ! 220: || (low != 0 && GET_CODE (low) == CONST_INT ! 221: && (INTVAL (low) & 0xffff0000) == 0)); ! 222: } ! 223: ! 224: /* Return 1 if the operand is either a floating-point register, a pseudo ! 225: register, or memory. */ ! 226: ! 227: int ! 228: fp_reg_or_mem_operand (op, mode) ! 229: register rtx op; ! 230: enum machine_mode mode; ! 231: { ! 232: return (memory_operand (op, mode) ! 233: || (register_operand (op, mode) ! 234: && (GET_CODE (op) != REG ! 235: || REGNO (op) >= FIRST_PSEUDO_REGISTER ! 236: || FP_REGNO_P (REGNO (op))))); ! 237: } ! 238: ! 239: /* Return 1 if the operand is either an easy FP constant (see above) or ! 240: memory. */ ! 241: ! 242: int ! 243: mem_or_easy_const_operand (op, mode) ! 244: register rtx op; ! 245: enum machine_mode mode; ! 246: { ! 247: return memory_operand (op, mode) || easy_fp_constant (op, mode); ! 248: } ! 249: ! 250: /* Return 1 if the operand is either a non-special register or an item ! 251: that can be used as the operand of an SI add insn. */ ! 252: ! 253: int ! 254: add_operand (op, mode) ! 255: register rtx op; ! 256: enum machine_mode mode; ! 257: { ! 258: return (reg_or_short_operand (op, mode) ! 259: || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0)); ! 260: } ! 261: ! 262: /* Return 1 if OP is a constant but not a valid add_operand. */ ! 263: ! 264: int ! 265: non_add_cint_operand (op, mode) ! 266: register rtx op; ! 267: enum machine_mode mode; ! 268: { ! 269: return (GET_CODE (op) == CONST_INT ! 270: && (unsigned) (INTVAL (op) + 0x8000) >= 0x10000 ! 271: && (INTVAL (op) & 0xffff) != 0); ! 272: } ! 273: ! 274: /* Return 1 if the operand is a non-special register or a constant that ! 275: can be used as the operand of an OR or XOR insn on the RS/6000. */ ! 276: ! 277: int ! 278: logical_operand (op, mode) ! 279: register rtx op; ! 280: enum machine_mode mode; ! 281: { ! 282: return (gpc_reg_operand (op, mode) ! 283: || (GET_CODE (op) == CONST_INT ! 284: && ((INTVAL (op) & 0xffff0000) == 0 ! 285: || (INTVAL (op) & 0xffff) == 0))); ! 286: } ! 287: ! 288: /* Return 1 if C is a constant that is not a logical operand (as ! 289: above). */ ! 290: ! 291: int ! 292: non_logical_cint_operand (op, mode) ! 293: register rtx op; ! 294: enum machine_mode mode; ! 295: { ! 296: return (GET_CODE (op) == CONST_INT ! 297: && (INTVAL (op) & 0xffff0000) != 0 ! 298: && (INTVAL (op) & 0xffff) != 0); ! 299: } ! 300: ! 301: /* Return 1 if C is a constant that can be encoded in a mask on the ! 302: RS/6000. It is if there are no more than two 1->0 or 0->1 transitions. ! 303: Reject all ones and all zeros, since these should have been optimized ! 304: away and confuse the making of MB and ME. */ ! 305: ! 306: int ! 307: mask_constant (c) ! 308: register int c; ! 309: { ! 310: int i; ! 311: int last_bit_value; ! 312: int transitions = 0; ! 313: ! 314: if (c == 0 || c == ~0) ! 315: return 0; ! 316: ! 317: last_bit_value = c & 1; ! 318: ! 319: for (i = 1; i < 32; i++) ! 320: if (((c >>= 1) & 1) != last_bit_value) ! 321: last_bit_value ^= 1, transitions++; ! 322: ! 323: return transitions <= 2; ! 324: } ! 325: ! 326: /* Return 1 if the operand is a constant that is a mask on the RS/6000. */ ! 327: ! 328: int ! 329: mask_operand (op, mode) ! 330: register rtx op; ! 331: enum machine_mode mode; ! 332: { ! 333: return GET_CODE (op) == CONST_INT && mask_constant (INTVAL (op)); ! 334: } ! 335: ! 336: /* Return 1 if the operand is either a non-special register or a ! 337: constant that can be used as the operand of an RS/6000 logical AND insn. */ ! 338: ! 339: int ! 340: and_operand (op, mode) ! 341: register rtx op; ! 342: enum machine_mode mode; ! 343: { ! 344: return (reg_or_short_operand (op, mode) ! 345: || logical_operand (op, mode) ! 346: || mask_operand (op, mode)); ! 347: } ! 348: ! 349: /* Return 1 if the operand is a constant but not a valid operand for an AND ! 350: insn. */ ! 351: ! 352: int ! 353: non_and_cint_operand (op, mode) ! 354: register rtx op; ! 355: enum machine_mode mode; ! 356: { ! 357: return GET_CODE (op) == CONST_INT && ! and_operand (op, mode); ! 358: } ! 359: ! 360: /* Return 1 if the operand is a general register or memory operand. */ ! 361: ! 362: int ! 363: reg_or_mem_operand (op, mode) ! 364: register rtx op; ! 365: register enum machine_mode mode; ! 366: { ! 367: return gpc_reg_operand (op, mode) || memory_operand (op, mode); ! 368: } ! 369: ! 370: /* Return 1 if the operand, used inside a MEM, is a valid first argument ! 371: to CALL. This is a SYMBOL_REF or a pseudo-register, which will be ! 372: forced to lr. */ ! 373: ! 374: int ! 375: call_operand (op, mode) ! 376: register rtx op; ! 377: enum machine_mode mode; ! 378: { ! 379: if (mode != VOIDmode && GET_MODE (op) != mode) ! 380: return 0; ! 381: ! 382: return (GET_CODE (op) == SYMBOL_REF ! 383: || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)); ! 384: } ! 385: ! 386: /* Return 1 if this operand is a valid input for a move insn. */ ! 387: ! 388: int ! 389: input_operand (op, mode) ! 390: register rtx op; ! 391: enum machine_mode mode; ! 392: { ! 393: if (memory_operand (op, mode)) ! 394: return 1; ! 395: ! 396: /* For floating-point or multi-word mode, only register or memory ! 397: is valid. */ ! 398: if (GET_MODE_CLASS (mode) == MODE_FLOAT ! 399: || GET_MODE_SIZE (mode) > UNITS_PER_WORD) ! 400: return gpc_reg_operand (op, mode); ! 401: ! 402: /* The only cases left are integral modes one word or smaller (we ! 403: do not get called for MODE_CC values). These can be in any ! 404: register. */ ! 405: if (register_operand (op, mode)) ! 406: return; ! 407: ! 408: /* For HImode and QImode, any constant is valid. */ ! 409: if ((mode == HImode || mode == QImode) ! 410: && GET_CODE (op) == CONST_INT) ! 411: return 1; ! 412: ! 413: /* Otherwise, we will be doing this SET with an add, so anything valid ! 414: for an add will be valid. */ ! 415: return add_operand (op, mode); ! 416: } ! 417: ! 418: /* Return 1 if OP is a load multiple operation. It is known to be a ! 419: PARALLEL and the first section will be tested. */ ! 420: ! 421: int ! 422: load_multiple_operation (op, mode) ! 423: rtx op; ! 424: enum machine_mode mode; ! 425: { ! 426: int count = XVECLEN (op, 0); ! 427: int dest_regno; ! 428: rtx src_addr; ! 429: int i; ! 430: ! 431: /* Perform a quick check so we don't blow up below. */ ! 432: if (count <= 1 ! 433: || GET_CODE (XVECEXP (op, 0, 0)) != SET ! 434: || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG ! 435: || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) ! 436: return 0; ! 437: ! 438: dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); ! 439: src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); ! 440: ! 441: for (i = 1; i < count; i++) ! 442: { ! 443: rtx elt = XVECEXP (op, 0, i); ! 444: ! 445: if (GET_CODE (elt) != SET ! 446: || GET_CODE (SET_DEST (elt)) != REG ! 447: || GET_MODE (SET_DEST (elt)) != SImode ! 448: || REGNO (SET_DEST (elt)) != dest_regno + i ! 449: || GET_CODE (SET_SRC (elt)) != MEM ! 450: || GET_MODE (SET_SRC (elt)) != SImode ! 451: || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS ! 452: || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) ! 453: || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT ! 454: || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4) ! 455: return 0; ! 456: } ! 457: ! 458: return 1; ! 459: } ! 460: ! 461: /* Similar, but tests for store multiple. Here, the second vector element ! 462: is a CLOBBER. It will be tested later. */ ! 463: ! 464: int ! 465: store_multiple_operation (op, mode) ! 466: rtx op; ! 467: enum machine_mode mode; ! 468: { ! 469: int count = XVECLEN (op, 0) - 1; ! 470: int src_regno; ! 471: rtx dest_addr; ! 472: int i; ! 473: ! 474: /* Perform a quick check so we don't blow up below. */ ! 475: if (count <= 1 ! 476: || GET_CODE (XVECEXP (op, 0, 0)) != SET ! 477: || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM ! 478: || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) ! 479: return 0; ! 480: ! 481: src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); ! 482: dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); ! 483: ! 484: for (i = 1; i < count; i++) ! 485: { ! 486: rtx elt = XVECEXP (op, 0, i + 1); ! 487: ! 488: if (GET_CODE (elt) != SET ! 489: || GET_CODE (SET_SRC (elt)) != REG ! 490: || GET_MODE (SET_SRC (elt)) != SImode ! 491: || REGNO (SET_SRC (elt)) != src_regno + i ! 492: || GET_CODE (SET_DEST (elt)) != MEM ! 493: || GET_MODE (SET_DEST (elt)) != SImode ! 494: || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS ! 495: || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) ! 496: || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT ! 497: || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4) ! 498: return 0; ! 499: } ! 500: ! 501: return 1; ! 502: } ! 503: ! 504: /* Return 1 if OP is a comparison operation that is valid for a branch insn. ! 505: We only check the opcode against the mode of the CC value here. */ ! 506: ! 507: int ! 508: branch_comparison_operator (op, mode) ! 509: register rtx op; ! 510: enum machine_mode mode; ! 511: { ! 512: enum rtx_code code = GET_CODE (op); ! 513: enum machine_mode cc_mode; ! 514: ! 515: if (GET_RTX_CLASS (code) != '<') ! 516: return 0; ! 517: ! 518: cc_mode = GET_MODE (XEXP (op, 0)); ! 519: if (GET_MODE_CLASS (cc_mode) != MODE_CC) ! 520: return 0; ! 521: ! 522: if ((code == GT || code == LT || code == GE || code == LE) ! 523: && cc_mode == CCUNSmode) ! 524: return 0; ! 525: ! 526: if ((code == GTU || code == LTU || code == GEU || code == LEU) ! 527: && (cc_mode != CCUNSmode)) ! 528: return 0; ! 529: ! 530: return 1; ! 531: } ! 532: ! 533: /* Return 1 if OP is a comparison operation that is valid for an scc insn. ! 534: We check the opcode against the mode of the CC value and disallow EQ or ! 535: NE comparisons for integers. */ ! 536: ! 537: int ! 538: scc_comparison_operator (op, mode) ! 539: register rtx op; ! 540: enum machine_mode mode; ! 541: { ! 542: enum rtx_code code = GET_CODE (op); ! 543: enum machine_mode cc_mode; ! 544: ! 545: if (GET_MODE (op) != mode && mode != VOIDmode) ! 546: return 0; ! 547: ! 548: if (GET_RTX_CLASS (code) != '<') ! 549: return 0; ! 550: ! 551: cc_mode = GET_MODE (XEXP (op, 0)); ! 552: if (GET_MODE_CLASS (cc_mode) != MODE_CC) ! 553: return 0; ! 554: ! 555: if (code == NE && cc_mode != CCFPmode) ! 556: return 0; ! 557: ! 558: if ((code == GT || code == LT || code == GE || code == LE) ! 559: && cc_mode == CCUNSmode) ! 560: return 0; ! 561: ! 562: if ((code == GTU || code == LTU || code == GEU || code == LEU) ! 563: && (cc_mode != CCUNSmode)) ! 564: return 0; ! 565: ! 566: if (cc_mode == CCEQmode && code != EQ && code != NE) ! 567: return 0; ! 568: ! 569: return 1; ! 570: } ! 571: ! 572: /* Return 1 if ANDOP is a mask that has no bits on that are not in the ! 573: mask required to convert the result of a rotate insn into a shift ! 574: left insn of SHIFTOP bits. Both are known to be CONST_INT. */ ! 575: ! 576: int ! 577: includes_lshift_p (shiftop, andop) ! 578: register rtx shiftop; ! 579: register rtx andop; ! 580: { ! 581: int shift_mask = (~0 << INTVAL (shiftop)); ! 582: ! 583: return (INTVAL (andop) & ~shift_mask) == 0; ! 584: } ! 585: ! 586: /* Similar, but for right shift. */ ! 587: ! 588: int ! 589: includes_rshift_p (shiftop, andop) ! 590: register rtx shiftop; ! 591: register rtx andop; ! 592: { ! 593: unsigned shift_mask = ~0; ! 594: ! 595: shift_mask >>= INTVAL (shiftop); ! 596: ! 597: return (INTVAL (andop) & ~ shift_mask) == 0; ! 598: } ! 599: ! 600: /* Return the register class of a scratch register needed to copy IN into ! 601: or out of a register in CLASS in MODE. If it can be done directly, ! 602: NO_REGS is returned. */ ! 603: ! 604: enum reg_class ! 605: secondary_reload_class (class, mode, in) ! 606: enum reg_class class; ! 607: enum machine_mode mode; ! 608: rtx in; ! 609: { ! 610: int regno = true_regnum (in); ! 611: ! 612: if (regno >= FIRST_PSEUDO_REGISTER) ! 613: regno = -1; ! 614: ! 615: /* We can place anything into GENERAL_REGS and can put GENERAL_REGS ! 616: into anything. */ ! 617: if (class == GENERAL_REGS || class == BASE_REGS ! 618: || (regno >= 0 && INT_REGNO_P (regno))) ! 619: return NO_REGS; ! 620: ! 621: /* Constants, memory, and FP registers can go into FP registers. */ ! 622: if ((regno == -1 || FP_REGNO_P (regno)) ! 623: && (class == FLOAT_REGS || class == NON_SPECIAL_REGS)) ! 624: return NO_REGS; ! 625: ! 626: /* We can copy among the CR registers. */ ! 627: if ((class == CR_REGS || class == CR0_REGS) ! 628: && regno >= 0 && CR_REGNO_P (regno)) ! 629: return NO_REGS; ! 630: ! 631: /* Otherwise, we need GENERAL_REGS. */ ! 632: return GENERAL_REGS; ! 633: } ! 634: ! 635: /* Given a comparison operation, return the bit number in CCR to test. We ! 636: know this is a valid comparison. ! 637: ! 638: SCC_P is 1 if this is for an scc. That means that %D will have been ! 639: used instead of %C, so the bits will be in different places. ! 640: ! 641: Return -1 if OP isn't a valid comparison for some reason. */ ! 642: ! 643: int ! 644: ccr_bit (op, scc_p) ! 645: register rtx op; ! 646: int scc_p; ! 647: { ! 648: enum rtx_code code = GET_CODE (op); ! 649: enum machine_mode cc_mode; ! 650: int cc_regnum; ! 651: int base_bit; ! 652: ! 653: if (GET_RTX_CLASS (code) != '<') ! 654: return -1; ! 655: ! 656: cc_mode = GET_MODE (XEXP (op, 0)); ! 657: cc_regnum = REGNO (XEXP (op, 0)); ! 658: base_bit = 4 * (cc_regnum - 68); ! 659: ! 660: /* In CCEQmode cases we have made sure that the result is always in the ! 661: third bit of the CR field. */ ! 662: ! 663: if (cc_mode == CCEQmode) ! 664: return base_bit + 3; ! 665: ! 666: switch (code) ! 667: { ! 668: case NE: ! 669: return scc_p ? base_bit + 3 : base_bit + 2; ! 670: case EQ: ! 671: return base_bit + 2; ! 672: case GT: case GTU: ! 673: return base_bit + 1; ! 674: case LT: case LTU: ! 675: return base_bit; ! 676: ! 677: case GE: case GEU: ! 678: /* If floating-point, we will have done a cror to put the bit in the ! 679: unordered position. So test that bit. For integer, this is ! LT ! 680: unless this is an scc insn. */ ! 681: return cc_mode == CCFPmode || scc_p ? base_bit + 3 : base_bit; ! 682: ! 683: case LE: case LEU: ! 684: return cc_mode == CCFPmode || scc_p ? base_bit + 3 : base_bit + 1; ! 685: ! 686: default: ! 687: abort (); ! 688: } ! 689: } ! 690: ! 691: /* Print an operand. Recognize special options, documented below. */ ! 692: ! 693: void ! 694: print_operand (file, x, code) ! 695: FILE *file; ! 696: rtx x; ! 697: char code; ! 698: { ! 699: int i; ! 700: int val; ! 701: ! 702: /* These macros test for integers and extract the low-order bits. */ ! 703: #define INT_P(X) \ ! 704: ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \ ! 705: && GET_MODE (X) == VOIDmode) ! 706: ! 707: #define INT_LOWPART(X) \ ! 708: (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X)) ! 709: ! 710: switch (code) ! 711: { ! 712: case 'A': ! 713: /* If X is a constant integer whose low-order 5 bits are zero, ! 714: write 'l'. Otherwise, write 'r'. This is a kludge to fix a bug ! 715: in the RS/6000 assembler where "sri" with a zero shift count ! 716: write a trash instruction. */ ! 717: if (GET_CODE (x) == CONST_INT && (INTVAL (x) & 31) == 0) ! 718: fprintf (file, "l"); ! 719: else ! 720: fprintf (file, "r"); ! 721: return; ! 722: ! 723: case 'b': ! 724: /* Low-order 16 bits of constant, unsigned. */ ! 725: if (! INT_P (x)) ! 726: output_operand_lossage ("invalid %%b value"); ! 727: ! 728: fprintf (file, "%d", INT_LOWPART (x) & 0xffff); ! 729: return; ! 730: ! 731: case 'C': ! 732: /* This is an optional cror needed for LE or GE floating-point ! 733: comparisons. Otherwise write nothing. */ ! 734: if ((GET_CODE (x) == LE || GET_CODE (x) == GE) ! 735: && GET_MODE (XEXP (x, 0)) == CCFPmode) ! 736: { ! 737: int base_bit = 4 * (REGNO (XEXP (x, 0)) - 68); ! 738: ! 739: fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3, ! 740: base_bit + 2, base_bit + (GET_CODE (x) == GE)); ! 741: } ! 742: return; ! 743: ! 744: case 'D': ! 745: /* Similar, except that this is for an scc, so we must be able to ! 746: encode the test in a single bit that is one. We do the above ! 747: for any LE, GE, GEU, or LEU and invert the bit for NE. */ ! 748: if (GET_CODE (x) == LE || GET_CODE (x) == GE ! 749: || GET_CODE (x) == LEU || GET_CODE (x) == GEU) ! 750: { ! 751: int base_bit = 4 * (REGNO (XEXP (x, 0)) - 68); ! 752: ! 753: fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3, ! 754: base_bit + 2, ! 755: base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU)); ! 756: } ! 757: ! 758: else if (GET_CODE (x) == NE) ! 759: { ! 760: int base_bit = 4 * (REGNO (XEXP (x, 0)) - 68); ! 761: ! 762: fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3, ! 763: base_bit + 2, base_bit + 2); ! 764: } ! 765: return; ! 766: ! 767: case 'E': ! 768: /* X is a CR register. Print the number of the third bit of the CR */ ! 769: if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) ! 770: output_operand_lossage ("invalid %%E value"); ! 771: ! 772: fprintf(file, "%d", 4 * (REGNO (x) - 68) + 3); ! 773: break; ! 774: ! 775: case 'f': ! 776: /* X is a CR register. Print the shift count needed to move it ! 777: to the high-order four bits. */ ! 778: if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) ! 779: output_operand_lossage ("invalid %%f value"); ! 780: else ! 781: fprintf (file, "%d", 4 * (REGNO (x) - 68)); ! 782: return; ! 783: ! 784: case 'F': ! 785: /* Similar, but print the count for the rotate in the opposite ! 786: direction. */ ! 787: if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) ! 788: output_operand_lossage ("invalid %%F value"); ! 789: else ! 790: fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68)); ! 791: return; ! 792: ! 793: case 'G': ! 794: /* X is a constant integer. If it is negative, print "m", ! 795: otherwise print "z". This is to make a aze or ame insn. */ ! 796: if (GET_CODE (x) != CONST_INT) ! 797: output_operand_lossage ("invalid %%G value"); ! 798: else if (INTVAL (x) >= 0) ! 799: fprintf (file, "z"); ! 800: else ! 801: fprintf (file, "m"); ! 802: return; ! 803: ! 804: case 'h': ! 805: /* If constant, output low-order five bits. Otherwise, ! 806: write normally. */ ! 807: if (INT_P (x)) ! 808: fprintf (file, "%d", INT_LOWPART (x) & 31); ! 809: else ! 810: print_operand (file, x, 0); ! 811: return; ! 812: ! 813: case 'H': ! 814: /* X must be a constant. Output the low order 5 bits plus 24. */ ! 815: if (! INT_P (x)) ! 816: output_operand_lossage ("invalid %%H value"); ! 817: ! 818: fprintf (file, "%d", (INT_LOWPART (x) + 24) & 31); ! 819: return; ! 820: ! 821: case 'I': ! 822: /* Print `i' if this is a constant, else nothing. */ ! 823: if (INT_P (x)) ! 824: fprintf (file, "i"); ! 825: return; ! 826: ! 827: case 'j': ! 828: /* Write the bit number in CCR for jump. */ ! 829: i = ccr_bit (x, 0); ! 830: if (i == -1) ! 831: output_operand_lossage ("invalid %%j code"); ! 832: else ! 833: fprintf (file, "%d", i); ! 834: return; ! 835: ! 836: case 'J': ! 837: /* Similar, but add one for shift count in rlinm for scc and pass ! 838: scc flag to `ccr_bit'. */ ! 839: i = ccr_bit (x, 1); ! 840: if (i == -1) ! 841: output_operand_lossage ("invalid %%J code"); ! 842: else ! 843: fprintf (file, "%d", i + 1); ! 844: return; ! 845: ! 846: case 'k': ! 847: /* X must be a constant. Write the 1's complement of the ! 848: constant. */ ! 849: if (! INT_P (x)) ! 850: output_operand_lossage ("invalid %%k value"); ! 851: ! 852: fprintf (file, "%d", ~ INT_LOWPART (x)); ! 853: return; ! 854: ! 855: case 'L': ! 856: /* Write second word of DImode or DFmode reference. Works on register ! 857: or non-indexed memory only. */ ! 858: if (GET_CODE (x) == REG) ! 859: fprintf (file, "%d", REGNO (x) + 1); ! 860: else if (GET_CODE (x) == MEM) ! 861: { ! 862: /* Handle possible auto-increment. Since it is pre-increment and ! 863: we have already done it, we can just use an offset of four. */ ! 864: if (GET_CODE (XEXP (x, 0)) == PRE_INC ! 865: || GET_CODE (XEXP (x, 0)) == PRE_DEC) ! 866: output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4)); ! 867: else ! 868: output_address (plus_constant (XEXP (x, 0), 4)); ! 869: } ! 870: return; ! 871: ! 872: case 'm': ! 873: /* MB value for a mask operand. */ ! 874: if (! mask_operand (x, VOIDmode)) ! 875: output_operand_lossage ("invalid %%m value"); ! 876: ! 877: val = INT_LOWPART (x); ! 878: ! 879: /* If the high bit is set and the low bit is not, the value is zero. ! 880: If the high bit is zero, the value is the first 1 bit we find from ! 881: the left. */ ! 882: if (val < 0 && (val & 1) == 0) ! 883: { ! 884: fprintf (file, "0"); ! 885: return; ! 886: } ! 887: else if (val >= 0) ! 888: { ! 889: for (i = 1; i < 32; i++) ! 890: if ((val <<= 1) < 0) ! 891: break; ! 892: fprintf (file, "%d", i); ! 893: return; ! 894: } ! 895: ! 896: /* Otherwise, look for the first 0 bit from the right. The result is its ! 897: number plus 1. We know the low-order bit is one. */ ! 898: for (i = 0; i < 32; i++) ! 899: if (((val >>= 1) & 1) == 0) ! 900: break; ! 901: ! 902: /* If we ended in ...01, I would be 0. The correct value is 31, so ! 903: we want 31 - i. */ ! 904: fprintf (file, "%d", 31 - i); ! 905: return; ! 906: ! 907: case 'M': ! 908: /* ME value for a mask operand. */ ! 909: if (! mask_operand (x, VOIDmode)) ! 910: output_operand_lossage ("invalid %%m value"); ! 911: ! 912: val = INT_LOWPART (x); ! 913: ! 914: /* If the low bit is set and the high bit is not, the value is 31. ! 915: If the low bit is zero, the value is the first 1 bit we find from ! 916: the right. */ ! 917: if ((val & 1) && val >= 0) ! 918: { ! 919: fprintf (file, "31"); ! 920: return; ! 921: } ! 922: else if ((val & 1) == 0) ! 923: { ! 924: for (i = 0; i < 32; i++) ! 925: if ((val >>= 1) & 1) ! 926: break; ! 927: ! 928: /* If we had ....10, I would be 0. The result should be ! 929: 30, so we need 30 - i. */ ! 930: fprintf (file, "%d", 30 - i); ! 931: return; ! 932: } ! 933: ! 934: /* Otherwise, look for the first 0 bit from the left. The result is its ! 935: number minus 1. We know the high-order bit is one. */ ! 936: for (i = 0; i < 32; i++) ! 937: if ((val <<= 1) >= 0) ! 938: break; ! 939: ! 940: fprintf (file, "%d", i); ! 941: return; ! 942: ! 943: case 'N': ! 944: /* Write the number of elements in the vector times 4. */ ! 945: if (GET_CODE (x) != PARALLEL) ! 946: output_operand_lossage ("invalid %%N value"); ! 947: ! 948: fprintf (file, "%d", XVECLEN (x, 0) * 4); ! 949: return; ! 950: ! 951: case 'O': ! 952: /* Similar, but subtract 1 first. */ ! 953: if (GET_CODE (x) != PARALLEL) ! 954: output_operand_lossage ("invalid %%N value"); ! 955: ! 956: fprintf (file, "%d", (XVECLEN (x, 0) - 1) * 4); ! 957: return; ! 958: ! 959: case 'p': ! 960: /* X is a CONST_INT that is a power of two. Output the logarithm. */ ! 961: if (! INT_P (x) ! 962: || (i = exact_log2 (INT_LOWPART (x))) < 0) ! 963: output_operand_lossage ("invalid %%p value"); ! 964: ! 965: fprintf (file, "%d", i); ! 966: return; ! 967: ! 968: case 'P': ! 969: /* The operand must be an indirect memory reference. The result ! 970: is the register number. */ ! 971: if (GET_CODE (x) != MEM || GET_CODE (XEXP (x, 0)) != REG ! 972: || REGNO (XEXP (x, 0)) >= 32) ! 973: output_operand_lossage ("invalid %%P value"); ! 974: ! 975: fprintf (file, "%d", REGNO (XEXP (x, 0))); ! 976: return; ! 977: ! 978: case 'R': ! 979: /* X is a CR register. Print the mask for `mtcrf'. */ ! 980: if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) ! 981: output_operand_lossage ("invalid %%R value"); ! 982: else ! 983: fprintf (file, "%d", 128 >> (REGNO (x) - 68)); ! 984: return; ! 985: ! 986: case 's': ! 987: /* Low 5 bits of 32 - value */ ! 988: if (! INT_P (x)) ! 989: output_operand_lossage ("invalid %%s value"); ! 990: ! 991: fprintf (file, "%d", (32 - INT_LOWPART (x)) & 31); ! 992: return; ! 993: ! 994: case 'S': ! 995: /* Low 5 bits of 31 - value */ ! 996: if (! INT_P (x)) ! 997: output_operand_lossage ("invalid %%S value"); ! 998: ! 999: fprintf (file, "%d", (31 - INT_LOWPART (x)) & 31); ! 1000: return; ! 1001: ! 1002: case 't': ! 1003: /* Write 12 if this jump operation will branch if true, 4 otherwise. ! 1004: All floating-point operations except NE branch true and integer ! 1005: EQ, LT, GT, LTU and GTU also branch true. */ ! 1006: if (GET_RTX_CLASS (GET_CODE (x)) != '<') ! 1007: output_operand_lossage ("invalid %%t value"); ! 1008: ! 1009: else if ((GET_MODE (XEXP (x, 0)) == CCFPmode ! 1010: && GET_CODE (x) != NE) ! 1011: || GET_CODE (x) == EQ ! 1012: || GET_CODE (x) == LT || GET_CODE (x) == GT ! 1013: || GET_CODE (x) == LTU || GET_CODE (x) == GTU) ! 1014: fprintf (file, "12"); ! 1015: else ! 1016: fprintf (file, "4"); ! 1017: return; ! 1018: ! 1019: case 'T': ! 1020: /* Opposite of 't': write 4 if this jump operation will branch if true, ! 1021: 12 otherwise. */ ! 1022: if (GET_RTX_CLASS (GET_CODE (x)) != '<') ! 1023: output_operand_lossage ("invalid %%t value"); ! 1024: ! 1025: else if ((GET_MODE (XEXP (x, 0)) == CCFPmode ! 1026: && GET_CODE (x) != NE) ! 1027: || GET_CODE (x) == EQ ! 1028: || GET_CODE (x) == LT || GET_CODE (x) == GT ! 1029: || GET_CODE (x) == LTU || GET_CODE (x) == GTU) ! 1030: fprintf (file, "4"); ! 1031: else ! 1032: fprintf (file, "12"); ! 1033: return; ! 1034: ! 1035: case 'u': ! 1036: /* High-order 16 bits of constant. */ ! 1037: if (! INT_P (x)) ! 1038: output_operand_lossage ("invalid %%u value"); ! 1039: ! 1040: fprintf (file, "%d", (INT_LOWPART (x) >> 16) & 0xffff); ! 1041: return; ! 1042: ! 1043: case 'U': ! 1044: /* Print `u' if this has an auto-increment or auto-decrement. */ ! 1045: if (GET_CODE (x) == MEM ! 1046: && (GET_CODE (XEXP (x, 0)) == PRE_INC ! 1047: || GET_CODE (XEXP (x, 0)) == PRE_DEC)) ! 1048: fprintf (file, "u"); ! 1049: return; ! 1050: ! 1051: case 'w': ! 1052: /* If constant, low-order 16 bits of constant, signed. Otherwise, write ! 1053: normally. */ ! 1054: if (INT_P (x)) ! 1055: fprintf (file, "%d", ! 1056: (INT_LOWPART (x) & 0xffff) - 2 * (INT_LOWPART (x) & 0x8000)); ! 1057: else ! 1058: print_operand (file, x, 0); ! 1059: return; ! 1060: ! 1061: case 'W': ! 1062: /* If constant, low-order 16 bits of constant, unsigned. ! 1063: Otherwise, write normally. */ ! 1064: if (INT_P (x)) ! 1065: fprintf (file, "%d", INT_LOWPART (x) & 0xffff); ! 1066: else ! 1067: print_operand (file, x, 0); ! 1068: return; ! 1069: ! 1070: case 'X': ! 1071: if (GET_CODE (x) == MEM ! 1072: && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0))) ! 1073: fprintf (file, "x"); ! 1074: return; ! 1075: ! 1076: case 'Y': ! 1077: /* Like 'L', for third word of TImode */ ! 1078: if (GET_CODE (x) == REG) ! 1079: fprintf (file, "%d", REGNO (x) + 2); ! 1080: else if (GET_CODE (x) == MEM) ! 1081: { ! 1082: if (GET_CODE (XEXP (x, 0)) == PRE_INC ! 1083: || GET_CODE (XEXP (x, 0)) == PRE_DEC) ! 1084: output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8)); ! 1085: else ! 1086: output_address (plus_constant (XEXP (x, 0), 8)); ! 1087: } ! 1088: return; ! 1089: ! 1090: case 'z': ! 1091: /* X is a SYMBOL_REF. Write out the name preceded by a ! 1092: period and without any trailing data in brackets. Used for function ! 1093: names. */ ! 1094: if (GET_CODE (x) != SYMBOL_REF) ! 1095: abort (); ! 1096: ! 1097: fprintf (file, "."); ! 1098: RS6000_OUTPUT_BASENAME (file, XSTR (x, 0)); ! 1099: return; ! 1100: ! 1101: case 'Z': ! 1102: /* Like 'L', for last word of TImode. */ ! 1103: if (GET_CODE (x) == REG) ! 1104: fprintf (file, "%d", REGNO (x) + 3); ! 1105: else if (GET_CODE (x) == MEM) ! 1106: { ! 1107: if (GET_CODE (XEXP (x, 0)) == PRE_INC ! 1108: || GET_CODE (XEXP (x, 0)) == PRE_DEC) ! 1109: output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12)); ! 1110: else ! 1111: output_address (plus_constant (XEXP (x, 0), 12)); ! 1112: } ! 1113: return; ! 1114: ! 1115: case 0: ! 1116: if (GET_CODE (x) == REG) ! 1117: fprintf (file, "%s", reg_names[REGNO (x)]); ! 1118: else if (GET_CODE (x) == MEM) ! 1119: { ! 1120: /* We need to handle PRE_INC and PRE_DEC here, since we need to ! 1121: know the width from the mode. */ ! 1122: if (GET_CODE (XEXP (x, 0)) == PRE_INC) ! 1123: fprintf (file, "%d(%d)", GET_MODE_SIZE (GET_MODE (x)), ! 1124: REGNO (XEXP (XEXP (x, 0), 0))); ! 1125: else if (GET_CODE (XEXP (x, 0)) == PRE_DEC) ! 1126: fprintf (file, "%d(%d)", - GET_MODE_SIZE (GET_MODE (x)), ! 1127: REGNO (XEXP (XEXP (x, 0), 0))); ! 1128: else ! 1129: output_address (XEXP (x, 0)); ! 1130: } ! 1131: else ! 1132: output_addr_const (file, x); ! 1133: break; ! 1134: ! 1135: default: ! 1136: output_operand_lossage ("invalid %%xn code"); ! 1137: } ! 1138: } ! 1139: ! 1140: /* Print the address of an operand. */ ! 1141: ! 1142: void ! 1143: print_operand_address (file, x) ! 1144: FILE *file; ! 1145: register rtx x; ! 1146: { ! 1147: if (GET_CODE (x) == REG) ! 1148: fprintf (file, "0(%d)", REGNO (x)); ! 1149: else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST) ! 1150: { ! 1151: output_addr_const (file, x); ! 1152: fprintf (file, "(2)"); ! 1153: } ! 1154: else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG) ! 1155: { ! 1156: if (REGNO (XEXP (x, 0)) == 0) ! 1157: fprintf (file, "%d,%d", REGNO (XEXP (x, 1)), REGNO (XEXP (x, 0))); ! 1158: else ! 1159: fprintf (file, "%d,%d", REGNO (XEXP (x, 0)), REGNO (XEXP (x, 1))); ! 1160: } ! 1161: else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) ! 1162: fprintf (file, "%d(%d)", INTVAL (XEXP (x, 1)), REGNO (XEXP (x, 0))); ! 1163: else ! 1164: abort (); ! 1165: } ! 1166: ! 1167: /* This page contains routines that are used to determine what the function ! 1168: prologue and epilogue code will do and write them out. */ ! 1169: ! 1170: /* Return the first fixed-point register that is required to be saved. 32 if ! 1171: none. */ ! 1172: ! 1173: int ! 1174: first_reg_to_save () ! 1175: { ! 1176: int first_reg; ! 1177: ! 1178: /* Find lowest numbered live register. */ ! 1179: for (first_reg = 13; first_reg <= 31; first_reg++) ! 1180: if (regs_ever_live[first_reg]) ! 1181: break; ! 1182: ! 1183: /* If profiling, then we must save/restore every register that contains ! 1184: a parameter before/after the .mcount call. Use registers from 30 down ! 1185: to 23 to do this. Don't use the frame pointer in reg 31. ! 1186: ! 1187: For now, save enough room for all of the parameter registers. */ ! 1188: if (profile_flag) ! 1189: if (first_reg > 23) ! 1190: first_reg = 23; ! 1191: ! 1192: return first_reg; ! 1193: } ! 1194: ! 1195: /* Similar, for FP regs. */ ! 1196: ! 1197: int ! 1198: first_fp_reg_to_save () ! 1199: { ! 1200: int first_reg; ! 1201: ! 1202: /* Find lowest numbered live register. */ ! 1203: for (first_reg = 14 + 32; first_reg <= 63; first_reg++) ! 1204: if (regs_ever_live[first_reg]) ! 1205: break; ! 1206: ! 1207: return first_reg; ! 1208: } ! 1209: ! 1210: /* Return 1 if we need to save CR. */ ! 1211: ! 1212: int ! 1213: must_save_cr () ! 1214: { ! 1215: return regs_ever_live[70] || regs_ever_live[71] || regs_ever_live[72]; ! 1216: } ! 1217: ! 1218: /* Compute the size of the save area in the stack, including the space for ! 1219: the fixed area. */ ! 1220: ! 1221: int ! 1222: rs6000_sa_size () ! 1223: { ! 1224: int size; ! 1225: int i; ! 1226: ! 1227: /* We have the six fixed words, plus the size of the register save ! 1228: areas, rounded to a double-word. */ ! 1229: size = 6 + (32 - first_reg_to_save ()) + (64 - first_fp_reg_to_save ()) * 2; ! 1230: if (size & 1) ! 1231: size++; ! 1232: ! 1233: return size * 4; ! 1234: } ! 1235: ! 1236: /* Return non-zero if this function makes calls. */ ! 1237: ! 1238: int ! 1239: rs6000_makes_calls () ! 1240: { ! 1241: rtx insn; ! 1242: ! 1243: /* If we are profiling, we will be making a call to mcount. */ ! 1244: if (profile_flag) ! 1245: return 1; ! 1246: ! 1247: for (insn = get_insns (); insn; insn = next_insn (insn)) ! 1248: if (GET_CODE (insn) == CALL_INSN) ! 1249: return 1; ! 1250: ! 1251: return 0; ! 1252: } ! 1253: ! 1254: /* Return non-zero if this function needs to push space on the stack. */ ! 1255: ! 1256: int ! 1257: rs6000_pushes_stack () ! 1258: { ! 1259: int total_size = (rs6000_sa_size () + get_frame_size () ! 1260: + current_function_outgoing_args_size); ! 1261: ! 1262: /* We need to push the stack if a frame pointer is needed (because the ! 1263: stack might be dynamically adjusted), if we are debugging, if the ! 1264: total stack size is more than 220 bytes, or if we make calls. */ ! 1265: ! 1266: return (frame_pointer_needed || write_symbols != NO_DEBUG ! 1267: || total_size > 220 ! 1268: || rs6000_makes_calls ()); ! 1269: } ! 1270: ! 1271: /* Write function prologue. */ ! 1272: ! 1273: void ! 1274: output_prolog (file, size) ! 1275: FILE *file; ! 1276: int size; ! 1277: { ! 1278: int first_reg = first_reg_to_save (); ! 1279: int must_push = rs6000_pushes_stack (); ! 1280: int first_fp_reg = first_fp_reg_to_save (); ! 1281: int basic_size = rs6000_sa_size (); ! 1282: int total_size = (basic_size + size + current_function_outgoing_args_size); ! 1283: ! 1284: /* Round size to multiple of 8 bytes. */ ! 1285: total_size = (total_size + 7) & ~7; ! 1286: ! 1287: /* Write .extern for any function we will call to save and restore fp ! 1288: values. */ ! 1289: if (first_fp_reg < 62) ! 1290: fprintf (file, "\t.extern ._savef%d\n\t.extern ._restf%d\n", ! 1291: first_fp_reg - 32, first_fp_reg - 32); ! 1292: ! 1293: /* Write .extern for truncation routines, if needed. */ ! 1294: if (rs6000_trunc_used && ! trunc_defined) ! 1295: { ! 1296: fprintf (file, "\t.extern .itrunc\n\t.extern .uitrunc\n"); ! 1297: trunc_defined = 1; ! 1298: } ! 1299: ! 1300: /* If we have to call a function to save fpr's, or if we are doing profiling, ! 1301: then we will be using LR. */ ! 1302: if (first_fp_reg < 62 || profile_flag) ! 1303: regs_ever_live[65] = 1; ! 1304: ! 1305: /* If we use the link register, get it into r0. */ ! 1306: if (regs_ever_live[65]) ! 1307: fprintf (file, "\tmflr 0\n"); ! 1308: ! 1309: /* If we need to save CR, put it into r12. */ ! 1310: if (must_save_cr ()) ! 1311: fprintf (file, "\tmfcr 12\n"); ! 1312: ! 1313: /* Do any required saving of fpr's. If only one or two to save, do it ! 1314: ourself. Otherwise, call function. */ ! 1315: if (first_fp_reg == 62) ! 1316: fprintf (file, "\tstfd 30,-16(1)\n\tstfd 31,-8(1)\n"); ! 1317: else if (first_fp_reg == 63) ! 1318: fprintf (file, "\tstfd 31,-8(1)\n"); ! 1319: else if (first_fp_reg != 64) ! 1320: fprintf (file, "\tbl ._savef%d\n\tcror 15,15,15\n", first_fp_reg - 32); ! 1321: ! 1322: /* Now save gpr's. */ ! 1323: if (first_reg == 31) ! 1324: fprintf (file, "\tst 31,%d(1)\n", -4 - (64 - first_fp_reg) * 8); ! 1325: else if (first_reg != 32) ! 1326: fprintf (file, "\tstm %d,%d(1)\n", first_reg, ! 1327: - (32 - first_reg) * 4 - (64 - first_fp_reg) * 8); ! 1328: ! 1329: /* Save lr if we used it. */ ! 1330: if (regs_ever_live[65]) ! 1331: fprintf (file, "\tst 0,8(1)\n"); ! 1332: ! 1333: /* Save CR if we use any that must be preserved. */ ! 1334: if (must_save_cr ()) ! 1335: fprintf (file, "\tst 12,4(1)\n"); ! 1336: ! 1337: /* Update stack and set back pointer. */ ! 1338: if (must_push) ! 1339: { ! 1340: if (total_size < 32767) ! 1341: fprintf (file, "\tstu 1,%d(1)\n", - total_size); ! 1342: else ! 1343: { ! 1344: fprintf (file, "\tcau 0,0,%d\n\toril 0,0,%d\n", ! 1345: (total_size >> 16) & 0xffff, total_size & 0xffff); ! 1346: fprintf (file, "\tsf 12,0,1\n\tst 1,0(12)\n\toril 1,12,0\n"); ! 1347: } ! 1348: } ! 1349: ! 1350: /* Set frame pointer, if needed. */ ! 1351: if (frame_pointer_needed) ! 1352: fprintf (file, "\toril 31,1,0\n"); ! 1353: } ! 1354: ! 1355: /* Write function epilogue. */ ! 1356: ! 1357: void ! 1358: output_epilog (file, size) ! 1359: FILE *file; ! 1360: int size; ! 1361: { ! 1362: int first_reg = first_reg_to_save (); ! 1363: int must_push = rs6000_pushes_stack (); ! 1364: int first_fp_reg = first_fp_reg_to_save (); ! 1365: int basic_size = rs6000_sa_size (); ! 1366: int total_size = (basic_size + size + current_function_outgoing_args_size); ! 1367: rtx insn = get_last_insn (); ! 1368: ! 1369: /* Round size to multiple of 8 bytes. */ ! 1370: total_size = (total_size + 7) & ~7; ! 1371: ! 1372: /* If the last insn was a BARRIER, we don't have to write anything except ! 1373: the trace table. */ ! 1374: if (GET_CODE (insn) == NOTE) ! 1375: insn = prev_nonnote_insn (insn); ! 1376: if (insn == 0 || GET_CODE (insn) != BARRIER) ! 1377: { ! 1378: /* If we have a frame pointer, a call to alloca, or a large stack ! 1379: frame, restore the old stack pointer using the backchain. Otherwise, ! 1380: we know what size to update it with. */ ! 1381: if (frame_pointer_needed || current_function_calls_alloca ! 1382: || total_size > 32767) ! 1383: fprintf (file, "\tl 1,0(1)\n"); ! 1384: else if (must_push) ! 1385: fprintf (file, "\tai 1,1,%d\n", total_size); ! 1386: ! 1387: /* Get the old lr if we saved it. */ ! 1388: if (regs_ever_live[65]) ! 1389: fprintf (file, "\tl 0,8(1)\n"); ! 1390: ! 1391: /* Get the old cr if we saved it. */ ! 1392: if (must_save_cr ()) ! 1393: fprintf (file, "\tl 12,4(1)\n"); ! 1394: ! 1395: /* Set LR here to try to overlap restores below. */ ! 1396: if (regs_ever_live[65]) ! 1397: fprintf (file, "\tmtlr 0\n"); ! 1398: ! 1399: /* Restore gpr's. */ ! 1400: if (first_reg == 31) ! 1401: fprintf (file, "\tl 31,%d(1)\n", -4 - (64 - first_fp_reg) * 8); ! 1402: else if (first_reg != 32) ! 1403: fprintf (file, "\tlm %d,%d(1)\n", first_reg, ! 1404: - (32 - first_reg) * 4 - (64 - first_fp_reg) * 8); ! 1405: ! 1406: /* Restore fpr's if we can do it without calling a function. */ ! 1407: if (first_fp_reg == 62) ! 1408: fprintf (file, "\tlfd 30,-16(1)\n\tlfd 31,-8(1)\n"); ! 1409: else if (first_fp_reg == 63) ! 1410: fprintf (file, "\tlfd 31,-8(1)\n"); ! 1411: ! 1412: /* If we saved cr, restore it here. Just those of cr2, cr3, and cr4 ! 1413: that were used. */ ! 1414: if (must_save_cr ()) ! 1415: fprintf (file, "\tmtcrf %d,12\n", ! 1416: (regs_ever_live[70] != 0) * 0x20 ! 1417: + (regs_ever_live[71] != 0) * 0x10 ! 1418: + (regs_ever_live[72] != 0) * 0x8); ! 1419: ! 1420: /* If we have to restore more than two FP registers, branch to the ! 1421: restore function. It will return to our caller. */ ! 1422: if (first_fp_reg < 62) ! 1423: fprintf (file, "\tb ._restf%d\n\tcror 15,15,15\n", first_fp_reg - 32); ! 1424: else ! 1425: fprintf (file, "\tbr\n"); ! 1426: } ! 1427: ! 1428: /* Output a traceback table here. See /usr/include/sys/debug.h for info ! 1429: on its format. */ ! 1430: { ! 1431: char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); ! 1432: int fixed_parms, float_parms, parm_info; ! 1433: int i; ! 1434: ! 1435: /* Need label immediately before tbtab, so we can compute its offset ! 1436: from the function start. */ ! 1437: if (*fname == '*') ! 1438: ++fname; ! 1439: fprintf (file, "LT.."); ! 1440: ASM_OUTPUT_LABEL (file, fname); ! 1441: ! 1442: /* The .tbtab pseudo-op can only be used for the first eight ! 1443: expressions, since it can't handle the possibly variable length ! 1444: fields that follow. However, if you omit the optional fields, ! 1445: the assembler outputs zeros for all optional fields anyways, giving each ! 1446: variable length field is minimum length (as defined in sys/debug.h). ! 1447: Thus we can not use the .tbtab pseudo-op at all. */ ! 1448: ! 1449: /* An all-zero word flags the start of the tbtab, for debuggers that have ! 1450: to find it by searching forward from the entry point or from the ! 1451: current pc. */ ! 1452: fprintf (file, "\t.long 0\n"); ! 1453: ! 1454: /* Tbtab format type. Use format type 0. */ ! 1455: fprintf (file, "\t.byte 0,"); ! 1456: ! 1457: /* Language type. Unfortunately, there doesn't seem to be any official way ! 1458: to get this info, so we use language_string. C is 0. C++ is 9. ! 1459: No number defined for Obj-C, so use the value for C for now. */ ! 1460: if (! strcmp (language_string, "GNU C") ! 1461: || ! strcmp (language_string, "GNU Obj-C")) ! 1462: i = 0; ! 1463: else if (! strcmp (language_string, "GNU F77")) ! 1464: i = 1; ! 1465: else if (! strcmp (language_string, "GNU Ada")) ! 1466: i = 3; ! 1467: else if (! strcmp (language_string, "GNU PASCAL")) ! 1468: i = 2; ! 1469: else if (! strcmp (language_string, "GNU C++")) ! 1470: i = 9; ! 1471: else ! 1472: abort (); ! 1473: fprintf (file, "%d,", i); ! 1474: ! 1475: /* 8 single bit fields: global linkage (not set for C extern linkage, ! 1476: apparently a PL/I convention?), out-of-line epilogue/prologue, offset ! 1477: from start of procedure stored in tbtab, internal function, function ! 1478: has controlled storage, function has no toc, function uses fp, ! 1479: function logs/aborts fp operations. */ ! 1480: /* Assume that fp operations are used if any fp reg must be saved. */ ! 1481: fprintf (file, "%d,", (1 << 5) | ((first_fp_reg != 64) << 1)); ! 1482: ! 1483: /* 6 bitfields: function is interrupt handler, name present in proc table, ! 1484: function calls alloca, on condition directives (controls stack walks, ! 1485: 3 bits), saves condition reg, saves link reg. */ ! 1486: /* The `function calls alloca' bit seems to be set whenever reg 31 is ! 1487: set up as a frame pointer, even when there is no alloca call. */ ! 1488: fprintf (file, "%d,", ! 1489: ((1 << 6) | (frame_pointer_needed << 5) ! 1490: | (must_save_cr () << 1) | (regs_ever_live[65]))); ! 1491: ! 1492: /* 3 bitfields: saves backchain, spare bit, number of fpr saved ! 1493: (6 bits). */ ! 1494: fprintf (file, "%d,", ! 1495: (must_push << 7) | (64 - first_fp_reg_to_save ())); ! 1496: ! 1497: /* 2 bitfields: spare bits (2 bits), number of gpr saved (6 bits). */ ! 1498: fprintf (file, "%d,", (32 - first_reg_to_save ())); ! 1499: ! 1500: { ! 1501: /* Compute the parameter info from the function decl argument list. */ ! 1502: tree decl; ! 1503: int next_parm_info_bit; ! 1504: ! 1505: next_parm_info_bit = 31; ! 1506: parm_info = 0; ! 1507: fixed_parms = 0; ! 1508: float_parms = 0; ! 1509: ! 1510: for (decl = DECL_ARGUMENTS (current_function_decl); ! 1511: decl; decl = TREE_CHAIN (decl)) ! 1512: { ! 1513: rtx parameter = DECL_INCOMING_RTL (decl); ! 1514: enum machine_mode mode = GET_MODE (parameter); ! 1515: ! 1516: if (GET_CODE (parameter) == REG) ! 1517: { ! 1518: if (GET_MODE_CLASS (mode) == MODE_FLOAT) ! 1519: { ! 1520: int bits; ! 1521: ! 1522: float_parms++; ! 1523: ! 1524: if (mode == SFmode) ! 1525: bits = 0x2; ! 1526: else if (mode == DFmode) ! 1527: bits = 0x3; ! 1528: else ! 1529: abort (); ! 1530: ! 1531: /* If only one bit will fit, don't or in this entry. */ ! 1532: if (next_parm_info_bit > 0) ! 1533: parm_info |= (bits << (next_parm_info_bit - 1)); ! 1534: next_parm_info_bit -= 2; ! 1535: } ! 1536: else ! 1537: { ! 1538: fixed_parms += ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) ! 1539: / UNITS_PER_WORD); ! 1540: next_parm_info_bit -= 1; ! 1541: } ! 1542: } ! 1543: } ! 1544: } ! 1545: ! 1546: /* Number of fixed point parameters. */ ! 1547: /* This is actually the number of words of fixed point parameters; thus ! 1548: an 8 byte struct counts as 2; and thus the maximum value is 8. */ ! 1549: fprintf (file, "%d,", fixed_parms); ! 1550: ! 1551: /* 2 bitfields: number of floating point parameters (7 bits), parameters ! 1552: all on stack. */ ! 1553: /* This is actually the number of fp registers that hold parameters; ! 1554: and thus the maximum value is 13. */ ! 1555: /* Set parameters on stack bit if parameters are not in their original ! 1556: registers, regardless of whether they are on the stack? Xlc ! 1557: seems to set the bit when not optimizing. */ ! 1558: fprintf (file, "%d\n", ((float_parms << 1) | (! optimize))); ! 1559: ! 1560: /* Optional fields follow. Some are variable length. */ ! 1561: ! 1562: /* Parameter types, left adjusted bit fields: 0 fixed, 10 single float, ! 1563: 11 double float. */ ! 1564: /* There is an entry for each parameter in a register, in the order that ! 1565: they occur in the parameter list. Any intervening arguments on the ! 1566: stack are ignored. If the list overflows a long (max possible length ! 1567: 34 bits) then completely leave off all elements that don't fit. */ ! 1568: /* Only emit this long if there was at least one parameter. */ ! 1569: if (fixed_parms || float_parms) ! 1570: fprintf (file, "\t.long %d\n", parm_info); ! 1571: ! 1572: /* Offset from start of code to tb table. */ ! 1573: fprintf (file, "\t.long LT.."); ! 1574: RS6000_OUTPUT_BASENAME (file, fname); ! 1575: fprintf (file, "-."); ! 1576: RS6000_OUTPUT_BASENAME (file, fname); ! 1577: fprintf (file, "\n"); ! 1578: ! 1579: /* Interrupt handler mask. */ ! 1580: /* Omit this long, since we never set the interrupt handler bit above. */ ! 1581: ! 1582: /* Number of CTL (controlled storage) anchors. */ ! 1583: /* Omit this long, since the has_ctl bit is never set above. */ ! 1584: ! 1585: /* Displacement into stack of each CTL anchor. */ ! 1586: /* Omit this list of longs, because there are no CTL anchors. */ ! 1587: ! 1588: /* Length of function name. */ ! 1589: fprintf (file, "\t.short %d\n", strlen (fname)); ! 1590: ! 1591: /* Function name. */ ! 1592: assemble_string (fname, strlen (fname)); ! 1593: ! 1594: /* Register for alloca automatic storage; this is always reg 31. ! 1595: Only emit this if the alloca bit was set above. */ ! 1596: if (frame_pointer_needed) ! 1597: fprintf (file, "\t.byte 31\n"); ! 1598: } ! 1599: } ! 1600: ! 1601: /* Output a TOC entry. We derive the entry name from what is ! 1602: being written. */ ! 1603: ! 1604: void ! 1605: output_toc (file, x, labelno) ! 1606: FILE *file; ! 1607: rtx x; ! 1608: int labelno; ! 1609: { ! 1610: char buf[256]; ! 1611: char *name = buf; ! 1612: rtx base = x; ! 1613: int offset = 0; ! 1614: ! 1615: ASM_OUTPUT_INTERNAL_LABEL (file, "LC", labelno); ! 1616: ! 1617: /* Handle FP constants specially. */ ! 1618: if (GET_CODE (x) == CONST_DOUBLE ! 1619: && GET_MODE (x) == DFmode ! 1620: && TARGET_FLOAT_FORMAT == HOST_FLOAT_FORMAT ! 1621: && BITS_PER_WORD == HOST_BITS_PER_INT ! 1622: && TARGET_FP_IN_TOC) ! 1623: { ! 1624: fprintf (file, "\t.tc FD_%x_%x[TC],%d,%d\n", ! 1625: CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x), ! 1626: CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x)); ! 1627: return; ! 1628: } ! 1629: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode ! 1630: && TARGET_FP_IN_TOC) ! 1631: { ! 1632: rtx val = operand_subword (x, 0, 0, SFmode); ! 1633: ! 1634: if (val == 0 || GET_CODE (val) != CONST_INT) ! 1635: abort (); ! 1636: ! 1637: fprintf (file, "\t.tc FS_%x[TC],%d\n", INTVAL (val), INTVAL (val)); ! 1638: return; ! 1639: } ! 1640: ! 1641: if (GET_CODE (x) == CONST) ! 1642: { ! 1643: base = XEXP (XEXP (x, 0), 0); ! 1644: offset = INTVAL (XEXP (XEXP (x, 0), 1)); ! 1645: } ! 1646: ! 1647: if (GET_CODE (base) == SYMBOL_REF) ! 1648: name = XSTR (base, 0); ! 1649: else if (GET_CODE (base) == LABEL_REF) ! 1650: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (base, 0))); ! 1651: else if (GET_CODE (base) == CODE_LABEL) ! 1652: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base)); ! 1653: else ! 1654: abort (); ! 1655: ! 1656: fprintf (file, "\t.tc "); ! 1657: RS6000_OUTPUT_BASENAME (file, name); ! 1658: ! 1659: if (offset < 0) ! 1660: fprintf (file, ".N%d", - offset); ! 1661: else if (offset) ! 1662: fprintf (file, ".P%d", offset); ! 1663: ! 1664: fprintf (file, "[TC],"); ! 1665: output_addr_const (file, x); ! 1666: fprintf (file, "\n"); ! 1667: } ! 1668: ! 1669: /* Output an assembler pseudo-op to write an ASCII string of N characters ! 1670: starting at P to FILE. ! 1671: ! 1672: On the RS/6000, we have to do this using the .byte operation and ! 1673: write out special characters outside the quoted string. ! 1674: Also, the assembler is broken; very long strings are truncated, ! 1675: so we must artificially break them up early. */ ! 1676: ! 1677: void ! 1678: output_ascii (file, p, n) ! 1679: FILE *file; ! 1680: char *p; ! 1681: int n; ! 1682: { ! 1683: char c; ! 1684: int i, count_string; ! 1685: char *for_string = "\t.byte \""; ! 1686: char *for_decimal = "\t.byte "; ! 1687: char *to_close = NULL; ! 1688: ! 1689: count_string = 0; ! 1690: for (i = 0; i < n; i++) ! 1691: { ! 1692: c = *p++; ! 1693: if (c >= ' ' && c < 0177) ! 1694: { ! 1695: if (for_string) ! 1696: fputs (for_string, file); ! 1697: putc (c, file); ! 1698: ! 1699: /* Write two quotes to get one. */ ! 1700: if (c == '"') ! 1701: { ! 1702: putc (c, file); ! 1703: ++count_string; ! 1704: } ! 1705: ! 1706: for_string = NULL; ! 1707: for_decimal = "\"\n\t.byte "; ! 1708: to_close = "\"\n"; ! 1709: ++count_string; ! 1710: ! 1711: if (count_string >= 512) ! 1712: { ! 1713: fputs (to_close, file); ! 1714: ! 1715: for_string = "\t.byte \""; ! 1716: for_decimal = "\t.byte "; ! 1717: to_close = NULL; ! 1718: count_string = 0; ! 1719: } ! 1720: } ! 1721: else ! 1722: { ! 1723: if (for_decimal) ! 1724: fputs (for_decimal, file); ! 1725: fprintf (file, "%d", c); ! 1726: ! 1727: for_string = "\n\t.byte \""; ! 1728: for_decimal = ", "; ! 1729: to_close = "\n"; ! 1730: count_string = 0; ! 1731: } ! 1732: } ! 1733: ! 1734: /* Now close the string if we have written one. Then end the line. */ ! 1735: if (to_close) ! 1736: fprintf (file, to_close); ! 1737: } ! 1738: ! 1739: /* Generate a unique section name for FILENAME for a section type ! 1740: represented by SECTION_DESC. Output goes into BUF. ! 1741: ! 1742: SECTION_DESC can be any string, as long as it is different for each ! 1743: possible section type. ! 1744: ! 1745: We name the section in the same manner as xlc. The name begins with an ! 1746: underscore followed by the filename (after stripping any leading directory ! 1747: names) with the last period replaced by the string SECTION_DESC. If ! 1748: FILENAME does not contain a period, SECTION_DESC is appended to the end of ! 1749: the name. */ ! 1750: ! 1751: void ! 1752: rs6000_gen_section_name (buf, filename, section_desc) ! 1753: char **buf; ! 1754: char *filename; ! 1755: char *section_desc; ! 1756: { ! 1757: char *q, *after_last_slash, *last_period; ! 1758: char *p; ! 1759: int len; ! 1760: ! 1761: after_last_slash = filename; ! 1762: for (q = filename; *q; q++) ! 1763: { ! 1764: if (*q == '/') ! 1765: after_last_slash = q + 1; ! 1766: else if (*q == '.') ! 1767: last_period = q; ! 1768: } ! 1769: ! 1770: len = strlen (after_last_slash) + strlen (section_desc) + 2; ! 1771: *buf = (char *) permalloc (len); ! 1772: ! 1773: p = *buf; ! 1774: *p++ = '_'; ! 1775: ! 1776: for (q = after_last_slash; *q; q++) ! 1777: { ! 1778: if (q == last_period) ! 1779: { ! 1780: strcpy (p, section_desc); ! 1781: p += strlen (section_desc); ! 1782: } ! 1783: ! 1784: else if (isalnum (*q)) ! 1785: *p++ = *q; ! 1786: } ! 1787: ! 1788: if (last_period == 0) ! 1789: strcpy (p, section_desc); ! 1790: else ! 1791: *p = '\0'; ! 1792: } ! 1793: ! 1794: /* Write function profiler code. */ ! 1795: ! 1796: void ! 1797: output_function_profiler (file, labelno) ! 1798: FILE *file; ! 1799: int labelno; ! 1800: { ! 1801: /* The last used parameter register. */ ! 1802: int last_parm_reg; ! 1803: int i, j; ! 1804: ! 1805: /* Set up a TOC entry for the profiler label. */ ! 1806: toc_section (); ! 1807: fprintf (file, "LPC..%d:\n\t.tc\tLP..%d[TC],LP..%d\n", ! 1808: labelno, labelno, labelno); ! 1809: text_section (); ! 1810: ! 1811: /* Figure out last used parameter register. The proper thing to do is ! 1812: to walk incoming args of the function. A function might have live ! 1813: parameter registers even if it has no incoming args. */ ! 1814: ! 1815: for (last_parm_reg = 10; ! 1816: last_parm_reg > 2 && ! regs_ever_live [last_parm_reg]; ! 1817: last_parm_reg--) ! 1818: ; ! 1819: ! 1820: /* Save parameter registers in regs 23-30. Don't overwrite reg 31, since ! 1821: it might be set up as the frame pointer. */ ! 1822: ! 1823: for (i = 3, j = 30; i <= last_parm_reg; i++, j--) ! 1824: fprintf (file, "\tai %d,%d,0\n", j, i); ! 1825: ! 1826: /* Load location address into r3, and call mcount. */ ! 1827: ! 1828: fprintf (file, "\tl 3,LPC..%d(2)\n\tbl .mcount\n", labelno); ! 1829: ! 1830: /* Restore parameter registers. */ ! 1831: ! 1832: for (i = 3, j = 30; i <= last_parm_reg; i++, j--) ! 1833: fprintf (file, "\tai %d,%d,0\n", i, j); ! 1834: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.