|
|
1.1 ! root 1: /* Subroutines used for code generation on AMD Am29000. ! 2: Copyright (C) 1987, 88, 90, 91, 92, 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: #include "reload.h" ! 38: ! 39: #define min(A,B) ((A) < (B) ? (A) : (B)) ! 40: ! 41: /* This gives the size in words of the register stack for the current ! 42: procedure. */ ! 43: ! 44: static int a29k_regstack_size; ! 45: ! 46: /* This points to the last insn of the insn prologue. It is set when ! 47: an insn without a filled delay slot is found near the start of the ! 48: function. */ ! 49: ! 50: static char *a29k_last_prologue_insn; ! 51: ! 52: /* This points to the first insn that will be in the epilogue. It is null if ! 53: no epilogue is required. */ ! 54: ! 55: static char *a29k_first_epilogue_insn; ! 56: ! 57: /* This is nonzero if a a29k_first_epilogue_insn was put in a delay slot. It ! 58: indicates that an intermediate label needs to be written. */ ! 59: ! 60: static int a29k_first_epilogue_insn_used; ! 61: ! 62: /* Location to hold the name of the current function. We need this prolog to ! 63: contain the tag words prior to the declaration. So the name must be stored ! 64: away. */ ! 65: ! 66: char *a29k_function_name; ! 67: ! 68: /* Mapping of registers to debug register numbers. The only change is ! 69: for the frame pointer and the register numbers used for the incoming ! 70: arguments. */ ! 71: ! 72: int a29k_debug_reg_map[FIRST_PSEUDO_REGISTER]; ! 73: ! 74: /* Save information from a "cmpxx" operation until the branch or scc is ! 75: emitted. */ ! 76: ! 77: rtx a29k_compare_op0, a29k_compare_op1; ! 78: int a29k_compare_fp_p; ! 79: ! 80: /* Gives names for registers. */ ! 81: extern char *reg_names[]; ! 82: ! 83: /* Returns 1 if OP is a 8-bit constant. */ ! 84: ! 85: int ! 86: cint_8_operand (op, mode) ! 87: register rtx op; ! 88: enum machine_mode mode; ! 89: { ! 90: return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffffff00) == 0; ! 91: } ! 92: ! 93: /* Returns 1 if OP is a 16-bit constant. */ ! 94: ! 95: int ! 96: cint_16_operand (op, mode) ! 97: rtx op; ! 98: enum machine_mode mode; ! 99: { ! 100: return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0; ! 101: } ! 102: ! 103: /* Returns 1 if OP is a constant that cannot be moved in a single insn. */ ! 104: ! 105: int ! 106: long_const_operand (op, mode) ! 107: register rtx op; ! 108: enum machine_mode mode; ! 109: { ! 110: if (! CONSTANT_P (op)) ! 111: return 0; ! 112: ! 113: if (TARGET_29050 && GET_CODE (op) == CONST_INT ! 114: && (INTVAL (op) & 0xffff) == 0) ! 115: return 0; ! 116: ! 117: return (GET_CODE (op) != CONST_INT ! 118: || ((INTVAL (op) & 0xffff0000) != 0 ! 119: && (INTVAL (op) & 0xffff0000) != 0xffff0000 ! 120: && INTVAL (op) != 0x80000000)); ! 121: } ! 122: ! 123: /* The following four functions detect constants of 0, 8, 16, and 24 used as ! 124: a position in ZERO_EXTRACT operations. They can either be the appropriate ! 125: constant integer or a shift (which will be produced by combine). */ ! 126: ! 127: static int ! 128: shift_constant_operand (op, mode, val) ! 129: rtx op; ! 130: enum machine_mode mode; ! 131: int val; ! 132: { ! 133: return ((GET_CODE (op) == CONST_INT && INTVAL (op) == val) ! 134: || (GET_CODE (op) == ASHIFT ! 135: && GET_CODE (XEXP (op, 0)) == CONST_INT ! 136: && INTVAL (XEXP (op, 0)) == val / 8 ! 137: && GET_CODE (XEXP (op, 1)) == CONST_INT ! 138: && INTVAL (XEXP (op, 1)) == 3)); ! 139: } ! 140: ! 141: int ! 142: const_0_operand (op, mode) ! 143: rtx op; ! 144: enum machine_mode mode; ! 145: { ! 146: return shift_constant_operand (op, mode, 0); ! 147: } ! 148: ! 149: int ! 150: const_8_operand (op, mode) ! 151: rtx op; ! 152: enum machine_mode mode; ! 153: { ! 154: return shift_constant_operand (op, mode, 8); ! 155: } ! 156: ! 157: int ! 158: const_16_operand (op, mode) ! 159: rtx op; ! 160: enum machine_mode mode; ! 161: { ! 162: return shift_constant_operand (op, mode, 16); ! 163: } ! 164: ! 165: int ! 166: const_24_operand (op, mode) ! 167: rtx op; ! 168: enum machine_mode mode; ! 169: { ! 170: return shift_constant_operand (op, mode, 24); ! 171: } ! 172: ! 173: /* Returns 1 if OP is a floating-point constant of the proper mode. */ ! 174: ! 175: int ! 176: float_const_operand (op, mode) ! 177: rtx op; ! 178: enum machine_mode mode; ! 179: { ! 180: return GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == mode; ! 181: } ! 182: ! 183: /* Returns 1 if OP is a floating-point constant of the proper mode or a ! 184: general-purpose register. */ ! 185: ! 186: int ! 187: gpc_reg_or_float_constant_operand (op, mode) ! 188: rtx op; ! 189: enum machine_mode mode; ! 190: { ! 191: return float_const_operand (op, mode) || gpc_reg_operand (op, mode); ! 192: } ! 193: ! 194: /* Returns 1 if OP is an integer constant of the proper mode or a ! 195: general-purpose register. */ ! 196: ! 197: int ! 198: gpc_reg_or_integer_constant_operand (op, mode) ! 199: rtx op; ! 200: enum machine_mode mode; ! 201: { ! 202: return ((GET_MODE (op) == VOIDmode ! 203: && (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)) ! 204: || gpc_reg_operand (op, mode)); ! 205: } ! 206: ! 207: /* Returns 1 if OP is a special machine register. */ ! 208: ! 209: int ! 210: spec_reg_operand (op, mode) ! 211: rtx op; ! 212: enum machine_mode mode; ! 213: { ! 214: if (GET_CODE (op) != REG || GET_MODE (op) != mode) ! 215: return 0; ! 216: ! 217: switch (GET_MODE_CLASS (mode)) ! 218: { ! 219: case MODE_PARTIAL_INT: ! 220: return REGNO (op) >= R_BP && REGNO (op) <= R_CR; ! 221: case MODE_INT: ! 222: return REGNO (op) >= R_Q && REGNO (op) <= R_EXO; ! 223: detault: ! 224: return 0; ! 225: } ! 226: } ! 227: ! 228: /* Returns 1 if OP is an accumulator register. */ ! 229: ! 230: int ! 231: accum_reg_operand (op, mode) ! 232: rtx op; ! 233: enum machine_mode mode; ! 234: { ! 235: return (GET_CODE (op) == REG ! 236: && REGNO (op) >= R_ACC (0) && REGNO (op) <= R_ACC (3)); ! 237: } ! 238: ! 239: /* Returns 1 if OP is a normal data register. */ ! 240: ! 241: int ! 242: gpc_reg_operand (op, mode) ! 243: rtx op; ! 244: enum machine_mode mode; ! 245: { ! 246: int regno; ! 247: ! 248: if (GET_MODE (op) != mode && mode != VOIDmode) ! 249: return 0; ! 250: ! 251: if (GET_CODE (op) == REG) ! 252: regno = REGNO (op); ! 253: else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) ! 254: { ! 255: regno = REGNO (SUBREG_REG (op)); ! 256: if (regno < FIRST_PSEUDO_REGISTER) ! 257: regno += SUBREG_WORD (op); ! 258: } ! 259: else ! 260: return 0; ! 261: ! 262: return (regno >= FIRST_PSEUDO_REGISTER || regno < R_BP ! 263: || (regno >= R_KR (0) && regno <= R_KR (31))); ! 264: } ! 265: ! 266: /* Returns 1 if OP is either an 8-bit constant integer or a general register. ! 267: If a register, it must be in the proper mode unless MODE is VOIDmode. */ ! 268: ! 269: int ! 270: srcb_operand (op, mode) ! 271: register rtx op; ! 272: enum machine_mode mode; ! 273: { ! 274: if (GET_CODE (op) == CONST_INT ! 275: && (mode == QImode ! 276: || (INTVAL (op) & 0xffffff00) == 0)) ! 277: return 1; ! 278: ! 279: if (GET_MODE (op) != mode && mode != VOIDmode) ! 280: return 0; ! 281: ! 282: return gpc_reg_operand (op, mode); ! 283: } ! 284: ! 285: /* Return 1 if OP is either an immediate or a general register. This is used ! 286: for the input operand of mtsr/mtrsim. */ ! 287: ! 288: int ! 289: gpc_reg_or_immediate_operand (op, mode) ! 290: rtx op; ! 291: enum machine_mode mode; ! 292: { ! 293: return gpc_reg_operand (op, mode) || immediate_operand (op, mode); ! 294: } ! 295: ! 296: /* Return 1 if OP can be used as the second operand of and AND insn. This ! 297: includes srcb_operand and a constant whose complement fits in 8 bits. */ ! 298: ! 299: int ! 300: and_operand (op, mode) ! 301: rtx op; ! 302: enum machine_mode mode; ! 303: { ! 304: return (srcb_operand (op, mode) ! 305: || (GET_CODE (op) == CONST_INT ! 306: && ((unsigned) ((~ INTVAL (op)) & GET_MODE_MASK (mode)) < 256))); ! 307: } ! 308: ! 309: /* Return 1 if OP can be used as the second operand of an ADD insn. ! 310: This is the same as above, except we use negative, rather than ! 311: complement. */ ! 312: ! 313: int ! 314: add_operand (op, mode) ! 315: rtx op; ! 316: enum machine_mode mode; ! 317: { ! 318: return (srcb_operand (op, mode) ! 319: || (GET_CODE (op) == CONST_INT ! 320: && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256))); ! 321: } ! 322: ! 323: /* Return 1 if OP is a valid address in a CALL_INSN. These are a SYMBOL_REF ! 324: to the current function, all SYMBOL_REFs if TARGET_SMALL_MEMORY, or ! 325: a sufficiently-small constant. */ ! 326: ! 327: int ! 328: call_operand (op, mode) ! 329: rtx op; ! 330: enum machine_mode mode; ! 331: { ! 332: switch (GET_CODE (op)) ! 333: { ! 334: case SYMBOL_REF: ! 335: return (TARGET_SMALL_MEMORY ! 336: || (! TARGET_LARGE_MEMORY ! 337: && ((GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FLAG (op)) ! 338: || ! strcmp (XSTR (op, 0), current_function_name)))); ! 339: ! 340: case CONST_INT: ! 341: return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000; ! 342: ! 343: default: ! 344: return 0; ! 345: } ! 346: } ! 347: ! 348: /* Return 1 if OP can be used as the input operand for a move insn. */ ! 349: ! 350: int ! 351: in_operand (op, mode) ! 352: rtx op; ! 353: enum machine_mode mode; ! 354: { ! 355: rtx orig_op = op; ! 356: ! 357: if (! general_operand (op, mode)) ! 358: return 0; ! 359: ! 360: while (GET_CODE (op) == SUBREG) ! 361: op = SUBREG_REG (op); ! 362: ! 363: switch (GET_CODE (op)) ! 364: { ! 365: case REG: ! 366: return 1; ! 367: ! 368: case MEM: ! 369: return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); ! 370: ! 371: case CONST_INT: ! 372: if (GET_MODE_CLASS (mode) != MODE_INT ! 373: && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) ! 374: return 0; ! 375: ! 376: return 1; ! 377: ! 378: case CONST: ! 379: case SYMBOL_REF: ! 380: case LABEL_REF: ! 381: return (GET_MODE (op) == mode ! 382: || mode == SImode || mode == HImode || mode == QImode); ! 383: ! 384: case CONST_DOUBLE: ! 385: return ((GET_MODE_CLASS (mode) == MODE_FLOAT ! 386: && mode == GET_MODE (op)) ! 387: || (GET_MODE (op) == VOIDmode ! 388: && GET_MODE_CLASS (mode) == MODE_INT)); ! 389: ! 390: default: ! 391: return 0; ! 392: } ! 393: } ! 394: ! 395: /* Return 1 if OP can be used as the output operand for a move insn. */ ! 396: ! 397: int ! 398: out_operand (op, mode) ! 399: rtx op; ! 400: enum machine_mode mode; ! 401: { ! 402: rtx orig_op = op; ! 403: ! 404: if (! general_operand (op, mode)) ! 405: return 0; ! 406: ! 407: while (GET_CODE (op) == SUBREG) ! 408: op = SUBREG_REG (op); ! 409: ! 410: if (GET_CODE (op) == REG) ! 411: return (gpc_reg_operand (orig_op, mode) ! 412: || spec_reg_operand (orig_op, mode) ! 413: || (GET_MODE_CLASS (mode) == MODE_FLOAT ! 414: && accum_reg_operand (orig_op, mode))); ! 415: ! 416: else if (GET_CODE (op) == MEM) ! 417: return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); ! 418: else ! 419: return 0; ! 420: } ! 421: ! 422: /* Return 1 if OP is an item in memory, given that we are in reload. */ ! 423: ! 424: int ! 425: reload_memory_operand (op, mode) ! 426: rtx op; ! 427: enum machine_mode mode; ! 428: { ! 429: int regno = true_regnum (op); ! 430: ! 431: return (! CONSTANT_P (op) ! 432: && (regno == -1 ! 433: || (GET_CODE (op) == REG ! 434: && REGNO (op) >= FIRST_PSEUDO_REGISTER))); ! 435: } ! 436: ! 437: /* Given an object for which reload_memory_operand is true, return the address ! 438: of the operand, taking into account anything that reload may do. */ ! 439: ! 440: rtx ! 441: a29k_get_reloaded_address (op) ! 442: rtx op; ! 443: { ! 444: if (GET_CODE (op) == SUBREG) ! 445: { ! 446: if (SUBREG_WORD (op) != 0) ! 447: abort (); ! 448: ! 449: op = SUBREG_REG (op); ! 450: } ! 451: ! 452: if (GET_CODE (op) == REG) ! 453: op = reg_equiv_mem[REGNO (op)]; ! 454: ! 455: return find_replacement (&XEXP (op, 0)); ! 456: } ! 457: ! 458: /* Subfunction of the following function. Update the flags of any MEM ! 459: found in part of X. */ ! 460: ! 461: static void ! 462: a29k_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) ! 463: rtx x; ! 464: int in_struct_p, volatile_p, unchanging_p; ! 465: { ! 466: int i; ! 467: ! 468: switch (GET_CODE (x)) ! 469: { ! 470: case SEQUENCE: ! 471: case PARALLEL: ! 472: for (i = XVECLEN (x, 0) - 1; i >= 0; i--) ! 473: a29k_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, ! 474: unchanging_p); ! 475: break; ! 476: ! 477: case INSN: ! 478: a29k_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p, ! 479: unchanging_p); ! 480: break; ! 481: ! 482: case SET: ! 483: a29k_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p, ! 484: unchanging_p); ! 485: a29k_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, unchanging_p); ! 486: break; ! 487: ! 488: case MEM: ! 489: MEM_IN_STRUCT_P (x) = in_struct_p; ! 490: MEM_VOLATILE_P (x) = volatile_p; ! 491: RTX_UNCHANGING_P (x) = unchanging_p; ! 492: break; ! 493: } ! 494: } ! 495: ! 496: /* Given INSN, which is either an INSN or a SEQUENCE generated to ! 497: perform a memory operation, look for any MEMs in either a SET_DEST or ! 498: a SET_SRC and copy the in-struct, unchanging, and volatile flags from ! 499: REF into each of the MEMs found. If REF is not a MEM, don't do ! 500: anything. */ ! 501: ! 502: void ! 503: a29k_set_memflags (insn, ref) ! 504: rtx insn; ! 505: rtx ref; ! 506: { ! 507: /* Note that it is always safe to get these flags, though they won't ! 508: be what we think if REF is not a MEM. */ ! 509: int in_struct_p = MEM_IN_STRUCT_P (ref); ! 510: int volatile_p = MEM_VOLATILE_P (ref); ! 511: int unchanging_p = RTX_UNCHANGING_P (ref); ! 512: ! 513: if (GET_CODE (ref) != MEM ! 514: || (! in_struct_p && ! volatile_p && ! unchanging_p)) ! 515: return; ! 516: ! 517: a29k_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p); ! 518: } ! 519: ! 520: /* Return 1 if OP is a comparison operator that we have in floating-point. */ ! 521: ! 522: int ! 523: fp_comparison_operator (op, mode) ! 524: rtx op; ! 525: enum machine_mode mode; ! 526: { ! 527: return ((mode == VOIDmode || mode == GET_MODE (op)) ! 528: && (GET_CODE (op) == EQ || GET_CODE (op) == GT || ! 529: GET_CODE (op) == GE)); ! 530: } ! 531: ! 532: /* Return 1 if OP is a valid branch comparison. */ ! 533: ! 534: int ! 535: branch_operator (op, mode) ! 536: rtx op; ! 537: enum machine_mode mode; ! 538: { ! 539: return ((mode == VOIDmode || mode == GET_MODE (op)) ! 540: && (GET_CODE (op) == GE || GET_CODE (op) == LT)); ! 541: } ! 542: ! 543: /* Return 1 if OP is a load multiple operation. It is known to be a ! 544: PARALLEL and the first three sections will be tested. */ ! 545: ! 546: int ! 547: load_multiple_operation (op, mode) ! 548: rtx op; ! 549: enum machine_mode mode; ! 550: { ! 551: int count = XVECLEN (op, 0) - 2; ! 552: int dest_regno; ! 553: rtx src_addr; ! 554: int i; ! 555: ! 556: /* Perform a quick check so we don't blow up below. */ ! 557: if (count <= 1 ! 558: || GET_CODE (XVECEXP (op, 0, 0)) != SET ! 559: || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG ! 560: || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) ! 561: return 0; ! 562: ! 563: dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); ! 564: src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); ! 565: ! 566: for (i = 1; i < count; i++) ! 567: { ! 568: rtx elt = XVECEXP (op, 0, i + 2); ! 569: ! 570: if (GET_CODE (elt) != SET ! 571: || GET_CODE (SET_DEST (elt)) != REG ! 572: || GET_MODE (SET_DEST (elt)) != SImode ! 573: || REGNO (SET_DEST (elt)) != dest_regno + i ! 574: || GET_CODE (SET_SRC (elt)) != MEM ! 575: || GET_MODE (SET_SRC (elt)) != SImode ! 576: || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS ! 577: || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) ! 578: || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT ! 579: || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4) ! 580: return 0; ! 581: } ! 582: ! 583: return 1; ! 584: } ! 585: ! 586: /* Similar, but tests for store multiple. */ ! 587: ! 588: int ! 589: store_multiple_operation (op, mode) ! 590: rtx op; ! 591: enum machine_mode mode; ! 592: { ! 593: int num_special = TARGET_NO_STOREM_BUG ? 2 : 1; ! 594: int count = XVECLEN (op, 0) - num_special; ! 595: int src_regno; ! 596: rtx dest_addr; ! 597: int i; ! 598: ! 599: /* Perform a quick check so we don't blow up below. */ ! 600: if (count <= 1 ! 601: || GET_CODE (XVECEXP (op, 0, 0)) != SET ! 602: || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM ! 603: || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) ! 604: return 0; ! 605: ! 606: src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); ! 607: dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); ! 608: ! 609: for (i = 1; i < count; i++) ! 610: { ! 611: rtx elt = XVECEXP (op, 0, i + num_special); ! 612: ! 613: if (GET_CODE (elt) != SET ! 614: || GET_CODE (SET_SRC (elt)) != REG ! 615: || GET_MODE (SET_SRC (elt)) != SImode ! 616: || REGNO (SET_SRC (elt)) != src_regno + i ! 617: || GET_CODE (SET_DEST (elt)) != MEM ! 618: || GET_MODE (SET_DEST (elt)) != SImode ! 619: || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS ! 620: || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) ! 621: || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT ! 622: || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4) ! 623: return 0; ! 624: } ! 625: ! 626: return 1; ! 627: } ! 628: ! 629: /* Given a special register REG and MASK, a value being masked against a ! 630: quantity to which the special register is set, return 1 if the masking ! 631: operation is built-in to the setting of that special register. */ ! 632: ! 633: int ! 634: masks_bits_for_special (reg, mask) ! 635: rtx reg; ! 636: rtx mask; ! 637: { ! 638: int needed_mask_value; ! 639: ! 640: if (GET_CODE (reg) != REG || GET_CODE (mask) != CONST_INT) ! 641: abort (); ! 642: ! 643: switch (REGNO (reg)) ! 644: { ! 645: case R_BP: ! 646: case R_INT: ! 647: needed_mask_value = 3; ! 648: break; ! 649: ! 650: case R_FC: ! 651: needed_mask_value = 31; ! 652: break; ! 653: ! 654: case R_CR: ! 655: case R_LRU: ! 656: needed_mask_value = 255; ! 657: break; ! 658: ! 659: case R_FPE: ! 660: needed_mask_value = 511; ! 661: break; ! 662: ! 663: case R_MMU: ! 664: needed_mask_value = 0x3ff; ! 665: break; ! 666: ! 667: case R_OPS: ! 668: case R_CPS: ! 669: case R_RBP: ! 670: case R_FPS: ! 671: needed_mask_value = 0xffff; ! 672: break; ! 673: ! 674: case R_VAB: ! 675: needed_mask_value = 0xffff0000; ! 676: break; ! 677: ! 678: case R_Q: ! 679: case R_CFG: ! 680: case R_CHA: ! 681: case R_CHD: ! 682: case R_CHC: ! 683: case R_TMC: ! 684: case R_TMR: ! 685: case R_PC0: ! 686: case R_PC1: ! 687: case R_PC2: ! 688: return 0; ! 689: ! 690: default: ! 691: abort (); ! 692: } ! 693: ! 694: return (INTVAL (mask) & ~ needed_mask_value) == 0; ! 695: } ! 696: ! 697: /* Return nonzero if this label is that of the return point, but there is ! 698: a non-null epilogue. */ ! 699: ! 700: int ! 701: epilogue_operand (op, mode) ! 702: rtx op; ! 703: enum machine_mode mode; ! 704: { ! 705: return next_active_insn (op) == 0 && a29k_first_epilogue_insn != 0; ! 706: } ! 707: ! 708: /* Return the register class of a scratch register needed to copy IN into ! 709: or out of a register in CLASS in MODE. If it can be done directly, ! 710: NO_REGS is returned. */ ! 711: ! 712: enum reg_class ! 713: secondary_reload_class (class, mode, in) ! 714: enum reg_class class; ! 715: enum machine_mode mode; ! 716: rtx in; ! 717: { ! 718: int regno = -1; ! 719: enum rtx_code code = GET_CODE (in); ! 720: ! 721: if (! CONSTANT_P (in)) ! 722: { ! 723: regno = true_regnum (in); ! 724: ! 725: /* A pseudo is the same as memory. */ ! 726: if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER) ! 727: code = MEM; ! 728: } ! 729: ! 730: /* If we are transferring between memory and a multi-word mode, we need ! 731: CR. */ ! 732: ! 733: if (code == MEM && GET_MODE_SIZE (mode) > UNITS_PER_WORD) ! 734: return CR_REGS; ! 735: ! 736: /* If between memory and a mode smaller than a word without DW being ! 737: enabled, we need BP. */ ! 738: ! 739: if (code == MEM && ! TARGET_DW_ENABLE ! 740: && GET_MODE_SIZE (mode) < UNITS_PER_WORD) ! 741: return BP_REGS; ! 742: ! 743: /* Otherwise, we can place anything into GENERAL_REGS and can put ! 744: GENERAL_REGS into anything. */ ! 745: if (class == GENERAL_REGS ! 746: || (regno != -1 ! 747: && (regno < R_BP ! 748: || (regno >= R_KR (0) && regno <= R_KR (31))))) ! 749: return NO_REGS; ! 750: ! 751: /* We can place 16-bit constants into a special register. */ ! 752: if (code == CONST_INT ! 753: && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535) ! 754: && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS)) ! 755: return NO_REGS; ! 756: ! 757: /* Otherwise, we need GENERAL_REGS. */ ! 758: return GENERAL_REGS; ! 759: } ! 760: ! 761: /* START is the zero-based incoming argument register index used (0 is 160, ! 762: i.e., the first incoming argument register) and COUNT is the number used. ! 763: ! 764: Mark the corresponding incoming registers as neither fixed nor call used. ! 765: For each register used for incoming arguments, we have one less local ! 766: register that can be used. So also mark some high-numbered registers as ! 767: fixed. ! 768: ! 769: Return the first register number to use for the argument. */ ! 770: ! 771: int ! 772: incoming_reg (start, count) ! 773: int start; ! 774: int count; ! 775: { ! 776: int i; ! 777: ! 778: /* We only use 16 argument registers, so truncate at the end of the ! 779: area. */ ! 780: if (start + count > 16) ! 781: count = 16 - start; ! 782: ! 783: if (! TARGET_NO_REUSE_ARGS) ! 784: /* Mark all the used registers as not fixed and saved over calls. */ ! 785: for (i = R_AR (start); i < R_AR (start + count); i++) ! 786: { ! 787: fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0; ! 788: CLEAR_HARD_REG_BIT (fixed_reg_set, i); ! 789: CLEAR_HARD_REG_BIT (call_used_reg_set, i); ! 790: CLEAR_HARD_REG_BIT (call_fixed_reg_set, i); ! 791: } ! 792: ! 793: /* Shorten the maximum size of the frame. */ ! 794: for (i = R_AR (0) - start - count; i < R_AR (0) - start; i++) ! 795: { ! 796: fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1; ! 797: SET_HARD_REG_BIT (fixed_reg_set, i); ! 798: SET_HARD_REG_BIT (call_used_reg_set, i); ! 799: SET_HARD_REG_BIT (call_fixed_reg_set, i); ! 800: } ! 801: ! 802: return R_AR (start); ! 803: } ! 804: ! 805: /* These routines are used in finding insns to fill delay slots in the ! 806: epilogue. */ ! 807: ! 808: /* Return 1 if the current function will adjust the register stack. */ ! 809: ! 810: int ! 811: needs_regstack_p () ! 812: { ! 813: int i; ! 814: rtx insn; ! 815: ! 816: if (frame_pointer_needed) ! 817: return 1; ! 818: ! 819: /* If any local register is used, we need to adjust the regstack. */ ! 820: for (i = R_LR (127); i >= R_LR (0); i --) ! 821: if (regs_ever_live[i]) ! 822: return 1; ! 823: ! 824: /* We need a register stack if we make any calls. */ ! 825: for (insn = get_insns (); insn; insn = next_insn (insn)) ! 826: if (GET_CODE (insn) == CALL_INSN ! 827: || (GET_CODE (insn) == INSN ! 828: && GET_CODE (PATTERN (insn)) == SEQUENCE ! 829: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) ! 830: return 1; ! 831: ! 832: /* Otherwise, we don't. */ ! 833: return 0; ! 834: } ! 835: ! 836: /* Return 1 if X uses a local register. */ ! 837: ! 838: int ! 839: uses_local_reg_p (x) ! 840: rtx x; ! 841: { ! 842: char *fmt; ! 843: int i, j; ! 844: ! 845: switch (GET_CODE (x)) ! 846: { ! 847: case REG: ! 848: return REGNO (x) >= R_LR (0) && REGNO (x) <= R_FP; ! 849: ! 850: case CONST_INT: ! 851: case CONST: ! 852: case PC: ! 853: case CC0: ! 854: case LABEL_REF: ! 855: case SYMBOL_REF: ! 856: return 0; ! 857: } ! 858: ! 859: fmt = GET_RTX_FORMAT (GET_CODE (x)); ! 860: for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) ! 861: { ! 862: if (fmt[i] == 'e') ! 863: { ! 864: if (uses_local_reg_p (XEXP (x, i))) ! 865: return 1; ! 866: } ! 867: else if (fmt[i] == 'E') ! 868: { ! 869: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 870: if (uses_local_reg_p (XVECEXP (x, i, j))) ! 871: return 1; ! 872: } ! 873: } ! 874: ! 875: return 0; ! 876: } ! 877: ! 878: /* Returns 1 if this function is known to have a null epilogue. */ ! 879: ! 880: int ! 881: null_epilogue () ! 882: { ! 883: return (reload_completed && ! needs_regstack_p () ! 884: && get_frame_size () == 0 ! 885: && current_function_pretend_args_size == 0); ! 886: } ! 887: ! 888: /* Write out the assembler form of an operand. Recognize the following ! 889: special options: ! 890: ! 891: %N means write the low-order 8 bits of the negative of the constant ! 892: %Q means write a QImode operand (truncate constants to 8 bits) ! 893: %M means write the low-order 16 bits of the constant ! 894: %m means write the low-order 16 bits shifted left 16 bits ! 895: %C means write the low-order 8 bits of the complement of the constant ! 896: %b means write `f' is this is a reversed condition, `t' otherwise ! 897: %B means write `t' is this is a reversed condition, `f' otherwise ! 898: %J means write the 29k opcode part for a comparison operation ! 899: %e means write the label with an extra `X' is this is the epilogue ! 900: otherwise the normal label name ! 901: %E means write nothing if this insn has a delay slot, ! 902: a nop unless this is the epilogue label, in which case ! 903: write the first epilogue insn ! 904: %F means write just the normal operand if the insn has a delay slot; ! 905: otherwise, this is a recursive call so output the ! 906: symbol + 4 and write the first prologue insn in the ! 907: delay slot. ! 908: %L means write the register number plus one ("low order" register) ! 909: or the low-order part of a multi-word constant ! 910: %O means write the register number plus two ! 911: %P means write the register number plus three ("low order" of TImode) ! 912: %S means write the number of words in the mode of the operand, ! 913: minus one (for CR) ! 914: %V means write the number of elements in a PARALLEL minus 1 ! 915: %# means write nothing if we have a delay slot, "\n\tnop" otherwise ! 916: %* means write the register name for TPC. */ ! 917: ! 918: void ! 919: print_operand (file, x, code) ! 920: FILE *file; ! 921: rtx x; ! 922: char code; ! 923: { ! 924: char buf[100]; ! 925: ! 926: /* These macros test for integers and extract the low-order bits. */ ! 927: #define INT_P(X) \ ! 928: ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \ ! 929: && GET_MODE (X) == VOIDmode) ! 930: ! 931: #define INT_LOWPART(X) \ ! 932: (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X)) ! 933: ! 934: switch (code) ! 935: { ! 936: case 'Q': ! 937: if (GET_CODE (x) == REG) ! 938: break; ! 939: else if (! INT_P (x)) ! 940: output_operand_lossage ("invalid %%Q value"); ! 941: fprintf (file, "%d", INT_LOWPART (x) & 0xff); ! 942: return; ! 943: ! 944: case 'C': ! 945: if (! INT_P (x)) ! 946: output_operand_lossage ("invalid %%C value"); ! 947: fprintf (file, "%d", (~ INT_LOWPART (x)) & 0xff); ! 948: return; ! 949: ! 950: case 'N': ! 951: if (! INT_P (x)) ! 952: output_operand_lossage ("invalid %%N value"); ! 953: fprintf (file, "%d", (- INT_LOWPART (x)) & 0xff); ! 954: return; ! 955: ! 956: case 'M': ! 957: if (! INT_P (x)) ! 958: output_operand_lossage ("invalid %%M value"); ! 959: fprintf (file, "%d", INT_LOWPART (x) & 0xffff); ! 960: return; ! 961: ! 962: case 'm': ! 963: if (! INT_P (x)) ! 964: output_operand_lossage ("invalid %%m value"); ! 965: fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16); ! 966: return; ! 967: ! 968: case 'b': ! 969: if (GET_CODE (x) == GE) ! 970: fprintf (file, "f"); ! 971: else ! 972: fprintf (file, "t"); ! 973: return; ! 974: ! 975: case 'B': ! 976: if (GET_CODE (x) == GE) ! 977: fprintf (file, "t"); ! 978: else ! 979: fprintf (file, "f"); ! 980: return; ! 981: ! 982: case 'J': ! 983: /* It so happens that the RTX names for the conditions are the same as ! 984: the 29k's insns except for "ne", which requires "neq". */ ! 985: fprintf (file, GET_RTX_NAME (GET_CODE (x))); ! 986: if (GET_CODE (x) == NE) ! 987: fprintf (file, "q"); ! 988: return; ! 989: ! 990: case 'e': ! 991: if (optimize && flag_delayed_branch ! 992: && a29k_last_prologue_insn == 0 && epilogue_operand (x, VOIDmode) ! 993: && dbr_sequence_length () == 0) ! 994: { ! 995: /* We need to output the label number of the last label in the ! 996: function, which is not necessarily X since there might be ! 997: a USE insn in between. First go forward to the last insn, then ! 998: back up to a label. */ ! 999: while (NEXT_INSN (x) != 0) ! 1000: x = NEXT_INSN (x); ! 1001: ! 1002: while (GET_CODE (x) != CODE_LABEL) ! 1003: x = PREV_INSN (x); ! 1004: ! 1005: ASM_GENERATE_INTERNAL_LABEL (buf, "LX", CODE_LABEL_NUMBER (x)); ! 1006: assemble_name (file, buf); ! 1007: } ! 1008: else ! 1009: output_asm_label (x); ! 1010: return; ! 1011: ! 1012: case 'E': ! 1013: if (dbr_sequence_length ()) ! 1014: ; ! 1015: else if (a29k_last_prologue_insn) ! 1016: { ! 1017: fprintf (file, "\n\t%s", a29k_last_prologue_insn); ! 1018: a29k_last_prologue_insn = 0; ! 1019: } ! 1020: else if (optimize && flag_delayed_branch ! 1021: && epilogue_operand (x, VOIDmode)) ! 1022: { ! 1023: fprintf (file, "\n\t%s", a29k_first_epilogue_insn); ! 1024: a29k_first_epilogue_insn_used = 1; ! 1025: } ! 1026: else ! 1027: fprintf (file, "\n\tnop"); ! 1028: return; ! 1029: ! 1030: case 'F': ! 1031: output_addr_const (file, x); ! 1032: if (dbr_sequence_length () == 0) ! 1033: { ! 1034: if (GET_CODE (x) == SYMBOL_REF ! 1035: && ! strcmp (XSTR (x, 0), current_function_name)) ! 1036: fprintf (file, "+4\n\t%s,%d", ! 1037: a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1", ! 1038: a29k_regstack_size * 4); ! 1039: else ! 1040: fprintf (file, "\n\tnop"); ! 1041: } ! 1042: return; ! 1043: ! 1044: case 'L': ! 1045: if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) ! 1046: { ! 1047: union real_extract u; ! 1048: ! 1049: bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u); ! 1050: fprintf (file, "$double1(%.20e)", u.d); ! 1051: } ! 1052: else if (GET_CODE (x) == REG) ! 1053: fprintf (file, "%s", reg_names[REGNO (x) + 1]); ! 1054: else ! 1055: output_operand_lossage ("invalid %%L value"); ! 1056: return; ! 1057: ! 1058: case 'O': ! 1059: if (GET_CODE (x) != REG) ! 1060: output_operand_lossage ("invalid %%O value"); ! 1061: fprintf (file, "%s", reg_names[REGNO (x) + 2]); ! 1062: return; ! 1063: ! 1064: case 'P': ! 1065: if (GET_CODE (x) != REG) ! 1066: output_operand_lossage ("invalid %%P value"); ! 1067: fprintf (file, "%s", reg_names[REGNO (x) + 3]); ! 1068: return; ! 1069: ! 1070: case 'S': ! 1071: fprintf (file, "%d", (GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD)-1); ! 1072: return; ! 1073: ! 1074: case 'V': ! 1075: if (GET_CODE (x) != PARALLEL) ! 1076: output_operand_lossage ("invalid %%V value"); ! 1077: fprintf (file, "%d", XVECLEN (x, 0) - 2); ! 1078: return; ! 1079: ! 1080: case '#': ! 1081: if (dbr_sequence_length () == 0) ! 1082: { ! 1083: if (a29k_last_prologue_insn) ! 1084: { ! 1085: fprintf (file, "\n\t%s", a29k_last_prologue_insn); ! 1086: a29k_last_prologue_insn = 0; ! 1087: } ! 1088: else ! 1089: fprintf (file, "\n\tnop"); ! 1090: } ! 1091: return; ! 1092: ! 1093: case '*': ! 1094: fprintf (file, "%s", reg_names [R_TPC]); ! 1095: return; ! 1096: } ! 1097: ! 1098: if (GET_CODE (x) == REG) ! 1099: fprintf (file, "%s", reg_names [REGNO (x)]); ! 1100: ! 1101: else if (GET_CODE (x) == MEM) ! 1102: output_address (XEXP (x, 0)); ! 1103: ! 1104: else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == SUBREG ! 1105: && GET_CODE (SUBREG_REG (XEXP (x, 0))) == CONST_DOUBLE) ! 1106: { ! 1107: union real_extract u; ! 1108: ! 1109: if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode) ! 1110: fprintf (file, "$float"); ! 1111: else ! 1112: fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0))); ! 1113: bcopy (&CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), &u, sizeof u); ! 1114: fprintf (file, "(%.20e)", u.d); ! 1115: } ! 1116: ! 1117: else if (GET_CODE (x) == CONST_DOUBLE ! 1118: && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ! 1119: { ! 1120: union real_extract u; ! 1121: ! 1122: bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u); ! 1123: fprintf (file, "$%s(%.20e)", ! 1124: GET_MODE (x) == SFmode ? "float" : "double0", u.d); ! 1125: } ! 1126: ! 1127: else ! 1128: output_addr_const (file, x); ! 1129: } ! 1130: ! 1131: /* This page contains routines to output function prolog and epilog code. */ ! 1132: ! 1133: /* Output function prolog code to file FILE. Memory stack size is SIZE. ! 1134: ! 1135: Also sets register names for incoming arguments and frame pointer. */ ! 1136: ! 1137: void ! 1138: output_prolog (file, size) ! 1139: FILE *file; ! 1140: int size; ! 1141: { ! 1142: int makes_calls = 0; ! 1143: int arg_count = 0; ! 1144: rtx insn; ! 1145: int i; ! 1146: unsigned int tag_word; ! 1147: ! 1148: /* See if we make any calls. We need to set lr1 if so. */ ! 1149: for (insn = get_insns (); insn; insn = next_insn (insn)) ! 1150: if (GET_CODE (insn) == CALL_INSN ! 1151: || (GET_CODE (insn) == INSN ! 1152: && GET_CODE (PATTERN (insn)) == SEQUENCE ! 1153: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) ! 1154: { ! 1155: makes_calls = 1; ! 1156: break; ! 1157: } ! 1158: ! 1159: /* Find the highest local register used. */ ! 1160: for (i = R_LR (127); i >= R_LR (0); i--) ! 1161: if (regs_ever_live[i]) ! 1162: break; ! 1163: ! 1164: a29k_regstack_size = i - (R_LR (0) - 1); ! 1165: ! 1166: /* If calling routines, ensure we count lr0 & lr1. */ ! 1167: if (makes_calls && a29k_regstack_size < 2) ! 1168: a29k_regstack_size = 2; ! 1169: ! 1170: /* Count frame pointer and align to 8 byte boundary (even number of ! 1171: registers). */ ! 1172: a29k_regstack_size += frame_pointer_needed; ! 1173: if (a29k_regstack_size & 1) a29k_regstack_size++; ! 1174: ! 1175: /* See how many incoming arguments we have in registers. */ ! 1176: for (i = R_AR (0); i < R_AR (16); i++) ! 1177: if (! fixed_regs[i]) ! 1178: arg_count++; ! 1179: ! 1180: /* The argument count includes the caller's lr0 and lr1. */ ! 1181: arg_count += 2; ! 1182: ! 1183: /* Set the names and numbers of the frame pointer and incoming argument ! 1184: registers. */ ! 1185: ! 1186: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 1187: a29k_debug_reg_map[i] = i; ! 1188: ! 1189: reg_names[FRAME_POINTER_REGNUM] = reg_names[R_LR (a29k_regstack_size - 1)]; ! 1190: a29k_debug_reg_map[FRAME_POINTER_REGNUM] = R_LR (a29k_regstack_size - 1); ! 1191: ! 1192: for (i = 0; i < 16; i++) ! 1193: { ! 1194: reg_names[R_AR (i)] = reg_names[R_LR (a29k_regstack_size + i + 2)]; ! 1195: a29k_debug_reg_map[R_AR (i)] = R_LR (a29k_regstack_size + i + 2); ! 1196: } ! 1197: ! 1198: /* Compute memory stack size. Add in number of bytes that the we should ! 1199: push and pretend the caller did and the size of outgoing arguments. ! 1200: Then round to a doubleword boundary. */ ! 1201: size += (current_function_pretend_args_size ! 1202: + current_function_outgoing_args_size); ! 1203: size = (size + 7) & ~7; ! 1204: ! 1205: /* Write header words. See if one or two word form. */ ! 1206: tag_word = (frame_pointer_needed ? 0x400000 : 0) + (arg_count << 16); ! 1207: ! 1208: if (size / 8 > 0xff) ! 1209: fprintf (file, "\t.word %d, 0x%0x\n", (size / 8) << 2, ! 1210: 0x800000 + tag_word); ! 1211: else ! 1212: fprintf (file, "\t.word 0x%0x\n", tag_word + ((size / 8) << 3)); ! 1213: ! 1214: /* Define the function name. */ ! 1215: assemble_name (file, a29k_function_name); ! 1216: fprintf (file, ":\n"); ! 1217: ! 1218: /* Push the register stack by the proper amount. There are two possible ! 1219: ways to do this. */ ! 1220: if (a29k_regstack_size >= 256/4) ! 1221: fprintf (file, "\tconst %s,%d\n\tsub gr1,gr1,%s\n", ! 1222: reg_names[R_TAV], a29k_regstack_size * 4, reg_names[R_TAV]); ! 1223: else if (a29k_regstack_size) ! 1224: fprintf (file, "\tsub gr1,gr1,%d\n", a29k_regstack_size * 4); ! 1225: ! 1226: /* Test that the registers are available. */ ! 1227: if (a29k_regstack_size) ! 1228: fprintf (file, "\tasgeu V_%sSPILL,gr1,%s\n", ! 1229: TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RAB]); ! 1230: ! 1231: /* Set up frame pointer, if one is needed. */ ! 1232: if (frame_pointer_needed) ! 1233: fprintf (file, "\tsll %s,%s,0\n", reg_names[FRAME_POINTER_REGNUM], ! 1234: reg_names[R_MSP]); ! 1235: ! 1236: /* Make room for any frame space. There are three ways to do this. */ ! 1237: if (size >= 256) ! 1238: { ! 1239: fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size); ! 1240: if (size >= 65536) ! 1241: fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size); ! 1242: if (TARGET_STACK_CHECK) ! 1243: fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]); ! 1244: fprintf (file, "\tsub %s,%s,%s\n", ! 1245: reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]); ! 1246: } ! 1247: else if (size) ! 1248: { ! 1249: if (TARGET_STACK_CHECK) ! 1250: fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]); ! 1251: fprintf (file, "\tsub %s,%s,%d\n", ! 1252: reg_names[R_MSP], reg_names[R_MSP], size); ! 1253: } ! 1254: ! 1255: /* If this routine will make calls, set lr1. If we see an insn that ! 1256: can use a delay slot before a call or jump, save this insn for that ! 1257: slot (this condition is equivalent to seeing if we have an insn that ! 1258: needs delay slots before an insn that has a filled delay slot). */ ! 1259: a29k_last_prologue_insn = 0; ! 1260: if (makes_calls) ! 1261: { ! 1262: i = (a29k_regstack_size + arg_count) * 4; ! 1263: if (i >= 256) ! 1264: fprintf (file, "\tconst %s,%d\n\tadd lr1,gr1,%s\n", ! 1265: reg_names[R_TAV], i, reg_names[R_TAV]); ! 1266: else ! 1267: { ! 1268: if (optimize && flag_delayed_branch) ! 1269: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 1270: { ! 1271: if (GET_CODE (insn) == CODE_LABEL ! 1272: || (GET_CODE (insn) == INSN ! 1273: && GET_CODE (PATTERN (insn)) == SEQUENCE)) ! 1274: break; ! 1275: ! 1276: if (GET_CODE (insn) == NOTE ! 1277: || (GET_CODE (insn) == INSN ! 1278: && (GET_CODE (PATTERN (insn)) == USE ! 1279: || GET_CODE (PATTERN (insn)) == CLOBBER))) ! 1280: continue; ! 1281: ! 1282: if (num_delay_slots (insn) > 0) ! 1283: { ! 1284: a29k_last_prologue_insn = (char *) oballoc (100); ! 1285: sprintf (a29k_last_prologue_insn, "add lr1,gr1,%d", i); ! 1286: break; ! 1287: } ! 1288: } ! 1289: ! 1290: if (a29k_last_prologue_insn == 0) ! 1291: fprintf (file, "\tadd lr1,gr1,%d\n", i); ! 1292: } ! 1293: } ! 1294: ! 1295: /* Compute the first insn of the epilogue. */ ! 1296: a29k_first_epilogue_insn_used = 0; ! 1297: ! 1298: if (size == 0 && a29k_regstack_size == 0 && ! frame_pointer_needed) ! 1299: a29k_first_epilogue_insn = 0; ! 1300: else ! 1301: a29k_first_epilogue_insn = (char *) oballoc (100); ! 1302: ! 1303: if (frame_pointer_needed) ! 1304: sprintf (a29k_first_epilogue_insn, "sll %s,%s,0", ! 1305: reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]); ! 1306: else if (a29k_regstack_size) ! 1307: { ! 1308: if (a29k_regstack_size >= 256 / 4) ! 1309: sprintf (a29k_first_epilogue_insn, "const %s,%d", ! 1310: reg_names[R_TAV], a29k_regstack_size * 4); ! 1311: else ! 1312: sprintf (a29k_first_epilogue_insn, "add gr1,gr1,%d", ! 1313: a29k_regstack_size * 4); ! 1314: } ! 1315: else if (size) ! 1316: { ! 1317: if (size >= 256) ! 1318: sprintf (a29k_first_epilogue_insn, "const %s,%d", ! 1319: reg_names[R_TAV], size); ! 1320: else ! 1321: sprintf (a29k_first_epilogue_insn, "add %s,%s,%d", ! 1322: reg_names[R_MSP], reg_names[R_MSP], size); ! 1323: } ! 1324: } ! 1325: ! 1326: /* Call this after writing what might be the first instruction of the ! 1327: epilogue. If that first insn was used in a delay slot, an intermediate ! 1328: label is written. */ ! 1329: ! 1330: static void ! 1331: check_epilogue_internal_label (file) ! 1332: FILE *file; ! 1333: { ! 1334: rtx insn; ! 1335: ! 1336: if (! a29k_first_epilogue_insn_used) ! 1337: return; ! 1338: ! 1339: for (insn = get_last_insn (); ! 1340: GET_CODE (insn) != CODE_LABEL; ! 1341: insn = PREV_INSN (insn)) ! 1342: ; ! 1343: ! 1344: ASM_OUTPUT_INTERNAL_LABEL (file, "LX", CODE_LABEL_NUMBER (insn)); ! 1345: a29k_first_epilogue_insn_used = 0; ! 1346: } ! 1347: ! 1348: /* Output the epilog of the last procedure to file FILE. SIZE is the memory ! 1349: stack size. The register stack size is in the variable ! 1350: A29K_REGSTACK_SIZE. */ ! 1351: ! 1352: void ! 1353: output_epilog (file, size) ! 1354: FILE *file; ! 1355: int size; ! 1356: { ! 1357: rtx insn; ! 1358: int locals_unavailable = 0; /* True until after first insn ! 1359: after gr1 update. */ ! 1360: ! 1361: /* If we hit a BARRIER before a real insn or CODE_LABEL, we don't ! 1362: need to do anything because we are never jumped to. */ ! 1363: insn = get_last_insn (); ! 1364: if (GET_CODE (insn) == NOTE) ! 1365: insn = prev_nonnote_insn (insn); ! 1366: ! 1367: if (insn && GET_CODE (insn) == BARRIER) ! 1368: return; ! 1369: ! 1370: /* If a frame pointer was needed we must restore the memory stack pointer ! 1371: before adjusting the register stack. */ ! 1372: if (frame_pointer_needed) ! 1373: { ! 1374: fprintf (file, "\tsll %s,%s,0\n", ! 1375: reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]); ! 1376: check_epilogue_internal_label (file); ! 1377: } ! 1378: ! 1379: /* Restore the register stack. There are two ways to do this. */ ! 1380: if (a29k_regstack_size) ! 1381: { ! 1382: if (a29k_regstack_size >= 256/4) ! 1383: { ! 1384: fprintf (file, "\tconst %s,%d\n", ! 1385: reg_names[R_TAV], a29k_regstack_size * 4); ! 1386: check_epilogue_internal_label (file); ! 1387: fprintf (file, "\tadd gr1,gr1,%s\n", reg_names[R_TAV]); ! 1388: } ! 1389: else ! 1390: { ! 1391: fprintf (file, "\tadd gr1,gr1,%d\n", a29k_regstack_size * 4); ! 1392: check_epilogue_internal_label (file); ! 1393: } ! 1394: locals_unavailable = 1; ! 1395: } ! 1396: ! 1397: /* Restore the memory stack pointer if there is no frame pointer. ! 1398: Adjust the size to include any pretend arguments and pushed ! 1399: arguments and round to doubleword boundary. */ ! 1400: size += (current_function_pretend_args_size ! 1401: + current_function_outgoing_args_size); ! 1402: size = (size + 7) & ~7; ! 1403: ! 1404: if (size && ! frame_pointer_needed) ! 1405: { ! 1406: if (size >= 256) ! 1407: { ! 1408: fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size); ! 1409: check_epilogue_internal_label (file); ! 1410: locals_unavailable = 0; ! 1411: if (size >= 65536) ! 1412: fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size); ! 1413: fprintf (file, "\tadd %s,%s,%s\n", ! 1414: reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]); ! 1415: } ! 1416: else ! 1417: { ! 1418: fprintf (file, "\tadd %s,%s,%d\n", ! 1419: reg_names[R_MSP], reg_names[R_MSP], size); ! 1420: check_epilogue_internal_label (file); ! 1421: locals_unavailable = 0; ! 1422: } ! 1423: } ! 1424: ! 1425: if (locals_unavailable) ! 1426: { ! 1427: /* If we have an insn for this delay slot, write it. */ ! 1428: if (current_function_epilogue_delay_list) ! 1429: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), ! 1430: file, 1, -2, 1); ! 1431: else ! 1432: fprintf (file, "\tnop\n"); ! 1433: } ! 1434: ! 1435: fprintf (file, "\tjmpi lr0\n"); ! 1436: if (a29k_regstack_size) ! 1437: fprintf (file, "\tasleu V_%sFILL,lr1,%s\n", ! 1438: TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RFB]); ! 1439: else if (current_function_epilogue_delay_list) ! 1440: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), ! 1441: file, 1, -2, 1); ! 1442: else ! 1443: fprintf (file, "\tnop\n"); ! 1444: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.