|
|
1.1 root 1: /* Subroutines for insn-output.c for Sun SPARC. 1.1.1.3 ! root 2: Copyright (C) 1987, 88, 89, 92, 93, 1994 Free Software Foundation, Inc. 1.1 root 3: Contributed by Michael Tiemann ([email protected]) 1.1.1.3 ! root 4: 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, ! 5: at Cygnus Support. 1.1 root 6: 7: This file is part of GNU CC. 8: 9: GNU CC is free software; you can redistribute it and/or modify 10: it under the terms of the GNU General Public License as published by 11: the Free Software Foundation; either version 2, or (at your option) 12: any later version. 13: 14: GNU CC is distributed in the hope that it will be useful, 15: but WITHOUT ANY WARRANTY; without even the implied warranty of 16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17: GNU General Public License for more details. 18: 19: You should have received a copy of the GNU General Public License 20: along with GNU CC; see the file COPYING. If not, write to 21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 22: 23: #include <stdio.h> 24: #include "config.h" 25: #include "tree.h" 26: #include "rtl.h" 27: #include "regs.h" 28: #include "hard-reg-set.h" 29: #include "real.h" 30: #include "insn-config.h" 31: #include "conditions.h" 32: #include "insn-flags.h" 33: #include "output.h" 34: #include "insn-attr.h" 35: #include "flags.h" 36: #include "expr.h" 37: #include "recog.h" 38: 1.1.1.3 ! root 39: /* 1 if the caller has placed an "unimp" insn immediately after the call. ! 40: This is used in v8 code when calling a function that returns a structure. ! 41: v9 doesn't have this. */ ! 42: ! 43: #define SKIP_CALLERS_UNIMP_P (!TARGET_V9 && current_function_returns_struct) ! 44: 1.1 root 45: /* Global variables for machine-dependent things. */ 46: 1.1.1.3 ! root 47: /* Says what architecture we're compiling for. */ ! 48: enum arch_type sparc_arch_type; ! 49: ! 50: /* Size of frame. Need to know this to emit return insns from leaf procedures. ! 51: ACTUAL_FSIZE is set by compute_frame_size() which is called during the ! 52: reload pass. This is important as the value is later used in insn ! 53: scheduling (to see what can go in a delay slot). ! 54: APPARENT_FSIZE is the size of the stack less the register save area and less ! 55: the outgoing argument area. It is used when saving call preserved regs. */ ! 56: static int apparent_fsize; ! 57: static int actual_fsize; ! 58: 1.1 root 59: /* Save the operands last given to a compare for use when we 60: generate a scc or bcc insn. */ 61: 62: rtx sparc_compare_op0, sparc_compare_op1; 63: 1.1.1.3 ! root 64: /* Count of named arguments (v9 only). ! 65: ??? INIT_CUMULATIVE_ARGS initializes these, and FUNCTION_ARG_ADVANCE ! 66: increments SPARC_ARG_COUNT. They are then used by ! 67: FUNCTION_ARG_CALLEE_COPIES to determine if the argument is really a named ! 68: argument or not. This hack is necessary because the NAMED argument to the ! 69: FUNCTION_ARG_XXX macros is not what it says it is: it does not include the ! 70: last named argument. */ ! 71: ! 72: int sparc_arg_count; ! 73: int sparc_n_named_args; ! 74: 1.1 root 75: /* We may need an epilogue if we spill too many registers. 76: If this is non-zero, then we branch here for the epilogue. */ 77: static rtx leaf_label; 78: 79: #ifdef LEAF_REGISTERS 80: 81: /* Vector to say how input registers are mapped to output 82: registers. FRAME_POINTER_REGNUM cannot be remapped by 83: this function to eliminate it. You must use -fomit-frame-pointer 84: to get that. */ 85: char leaf_reg_remap[] = 86: { 0, 1, 2, 3, 4, 5, 6, 7, 87: -1, -1, -1, -1, -1, -1, 14, -1, 88: -1, -1, -1, -1, -1, -1, -1, -1, 89: 8, 9, 10, 11, 12, 13, -1, 15, 90: 91: 32, 33, 34, 35, 36, 37, 38, 39, 92: 40, 41, 42, 43, 44, 45, 46, 47, 93: 48, 49, 50, 51, 52, 53, 54, 55, 1.1.1.3 ! root 94: 56, 57, 58, 59, 60, 61, 62, 63, ! 95: 64, 65, 66, 67, 68, 69, 70, 71, ! 96: 72, 73, 74, 75, 76, 77, 78, 79, ! 97: 80, 81, 82, 83, 84, 85, 86, 87, ! 98: 88, 89, 90, 91, 92, 93, 94, 95, ! 99: 96, 97, 98, 99}; 1.1 root 100: 1.1.1.2 root 101: #endif 1.1 root 102: 103: /* Name of where we pretend to think the frame pointer points. 104: Normally, this is "%fp", but if we are in a leaf procedure, 1.1.1.3 ! root 105: this is "%sp+something". We record "something" separately as it may be ! 106: too big for reg+constant addressing. */ ! 107: ! 108: static char *frame_base_name; ! 109: static int frame_base_offset; 1.1 root 110: 111: static rtx find_addr_reg (); 1.1.1.3 ! root 112: static void sparc_init_modes (); ! 113: ! 114: /* Option handling. */ ! 115: ! 116: /* Validate and override various options, and do some machine dependent ! 117: initialization. */ ! 118: ! 119: void ! 120: sparc_override_options () ! 121: { ! 122: /* Check for any conflicts in the choice of options. */ ! 123: /* ??? This stuff isn't really usable yet. */ ! 124: ! 125: if (! TARGET_V9) ! 126: { ! 127: if (target_flags & MASK_CODE_MODEL) ! 128: error ("code model support is only available with -mv9"); ! 129: if (TARGET_INT64) ! 130: error ("-mint64 is only available with -mv9"); ! 131: if (TARGET_LONG64) ! 132: error ("-mlong64 is only available with -mv9"); ! 133: if (TARGET_PTR64) ! 134: error ("-mptr64 is only available with -mv9"); ! 135: if (TARGET_ENV32) ! 136: error ("-menv32 is only available with -mv9"); ! 137: if (TARGET_STACK_BIAS) ! 138: error ("-mstack-bias is only available with -mv9"); ! 139: } ! 140: else ! 141: { ! 142: /* ??? Are there any options that aren't usable with v9. ! 143: -munaligned-doubles? */ ! 144: } ! 145: ! 146: /* Check for conflicts in cpu specification. ! 147: If we use -mcpu=xxx, this can be removed. */ 1.1 root 148: 1.1.1.3 ! root 149: if ((TARGET_V8 != 0) + (TARGET_SPARCLITE != 0) + (TARGET_V9 != 0) > 1) ! 150: error ("conflicting architectures defined"); ! 151: ! 152: /* Do various machine dependent initializations. */ ! 153: sparc_init_modes (); ! 154: } ! 155: ! 156: /* Float conversions (v9 only). ! 157: ! 158: The floating point registers cannot hold DImode values because SUBREG's ! 159: on them get the wrong register. "(subreg:SI (reg:DI M int-reg) 0)" is the ! 160: same as "(subreg:SI (reg:DI N float-reg) 1)", but gcc doesn't know how to ! 161: turn the "0" to a "1". Therefore, we must explicitly do the conversions ! 162: to/from int/fp regs. `sparc64_fpconv_stack_slot' is the address of an ! 163: 8 byte stack slot used during the transfer. ! 164: ??? I could have used [%fp-16] but I didn't want to add yet another ! 165: dependence on this. */ ! 166: /* ??? Can we use assign_stack_temp here? */ ! 167: ! 168: static rtx fpconv_stack_temp; ! 169: ! 170: /* Called once for each function. */ ! 171: ! 172: void ! 173: sparc64_init_expanders () ! 174: { ! 175: fpconv_stack_temp = NULL_RTX; ! 176: } ! 177: ! 178: /* Assign a stack temp for fp/int DImode conversions. */ ! 179: ! 180: rtx ! 181: sparc64_fpconv_stack_temp () ! 182: { ! 183: if (fpconv_stack_temp == NULL_RTX) ! 184: fpconv_stack_temp = ! 185: assign_stack_local (DImode, GET_MODE_SIZE (DImode), 0); ! 186: ! 187: return fpconv_stack_temp; ! 188: } ! 189: 1.1 root 190: /* Return non-zero only if OP is a register of mode MODE, 191: or const0_rtx. */ 192: int 193: reg_or_0_operand (op, mode) 194: rtx op; 195: enum machine_mode mode; 196: { 197: if (op == const0_rtx || register_operand (op, mode)) 198: return 1; 1.1.1.3 ! root 199: if (GET_MODE (op) == VOIDmode && GET_CODE (op) == CONST_DOUBLE 1.1 root 200: && CONST_DOUBLE_HIGH (op) == 0 201: && CONST_DOUBLE_LOW (op) == 0) 202: return 1; 1.1.1.2 root 203: if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT 204: && GET_CODE (op) == CONST_DOUBLE 205: && fp_zero_operand (op)) 206: return 1; 1.1 root 207: return 0; 208: } 209: 1.1.1.2 root 210: /* Nonzero if OP is a floating point value with value 0.0. */ 211: int 212: fp_zero_operand (op) 213: rtx op; 214: { 215: REAL_VALUE_TYPE r; 216: 217: REAL_VALUE_FROM_CONST_DOUBLE (r, op); 218: return REAL_VALUES_EQUAL (r, dconst0); 219: } 220: 1.1.1.3 ! root 221: /* Nonzero if OP is an integer register. */ ! 222: ! 223: int ! 224: intreg_operand (op, mode) ! 225: rtx op; ! 226: enum machine_mode mode; ! 227: { ! 228: return (register_operand (op, SImode) ! 229: || (TARGET_V9 && register_operand (op, DImode))); ! 230: } ! 231: ! 232: /* Nonzero if OP is a floating point condition code register. */ ! 233: ! 234: int ! 235: ccfp_reg_operand (op, mode) ! 236: rtx op; ! 237: enum machine_mode mode; ! 238: { ! 239: /* This can happen when recog is called from combine. Op may be a MEM. ! 240: Fail instead of calling abort in this case. */ ! 241: if (GET_CODE (op) != REG || REGNO (op) == 0) ! 242: return 0; ! 243: if (GET_MODE (op) != mode) ! 244: return 0; ! 245: ! 246: #if 0 /* ??? ==> 1 when %fcc1-3 are pseudos first. See gen_compare_reg(). */ ! 247: if (reg_renumber == 0) ! 248: return REGNO (op) >= FIRST_PSEUDO_REGISTER; ! 249: return REGNO_OK_FOR_CCFP_P (REGNO (op)); ! 250: #else ! 251: return (unsigned) REGNO (op) - 96 < 4; ! 252: #endif ! 253: } ! 254: 1.1 root 255: /* Nonzero if OP can appear as the dest of a RESTORE insn. */ 256: int 257: restore_operand (op, mode) 258: rtx op; 259: enum machine_mode mode; 260: { 261: return (GET_CODE (op) == REG && GET_MODE (op) == mode 262: && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32))); 263: } 264: 265: /* Call insn on SPARC can take a PC-relative constant address, or any regular 266: memory address. */ 267: 268: int 269: call_operand (op, mode) 270: rtx op; 271: enum machine_mode mode; 272: { 273: if (GET_CODE (op) != MEM) 274: abort (); 275: op = XEXP (op, 0); 1.1.1.3 ! root 276: return (symbolic_operand (op, mode) || memory_address_p (Pmode, op)); 1.1 root 277: } 278: 279: int 280: call_operand_address (op, mode) 281: rtx op; 282: enum machine_mode mode; 283: { 1.1.1.3 ! root 284: return (symbolic_operand (op, mode) || memory_address_p (Pmode, op)); 1.1 root 285: } 286: 287: /* Returns 1 if OP is either a symbol reference or a sum of a symbol 288: reference and a constant. */ 289: 290: int 291: symbolic_operand (op, mode) 292: register rtx op; 293: enum machine_mode mode; 294: { 295: switch (GET_CODE (op)) 296: { 297: case SYMBOL_REF: 298: case LABEL_REF: 299: return 1; 300: 301: case CONST: 302: op = XEXP (op, 0); 303: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 304: || GET_CODE (XEXP (op, 0)) == LABEL_REF) 305: && GET_CODE (XEXP (op, 1)) == CONST_INT); 306: 307: /* ??? This clause seems to be irrelevant. */ 308: case CONST_DOUBLE: 309: return GET_MODE (op) == mode; 310: 311: default: 312: return 0; 313: } 314: } 315: 316: /* Return truth value of statement that OP is a symbolic memory 317: operand of mode MODE. */ 318: 319: int 320: symbolic_memory_operand (op, mode) 321: rtx op; 322: enum machine_mode mode; 323: { 324: if (GET_CODE (op) == SUBREG) 325: op = SUBREG_REG (op); 326: if (GET_CODE (op) != MEM) 327: return 0; 328: op = XEXP (op, 0); 329: return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST 330: || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); 331: } 332: 1.1.1.3 ! root 333: /* Return 1 if the operand is a data segment reference. This includes ! 334: the readonly data segment, or in other words anything but the text segment. ! 335: This is needed in the medium/anywhere code model on v9. These values ! 336: are accessed with MEDANY_BASE_REG. */ ! 337: ! 338: int ! 339: data_segment_operand (op, mode) ! 340: rtx op; ! 341: enum machine_mode mode; ! 342: { ! 343: switch (GET_CODE (op)) ! 344: { ! 345: case SYMBOL_REF : ! 346: return ! SYMBOL_REF_FLAG (op); ! 347: case PLUS : ! 348: /* Assume canonical format of symbol + constant. */ ! 349: case CONST : ! 350: return data_segment_operand (XEXP (op, 0)); ! 351: default : ! 352: return 0; ! 353: } ! 354: } ! 355: ! 356: /* Return 1 if the operand is a text segment reference. ! 357: This is needed in the medium/anywhere code model on v9. */ ! 358: ! 359: int ! 360: text_segment_operand (op, mode) ! 361: rtx op; ! 362: enum machine_mode mode; ! 363: { ! 364: switch (GET_CODE (op)) ! 365: { ! 366: case LABEL_REF : ! 367: return 1; ! 368: case SYMBOL_REF : ! 369: return SYMBOL_REF_FLAG (op); ! 370: case PLUS : ! 371: /* Assume canonical format of symbol + constant. */ ! 372: case CONST : ! 373: return text_segment_operand (XEXP (op, 0)); ! 374: default : ! 375: return 0; ! 376: } ! 377: } ! 378: 1.1 root 379: /* Return 1 if the operand is either a register or a memory operand that is 380: not symbolic. */ 381: 382: int 383: reg_or_nonsymb_mem_operand (op, mode) 384: register rtx op; 385: enum machine_mode mode; 386: { 387: if (register_operand (op, mode)) 388: return 1; 389: 390: if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode)) 391: return 1; 392: 393: return 0; 394: } 395: 396: int 397: sparc_operand (op, mode) 398: rtx op; 399: enum machine_mode mode; 400: { 401: if (register_operand (op, mode)) 402: return 1; 403: if (GET_CODE (op) == CONST_INT) 404: return SMALL_INT (op); 405: if (GET_MODE (op) != mode) 406: return 0; 407: if (GET_CODE (op) == SUBREG) 408: op = SUBREG_REG (op); 409: if (GET_CODE (op) != MEM) 410: return 0; 411: 412: op = XEXP (op, 0); 413: if (GET_CODE (op) == LO_SUM) 414: return (GET_CODE (XEXP (op, 0)) == REG 415: && symbolic_operand (XEXP (op, 1), Pmode)); 416: return memory_address_p (mode, op); 417: } 418: 419: int 420: move_operand (op, mode) 421: rtx op; 422: enum machine_mode mode; 423: { 424: if (mode == DImode && arith_double_operand (op, mode)) 425: return 1; 426: if (register_operand (op, mode)) 427: return 1; 428: if (GET_CODE (op) == CONST_INT) 429: return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0); 430: 431: if (GET_MODE (op) != mode) 432: return 0; 433: if (GET_CODE (op) == SUBREG) 434: op = SUBREG_REG (op); 435: if (GET_CODE (op) != MEM) 436: return 0; 437: op = XEXP (op, 0); 438: if (GET_CODE (op) == LO_SUM) 439: return (register_operand (XEXP (op, 0), Pmode) 440: && CONSTANT_P (XEXP (op, 1))); 441: return memory_address_p (mode, op); 442: } 443: 444: int 445: move_pic_label (op, mode) 446: rtx op; 447: enum machine_mode mode; 448: { 449: /* Special case for PIC. */ 450: if (flag_pic && GET_CODE (op) == LABEL_REF) 451: return 1; 452: return 0; 453: } 454: 455: int 456: memop (op, mode) 457: rtx op; 458: enum machine_mode mode; 459: { 460: if (GET_CODE (op) == MEM) 461: return (mode == VOIDmode || mode == GET_MODE (op)); 462: return 0; 463: } 464: 465: /* Return truth value of whether OP is EQ or NE. */ 466: 467: int 468: eq_or_neq (op, mode) 469: rtx op; 470: enum machine_mode mode; 471: { 472: return (GET_CODE (op) == EQ || GET_CODE (op) == NE); 473: } 474: 475: /* Return 1 if this is a comparison operator, but not an EQ, NE, GEU, 476: or LTU for non-floating-point. We handle those specially. */ 477: 478: int 479: normal_comp_operator (op, mode) 480: rtx op; 481: enum machine_mode mode; 482: { 483: enum rtx_code code = GET_CODE (op); 484: 485: if (GET_RTX_CLASS (code) != '<') 486: return 0; 487: 488: if (GET_MODE (XEXP (op, 0)) == CCFPmode 489: || GET_MODE (XEXP (op, 0)) == CCFPEmode) 490: return 1; 491: 492: return (code != NE && code != EQ && code != GEU && code != LTU); 493: } 494: 495: /* Return 1 if this is a comparison operator. This allows the use of 496: MATCH_OPERATOR to recognize all the branch insns. */ 497: 498: int 499: noov_compare_op (op, mode) 500: register rtx op; 501: enum machine_mode mode; 502: { 503: enum rtx_code code = GET_CODE (op); 504: 505: if (GET_RTX_CLASS (code) != '<') 506: return 0; 507: 508: if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode) 509: /* These are the only branches which work with CC_NOOVmode. */ 510: return (code == EQ || code == NE || code == GE || code == LT); 511: return 1; 512: } 513: 1.1.1.3 ! root 514: /* Nonzero if OP is a comparison operator suitable for use in v9 ! 515: conditional move or branch on register contents instructions. */ ! 516: ! 517: int ! 518: v9_regcmp_op (op, mode) ! 519: register rtx op; ! 520: enum machine_mode mode; ! 521: { ! 522: enum rtx_code code = GET_CODE (op); ! 523: ! 524: if (GET_RTX_CLASS (code) != '<') ! 525: return 0; ! 526: ! 527: return (code == EQ || code == NE || code == GE || code == LT ! 528: || code == LE || code == GT); ! 529: } ! 530: 1.1 root 531: /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */ 532: 533: int 534: extend_op (op, mode) 535: rtx op; 536: enum machine_mode mode; 537: { 538: return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND; 539: } 540: 541: /* Return nonzero if OP is an operator of mode MODE which can set 542: the condition codes explicitly. We do not include PLUS and MINUS 543: because these require CC_NOOVmode, which we handle explicitly. */ 544: 545: int 546: cc_arithop (op, mode) 547: rtx op; 548: enum machine_mode mode; 549: { 550: if (GET_CODE (op) == AND 551: || GET_CODE (op) == IOR 552: || GET_CODE (op) == XOR) 553: return 1; 554: 555: return 0; 556: } 557: 558: /* Return nonzero if OP is an operator of mode MODE which can bitwise 559: complement its second operand and set the condition codes explicitly. */ 560: 561: int 562: cc_arithopn (op, mode) 563: rtx op; 564: enum machine_mode mode; 565: { 566: /* XOR is not here because combine canonicalizes (xor (not ...) ...) 567: and (xor ... (not ...)) to (not (xor ...)). */ 568: return (GET_CODE (op) == AND 569: || GET_CODE (op) == IOR); 570: } 571: 572: /* Return true if OP is a register, or is a CONST_INT that can fit in a 13 573: bit immediate field. This is an acceptable SImode operand for most 3 574: address instructions. */ 575: 576: int 577: arith_operand (op, mode) 578: rtx op; 579: enum machine_mode mode; 580: { 581: return (register_operand (op, mode) 582: || (GET_CODE (op) == CONST_INT && SMALL_INT (op))); 583: } 584: 1.1.1.3 ! root 585: /* Return true if OP is a register, or is a CONST_INT that can fit in an 11 ! 586: bit immediate field. This is an acceptable SImode operand for the movcc ! 587: instructions. */ ! 588: ! 589: int ! 590: arith11_operand (op, mode) ! 591: rtx op; ! 592: enum machine_mode mode; ! 593: { ! 594: return (register_operand (op, mode) ! 595: || (GET_CODE (op) == CONST_INT ! 596: && ((unsigned) (INTVAL (op) + 0x400) < 0x800))); ! 597: } ! 598: ! 599: /* Return true if OP is a register, or is a CONST_INT that can fit in an 10 ! 600: bit immediate field. This is an acceptable SImode operand for the movrcc ! 601: instructions. */ ! 602: ! 603: int ! 604: arith10_operand (op, mode) ! 605: rtx op; ! 606: enum machine_mode mode; ! 607: { ! 608: return (register_operand (op, mode) ! 609: || (GET_CODE (op) == CONST_INT ! 610: && ((unsigned) (INTVAL (op) + 0x200) < 0x400))); ! 611: } ! 612: ! 613: /* Return true if OP is a register, is a CONST_INT that fits in a 13 bit ! 614: immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit ! 615: immediate field. ! 616: v9: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that 1.1 root 617: can fit in a 13 bit immediate field. This is an acceptable DImode operand 618: for most 3 address instructions. */ 619: 620: int 621: arith_double_operand (op, mode) 622: rtx op; 623: enum machine_mode mode; 624: { 625: return (register_operand (op, mode) 1.1.1.3 ! root 626: || (GET_CODE (op) == CONST_INT && SMALL_INT (op)) ! 627: || (! TARGET_V9 ! 628: && GET_CODE (op) == CONST_DOUBLE ! 629: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 ! 630: && (unsigned) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000) ! 631: || (TARGET_V9 ! 632: && GET_CODE (op) == CONST_DOUBLE 1.1 root 633: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 634: && ((CONST_DOUBLE_HIGH (op) == -1 635: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000) 636: || (CONST_DOUBLE_HIGH (op) == 0 1.1.1.3 ! root 637: && (CONST_DOUBLE_LOW (op) & 0x1000) == 0)))); ! 638: } ! 639: ! 640: /* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that ! 641: can fit in an 11 bit immediate field. This is an acceptable DImode ! 642: operand for the movcc instructions. */ ! 643: /* ??? Replace with arith11_operand? */ ! 644: ! 645: int ! 646: arith11_double_operand (op, mode) ! 647: rtx op; ! 648: enum machine_mode mode; ! 649: { ! 650: return (register_operand (op, mode) ! 651: || (GET_CODE (op) == CONST_DOUBLE ! 652: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) ! 653: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800 ! 654: && ((CONST_DOUBLE_HIGH (op) == -1 ! 655: && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400) ! 656: || (CONST_DOUBLE_HIGH (op) == 0 ! 657: && (CONST_DOUBLE_LOW (op) & 0x400) == 0))) ! 658: || (GET_CODE (op) == CONST_INT ! 659: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) ! 660: && (unsigned) (INTVAL (op) + 0x400) < 0x800)); ! 661: } ! 662: ! 663: /* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that ! 664: can fit in an 10 bit immediate field. This is an acceptable DImode ! 665: operand for the movrcc instructions. */ ! 666: /* ??? Replace with arith10_operand? */ ! 667: ! 668: int ! 669: arith10_double_operand (op, mode) ! 670: rtx op; ! 671: enum machine_mode mode; ! 672: { ! 673: return (register_operand (op, mode) ! 674: || (GET_CODE (op) == CONST_DOUBLE ! 675: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) ! 676: && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400 ! 677: && ((CONST_DOUBLE_HIGH (op) == -1 ! 678: && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200) ! 679: || (CONST_DOUBLE_HIGH (op) == 0 ! 680: && (CONST_DOUBLE_LOW (op) & 0x200) == 0))) 1.1 root 681: || (GET_CODE (op) == CONST_INT 682: && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) 1.1.1.3 ! root 683: && (unsigned) (INTVAL (op) + 0x200) < 0x400)); 1.1 root 684: } 685: 686: /* Return truth value of whether OP is a integer which fits the 687: range constraining immediate operands in most three-address insns, 688: which have a 13 bit immediate field. */ 689: 690: int 691: small_int (op, mode) 692: rtx op; 693: enum machine_mode mode; 694: { 695: return (GET_CODE (op) == CONST_INT && SMALL_INT (op)); 696: } 697: 1.1.1.2 root 698: /* Recognize operand values for the umul instruction. That instruction sign 699: extends immediate values just like all other sparc instructions, but 700: interprets the extended result as an unsigned number. */ 701: 702: int 703: uns_small_int (op, mode) 704: rtx op; 705: enum machine_mode mode; 706: { 707: #if HOST_BITS_PER_WIDE_INT > 32 708: /* All allowed constants will fit a CONST_INT. */ 709: return (GET_CODE (op) == CONST_INT 710: && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000) 711: || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) < 0x100000000L))); 712: #else 713: return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000) 714: || (GET_CODE (op) == CONST_DOUBLE 715: && CONST_DOUBLE_HIGH (op) == 0 716: && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000)); 717: #endif 718: } 719: 720: int 721: uns_arith_operand (op, mode) 722: rtx op; 723: enum machine_mode mode; 724: { 725: return register_operand (op, mode) || uns_small_int (op, mode); 726: } 727: 1.1 root 728: /* Return truth value of statement that OP is a call-clobbered register. */ 729: int 730: clobbered_register (op, mode) 731: rtx op; 732: enum machine_mode mode; 733: { 734: return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]); 735: } 736: 737: /* X and Y are two things to compare using CODE. Emit the compare insn and 1.1.1.3 ! root 738: return the rtx for the cc reg in the proper mode. */ 1.1 root 739: 740: rtx 741: gen_compare_reg (code, x, y) 742: enum rtx_code code; 743: rtx x, y; 744: { 745: enum machine_mode mode = SELECT_CC_MODE (code, x, y); 1.1.1.3 ! root 746: rtx cc_reg; ! 747: ! 748: /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the ! 749: fpcc regs (cse can't tell they're really call clobbered regs and will ! 750: remove a duplicate comparison even if there is an intervening function ! 751: call - it will then try to reload the cc reg via an int reg which is why ! 752: we need the movcc patterns). It is possible to provide the movcc ! 753: patterns by using the ldxfsr/stxfsr v9 insns. I tried it: you need two ! 754: registers (say %g1,%g5) and it takes about 6 insns. A better fix would be ! 755: to tell cse that CCFPE mode registers (even pseudoes) are call ! 756: clobbered. */ ! 757: ! 758: /* ??? This is an experiment. Rather than making changes to cse which may ! 759: or may not be easy/clean, we do our own cse. This is possible because ! 760: we will generate hard registers. Cse knows they're call clobbered (it ! 761: doesn't know the same thing about pseudos). If we guess wrong, no big ! 762: deal, but if we win, great! */ ! 763: ! 764: if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ! 765: #if 1 /* experiment */ ! 766: { ! 767: int reg; ! 768: /* We cycle through the registers to ensure they're all exercised. */ ! 769: static int next_fpcc_reg = 0; ! 770: /* Previous x,y for each fpcc reg. */ ! 771: static rtx prev_args[4][2]; ! 772: ! 773: /* Scan prev_args for x,y. */ ! 774: for (reg = 0; reg < 4; reg++) ! 775: if (prev_args[reg][0] == x && prev_args[reg][1] == y) ! 776: break; ! 777: if (reg == 4) ! 778: { ! 779: reg = next_fpcc_reg; ! 780: prev_args[reg][0] = x; ! 781: prev_args[reg][1] = y; ! 782: next_fpcc_reg = (next_fpcc_reg + 1) & 3; ! 783: } ! 784: cc_reg = gen_rtx (REG, mode, reg + 96); ! 785: } ! 786: #else ! 787: cc_reg = gen_reg_rtx (mode); ! 788: #endif /* ! experiment */ ! 789: else ! 790: cc_reg = gen_rtx (REG, mode, 0); 1.1 root 791: 792: emit_insn (gen_rtx (SET, VOIDmode, cc_reg, 793: gen_rtx (COMPARE, mode, x, y))); 794: 795: return cc_reg; 796: } 1.1.1.3 ! root 797: ! 798: /* This function is used for v9 only. ! 799: CODE is the code for an Scc's comparison. ! 800: OPERANDS[0] is the target of the Scc insn. ! 801: OPERANDS[1] is the value we compare against const0_rtx (which hasn't ! 802: been generated yet). ! 803: ! 804: This function is needed to turn ! 805: ! 806: (set (reg:SI 110) ! 807: (gt (reg:CCX 0 %g0) ! 808: (const_int 0))) ! 809: into ! 810: (set (reg:SI 110) ! 811: (gt:DI (reg:CCX 0 %g0) ! 812: (const_int 0))) ! 813: ! 814: IE: The instruction recognizer needs to see the mode of the comparison to ! 815: find the right instruction. We could use "gt:DI" right in the ! 816: define_expand, but leaving it out allows us to handle DI, SI, etc. ! 817: ! 818: We refer to the global sparc compare operands sparc_compare_op0 and ! 819: sparc_compare_op1. ! 820: ! 821: ??? Some of this is outdated as the scc insns set the mode of the ! 822: comparison now. ! 823: ! 824: ??? We optimize for the case where op1 is 0 and the comparison allows us to ! 825: use the "movrCC" insns. This reduces the generated code from three to two ! 826: insns. This way seems too brute force though. Is there a more elegant way ! 827: to achieve the same effect? ! 828: ! 829: Currently, this function always returns 1. ??? Can it ever fail? */ ! 830: ! 831: int ! 832: gen_v9_scc (compare_code, operands) ! 833: enum rtx_code compare_code; ! 834: register rtx *operands; ! 835: { ! 836: rtx temp; ! 837: ! 838: if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT ! 839: && sparc_compare_op1 == const0_rtx ! 840: && (compare_code == EQ || compare_code == NE ! 841: || compare_code == LT || compare_code == LE ! 842: || compare_code == GT || compare_code == GE)) ! 843: { ! 844: /* Special case for op0 != 0. This can be done with one instruction if ! 845: op0 can be clobbered. We store to a temp, and then clobber the temp, ! 846: but the combiner will remove the first insn. */ ! 847: ! 848: if (compare_code == NE ! 849: && GET_MODE (operands[0]) == DImode ! 850: && GET_MODE (sparc_compare_op0) == DImode) ! 851: { ! 852: emit_insn (gen_rtx (SET, VOIDmode, operands[0], sparc_compare_op0)); ! 853: emit_insn (gen_rtx (SET, VOIDmode, operands[0], ! 854: gen_rtx (IF_THEN_ELSE, VOIDmode, ! 855: gen_rtx (compare_code, DImode, ! 856: sparc_compare_op0, const0_rtx), ! 857: const1_rtx, ! 858: operands[0]))); ! 859: return 1; ! 860: } ! 861: ! 862: emit_insn (gen_rtx (SET, VOIDmode, operands[0], const0_rtx)); ! 863: if (GET_MODE (sparc_compare_op0) != DImode) ! 864: { ! 865: temp = gen_reg_rtx (DImode); ! 866: convert_move (temp, sparc_compare_op0, 0); ! 867: } ! 868: else ! 869: { ! 870: temp = sparc_compare_op0; ! 871: } ! 872: emit_insn (gen_rtx (SET, VOIDmode, operands[0], ! 873: gen_rtx (IF_THEN_ELSE, VOIDmode, ! 874: gen_rtx (compare_code, DImode, ! 875: temp, const0_rtx), ! 876: const1_rtx, ! 877: operands[0]))); ! 878: return 1; ! 879: } ! 880: else ! 881: { ! 882: operands[1] = gen_compare_reg (compare_code, ! 883: sparc_compare_op0, sparc_compare_op1); ! 884: ! 885: switch (GET_MODE (operands[1])) ! 886: { ! 887: case CCmode : ! 888: case CCXmode : ! 889: case CCFPEmode : ! 890: case CCFPmode : ! 891: break; ! 892: default : ! 893: abort (); ! 894: } ! 895: emit_insn (gen_rtx (SET, VOIDmode, operands[0], const0_rtx)); ! 896: emit_insn (gen_rtx (SET, VOIDmode, operands[0], ! 897: gen_rtx (IF_THEN_ELSE, VOIDmode, ! 898: gen_rtx (compare_code, ! 899: GET_MODE (operands[1]), ! 900: operands[1], const0_rtx), ! 901: const1_rtx, operands[0]))); ! 902: return 1; ! 903: } ! 904: } ! 905: ! 906: /* Emit a conditional jump insn for the v9 architecture using comparison code ! 907: CODE and jump target LABEL. ! 908: This function exists to take advantage of the v9 brxx insns. */ ! 909: ! 910: void ! 911: emit_v9_brxx_insn (code, op0, label) ! 912: enum rtx_code code; ! 913: rtx op0, label; ! 914: { ! 915: emit_jump_insn (gen_rtx (SET, VOIDmode, ! 916: pc_rtx, ! 917: gen_rtx (IF_THEN_ELSE, VOIDmode, ! 918: gen_rtx (code, GET_MODE (op0), ! 919: op0, const0_rtx), ! 920: gen_rtx (LABEL_REF, VOIDmode, label), ! 921: pc_rtx))); ! 922: } 1.1 root 923: 924: /* Return nonzero if a return peephole merging return with 925: setting of output register is ok. */ 926: int 927: leaf_return_peephole_ok () 928: { 929: return (actual_fsize == 0); 930: } 931: 932: /* Return nonzero if TRIAL can go into the function epilogue's 933: delay slot. SLOT is the slot we are trying to fill. */ 934: 935: int 936: eligible_for_epilogue_delay (trial, slot) 937: rtx trial; 938: int slot; 939: { 940: rtx pat, src; 941: 942: if (slot >= 1) 943: return 0; 944: if (GET_CODE (trial) != INSN 945: || GET_CODE (PATTERN (trial)) != SET) 946: return 0; 947: if (get_attr_length (trial) != 1) 948: return 0; 949: 950: /* In the case of a true leaf function, anything can go into the delay slot. 951: A delay slot only exists however if the frame size is zero, otherwise 952: we will put an insn to adjust the stack after the return. */ 953: if (leaf_function) 954: { 955: if (leaf_return_peephole_ok ()) 956: return (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE); 957: return 0; 958: } 959: 960: /* Otherwise, only operations which can be done in tandem with 961: a `restore' insn can go into the delay slot. */ 962: pat = PATTERN (trial); 963: if (GET_CODE (SET_DEST (pat)) != REG 964: || REGNO (SET_DEST (pat)) == 0 965: || REGNO (SET_DEST (pat)) >= 32 966: || REGNO (SET_DEST (pat)) < 24) 967: return 0; 968: 969: src = SET_SRC (pat); 970: if (arith_operand (src, GET_MODE (src))) 971: return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode); 972: if (arith_double_operand (src, GET_MODE (src))) 973: return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode); 974: if (GET_CODE (src) == PLUS) 975: { 976: if (register_operand (XEXP (src, 0), SImode) 977: && arith_operand (XEXP (src, 1), SImode)) 978: return 1; 979: if (register_operand (XEXP (src, 1), SImode) 980: && arith_operand (XEXP (src, 0), SImode)) 981: return 1; 982: if (register_operand (XEXP (src, 0), DImode) 983: && arith_double_operand (XEXP (src, 1), DImode)) 984: return 1; 985: if (register_operand (XEXP (src, 1), DImode) 986: && arith_double_operand (XEXP (src, 0), DImode)) 987: return 1; 988: } 989: if (GET_CODE (src) == MINUS 990: && register_operand (XEXP (src, 0), SImode) 991: && small_int (XEXP (src, 1), VOIDmode)) 992: return 1; 993: if (GET_CODE (src) == MINUS 994: && register_operand (XEXP (src, 0), DImode) 995: && !register_operand (XEXP (src, 1), DImode) 996: && arith_double_operand (XEXP (src, 1), DImode)) 997: return 1; 998: return 0; 999: } 1000: 1001: int 1002: short_branch (uid1, uid2) 1003: int uid1, uid2; 1004: { 1005: unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2]; 1006: if (delta + 1024 < 2048) 1007: return 1; 1008: /* warning ("long branch, distance %d", delta); */ 1009: return 0; 1010: } 1011: 1012: /* Return non-zero if REG is not used after INSN. 1013: We assume REG is a reload reg, and therefore does 1014: not live past labels or calls or jumps. */ 1015: int 1016: reg_unused_after (reg, insn) 1017: rtx reg; 1018: rtx insn; 1019: { 1020: enum rtx_code code, prev_code = UNKNOWN; 1021: 1022: while (insn = NEXT_INSN (insn)) 1023: { 1024: if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)]) 1025: return 1; 1026: 1027: code = GET_CODE (insn); 1028: if (GET_CODE (insn) == CODE_LABEL) 1029: return 1; 1030: 1031: if (GET_RTX_CLASS (code) == 'i') 1032: { 1033: rtx set = single_set (insn); 1034: int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set)); 1035: if (set && in_src) 1036: return 0; 1037: if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) 1038: return 1; 1039: if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn))) 1040: return 0; 1041: } 1042: prev_code = code; 1043: } 1044: return 1; 1045: } 1046: 1.1.1.2 root 1047: /* The rtx for the global offset table which is a special form 1048: that *is* a position independent symbolic constant. */ 1049: static rtx pic_pc_rtx; 1050: 1051: /* Ensure that we are not using patterns that are not OK with PIC. */ 1052: 1053: int 1054: check_pic (i) 1055: int i; 1056: { 1057: switch (flag_pic) 1058: { 1059: case 1: 1060: if (GET_CODE (recog_operand[i]) == SYMBOL_REF 1061: || (GET_CODE (recog_operand[i]) == CONST 1062: && ! rtx_equal_p (pic_pc_rtx, recog_operand[i]))) 1063: abort (); 1064: case 2: 1065: default: 1066: return 1; 1067: } 1068: } 1069: 1070: /* Return true if X is an address which needs a temporary register when 1071: reloaded while generating PIC code. */ 1072: 1073: int 1074: pic_address_needs_scratch (x) 1075: rtx x; 1076: { 1077: /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */ 1078: if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS 1079: && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF 1080: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT 1081: && ! SMALL_INT (XEXP (XEXP (x, 0), 1))) 1082: return 1; 1083: 1084: return 0; 1085: } 1086: 1.1 root 1087: /* Legitimize PIC addresses. If the address is already position-independent, 1088: we return ORIG. Newly generated position-independent addresses go into a 1089: reg. This is REG if non zero, otherwise we allocate register(s) as 1.1.1.2 root 1090: necessary. */ 1.1 root 1091: 1092: rtx 1.1.1.2 root 1093: legitimize_pic_address (orig, mode, reg) 1.1 root 1094: rtx orig; 1095: enum machine_mode mode; 1.1.1.2 root 1096: rtx reg; 1.1 root 1097: { 1098: if (GET_CODE (orig) == SYMBOL_REF) 1099: { 1100: rtx pic_ref, address; 1101: rtx insn; 1102: 1103: if (reg == 0) 1104: { 1105: if (reload_in_progress || reload_completed) 1106: abort (); 1107: else 1108: reg = gen_reg_rtx (Pmode); 1109: } 1110: 1111: if (flag_pic == 2) 1112: { 1113: /* If not during reload, allocate another temp reg here for loading 1114: in the address, so that these instructions can be optimized 1115: properly. */ 1116: rtx temp_reg = ((reload_in_progress || reload_completed) 1117: ? reg : gen_reg_rtx (Pmode)); 1118: 1119: /* Must put the SYMBOL_REF inside an UNSPEC here so that cse 1120: won't get confused into thinking that these two instructions 1121: are loading in the true address of the symbol. If in the 1122: future a PIC rtx exists, that should be used instead. */ 1123: emit_insn (gen_rtx (SET, VOIDmode, temp_reg, 1124: gen_rtx (HIGH, Pmode, 1125: gen_rtx (UNSPEC, Pmode, 1126: gen_rtvec (1, orig), 1127: 0)))); 1128: emit_insn (gen_rtx (SET, VOIDmode, temp_reg, 1129: gen_rtx (LO_SUM, Pmode, temp_reg, 1130: gen_rtx (UNSPEC, Pmode, 1131: gen_rtvec (1, orig), 1132: 0)))); 1133: address = temp_reg; 1134: } 1135: else 1136: address = orig; 1137: 1138: pic_ref = gen_rtx (MEM, Pmode, 1139: gen_rtx (PLUS, Pmode, 1140: pic_offset_table_rtx, address)); 1141: current_function_uses_pic_offset_table = 1; 1142: RTX_UNCHANGING_P (pic_ref) = 1; 1143: insn = emit_move_insn (reg, pic_ref); 1144: /* Put a REG_EQUAL note on this insn, so that it can be optimized 1145: by loop. */ 1146: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig, 1147: REG_NOTES (insn)); 1148: return reg; 1149: } 1150: else if (GET_CODE (orig) == CONST) 1151: { 1152: rtx base, offset; 1153: 1154: if (GET_CODE (XEXP (orig, 0)) == PLUS 1155: && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) 1156: return orig; 1157: 1158: if (reg == 0) 1159: { 1160: if (reload_in_progress || reload_completed) 1161: abort (); 1162: else 1163: reg = gen_reg_rtx (Pmode); 1164: } 1165: 1166: if (GET_CODE (XEXP (orig, 0)) == PLUS) 1167: { 1.1.1.2 root 1168: base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); 1.1 root 1169: offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, 1.1.1.2 root 1170: base == reg ? 0 : reg); 1.1 root 1171: } 1172: else 1173: abort (); 1174: 1175: if (GET_CODE (offset) == CONST_INT) 1176: { 1177: if (SMALL_INT (offset)) 1178: return plus_constant_for_output (base, INTVAL (offset)); 1179: else if (! reload_in_progress && ! reload_completed) 1180: offset = force_reg (Pmode, offset); 1181: else 1.1.1.2 root 1182: /* If we reach here, then something is seriously wrong. */ 1.1 root 1183: abort (); 1184: } 1185: return gen_rtx (PLUS, Pmode, base, offset); 1186: } 1187: else if (GET_CODE (orig) == LABEL_REF) 1188: current_function_uses_pic_offset_table = 1; 1189: 1190: return orig; 1191: } 1192: 1193: /* Set up PIC-specific rtl. This should not cause any insns 1194: to be emitted. */ 1195: 1196: void 1197: initialize_pic () 1198: { 1199: } 1200: 1201: /* Emit special PIC prologues and epilogues. */ 1202: 1203: void 1204: finalize_pic () 1205: { 1206: /* The table we use to reference PIC data. */ 1207: rtx global_offset_table; 1208: /* Labels to get the PC in the prologue of this function. */ 1209: rtx l1, l2; 1210: rtx seq; 1211: int orig_flag_pic = flag_pic; 1212: 1213: if (current_function_uses_pic_offset_table == 0) 1214: return; 1215: 1216: if (! flag_pic) 1217: abort (); 1218: 1219: flag_pic = 0; 1220: l1 = gen_label_rtx (); 1221: l2 = gen_label_rtx (); 1222: 1223: start_sequence (); 1224: 1225: emit_label (l1); 1226: /* Note that we pun calls and jumps here! */ 1227: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, 1228: gen_rtvec (2, 1229: gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)), 1230: gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2))))); 1231: emit_label (l2); 1232: 1233: /* Initialize every time through, since we can't easily 1234: know this to be permanent. */ 1235: global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "_GLOBAL_OFFSET_TABLE_"); 1236: pic_pc_rtx = gen_rtx (CONST, Pmode, 1237: gen_rtx (MINUS, Pmode, 1238: global_offset_table, 1239: gen_rtx (CONST, Pmode, 1240: gen_rtx (MINUS, Pmode, 1241: gen_rtx (LABEL_REF, VOIDmode, l1), 1242: pc_rtx)))); 1243: 1.1.1.3 ! root 1244: if (Pmode == DImode) ! 1245: emit_insn (gen_rtx (PARALLEL, VOIDmode, ! 1246: gen_rtvec (2, ! 1247: gen_rtx (SET, VOIDmode, pic_offset_table_rtx, ! 1248: gen_rtx (HIGH, Pmode, pic_pc_rtx)), ! 1249: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 1))))); ! 1250: else ! 1251: emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, ! 1252: gen_rtx (HIGH, Pmode, pic_pc_rtx))); ! 1253: 1.1 root 1254: emit_insn (gen_rtx (SET, VOIDmode, 1255: pic_offset_table_rtx, 1256: gen_rtx (LO_SUM, Pmode, 1257: pic_offset_table_rtx, pic_pc_rtx))); 1258: emit_insn (gen_rtx (SET, VOIDmode, 1259: pic_offset_table_rtx, 1260: gen_rtx (PLUS, Pmode, 1261: pic_offset_table_rtx, gen_rtx (REG, Pmode, 15)))); 1262: /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */ 1263: LABEL_PRESERVE_P (l1) = 1; 1264: LABEL_PRESERVE_P (l2) = 1; 1265: flag_pic = orig_flag_pic; 1266: 1267: seq = gen_sequence (); 1268: end_sequence (); 1269: emit_insn_after (seq, get_insns ()); 1270: 1271: /* Need to emit this whether or not we obey regdecls, 1272: since setjmp/longjmp can cause life info to screw up. */ 1273: emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); 1274: } 1275: 1276: /* Emit insns to move operands[1] into operands[0]. 1277: 1278: Return 1 if we have written out everything that needs to be done to 1279: do the move. Otherwise, return 0 and the caller will emit the move 1.1.1.2 root 1280: normally. */ 1.1 root 1281: 1282: int 1.1.1.2 root 1283: emit_move_sequence (operands, mode) 1.1 root 1284: rtx *operands; 1285: enum machine_mode mode; 1286: { 1287: register rtx operand0 = operands[0]; 1288: register rtx operand1 = operands[1]; 1289: 1.1.1.2 root 1290: if (CONSTANT_P (operand1) && flag_pic 1291: && pic_address_needs_scratch (operand1)) 1292: operands[1] = operand1 = legitimize_pic_address (operand1, mode, 0); 1293: 1.1 root 1294: /* Handle most common case first: storing into a register. */ 1295: if (register_operand (operand0, mode)) 1296: { 1297: if (register_operand (operand1, mode) 1298: || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1)) 1299: || (GET_CODE (operand1) == CONST_DOUBLE 1300: && arith_double_operand (operand1, DImode)) 1301: || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) != DImode) 1302: /* Only `general_operands' can come here, so MEM is ok. */ 1303: || GET_CODE (operand1) == MEM) 1304: { 1305: /* Run this case quickly. */ 1306: emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1)); 1307: return 1; 1308: } 1309: } 1310: else if (GET_CODE (operand0) == MEM) 1311: { 1312: if (register_operand (operand1, mode) || operand1 == const0_rtx) 1313: { 1314: /* Run this case quickly. */ 1315: emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1)); 1316: return 1; 1317: } 1318: if (! reload_in_progress) 1319: { 1320: operands[0] = validize_mem (operand0); 1321: operands[1] = operand1 = force_reg (mode, operand1); 1322: } 1323: } 1324: 1325: /* Simplify the source if we need to. Must handle DImode HIGH operators 1326: here because such a move needs a clobber added. */ 1327: if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) 1328: || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode)) 1329: { 1330: if (flag_pic && symbolic_operand (operand1, mode)) 1331: { 1332: rtx temp_reg = reload_in_progress ? operand0 : 0; 1333: 1.1.1.2 root 1334: operands[1] = legitimize_pic_address (operand1, mode, temp_reg); 1.1 root 1335: } 1336: else if (GET_CODE (operand1) == CONST_INT 1337: ? (! SMALL_INT (operand1) 1338: && (INTVAL (operand1) & 0x3ff) != 0) 1339: : (GET_CODE (operand1) == CONST_DOUBLE 1340: ? ! arith_double_operand (operand1, DImode) 1341: : 1)) 1342: { 1343: /* For DImode values, temp must be operand0 because of the way 1344: HI and LO_SUM work. The LO_SUM operator only copies half of 1345: the LSW from the dest of the HI operator. If the LO_SUM dest is 1346: not the same as the HI dest, then the MSW of the LO_SUM dest will 1347: never be set. 1348: 1349: ??? The real problem here is that the ...(HI:DImode pattern emits 1350: multiple instructions, and the ...(LO_SUM:DImode pattern emits 1351: one instruction. This fails, because the compiler assumes that 1352: LO_SUM copies all bits of the first operand to its dest. Better 1353: would be to have the HI pattern emit one instruction and the 1354: LO_SUM pattern multiple instructions. Even better would be 1355: to use four rtl insns. */ 1356: rtx temp = ((reload_in_progress || mode == DImode) 1357: ? operand0 : gen_reg_rtx (mode)); 1358: 1.1.1.3 ! root 1359: if (TARGET_V9 && mode == DImode) ! 1360: { ! 1361: int high_operand = 0; ! 1362: ! 1363: /* If the operand is already a HIGH, then remove the HIGH so ! 1364: that we won't get duplicate HIGH operators in this insn. ! 1365: Also, we must store the result into the original dest, ! 1366: because that is where the following LO_SUM expects it. */ ! 1367: if (GET_CODE (operand1) == HIGH) ! 1368: { ! 1369: operand1 = XEXP (operand1, 0); ! 1370: high_operand = 1; ! 1371: } ! 1372: ! 1373: emit_insn (gen_rtx (PARALLEL, VOIDmode, ! 1374: gen_rtvec (2, ! 1375: gen_rtx (SET, VOIDmode, temp, ! 1376: gen_rtx (HIGH, mode, operand1)), ! 1377: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, DImode, 1))))); ! 1378: ! 1379: /* If this was a high operand, then we are now finished. */ ! 1380: if (high_operand) ! 1381: return 1; ! 1382: } ! 1383: else ! 1384: emit_insn (gen_rtx (SET, VOIDmode, temp, ! 1385: gen_rtx (HIGH, mode, operand1))); ! 1386: 1.1 root 1387: operands[1] = gen_rtx (LO_SUM, mode, temp, operand1); 1388: } 1389: } 1390: 1391: if (GET_CODE (operand1) == LABEL_REF && flag_pic) 1392: { 1393: /* The procedure for doing this involves using a call instruction to 1394: get the pc into o7. We need to indicate this explicitly because 1395: the tablejump pattern assumes that it can use this value also. */ 1396: emit_insn (gen_rtx (PARALLEL, VOIDmode, 1397: gen_rtvec (2, 1398: gen_rtx (SET, VOIDmode, operand0, 1399: operand1), 1400: gen_rtx (SET, VOIDmode, 1401: gen_rtx (REG, mode, 15), 1402: pc_rtx)))); 1403: return 1; 1404: } 1405: 1406: /* Now have insn-emit do whatever it normally does. */ 1407: return 0; 1408: } 1409: 1410: /* Return the best assembler insn template 1411: for moving operands[1] into operands[0] as a fullword. */ 1412: 1413: char * 1414: singlemove_string (operands) 1415: rtx *operands; 1416: { 1417: if (GET_CODE (operands[0]) == MEM) 1418: { 1419: if (GET_CODE (operands[1]) != MEM) 1420: return "st %r1,%0"; 1421: else 1422: abort (); 1423: } 1424: else if (GET_CODE (operands[1]) == MEM) 1425: return "ld %1,%0"; 1426: else if (GET_CODE (operands[1]) == CONST_DOUBLE) 1427: { 1.1.1.2 root 1428: REAL_VALUE_TYPE r; 1429: long i; 1.1 root 1430: 1431: /* Must be SFmode, otherwise this doesn't make sense. */ 1432: if (GET_MODE (operands[1]) != SFmode) 1433: abort (); 1434: 1.1.1.2 root 1435: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); 1436: REAL_VALUE_TO_TARGET_SINGLE (r, i); 1.1 root 1437: operands[1] = gen_rtx (CONST_INT, VOIDmode, i); 1438: 1439: if (CONST_OK_FOR_LETTER_P (i, 'I')) 1440: return "mov %1,%0"; 1441: else if ((i & 0x000003FF) != 0) 1442: return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0"; 1443: else 1444: return "sethi %%hi(%a1),%0"; 1445: } 1446: else if (GET_CODE (operands[1]) == CONST_INT 1447: && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I')) 1448: { 1449: int i = INTVAL (operands[1]); 1450: 1451: /* If all low order 10 bits are clear, then we only need a single 1452: sethi insn to load the constant. */ 1453: if ((i & 0x000003FF) != 0) 1454: return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0"; 1455: else 1456: return "sethi %%hi(%a1),%0"; 1457: } 1458: /* Operand 1 must be a register, or a 'I' type CONST_INT. */ 1459: return "mov %1,%0"; 1460: } 1461: 1462: /* Return non-zero if it is OK to assume that the given memory operand is 1463: aligned at least to a 8-byte boundary. This should only be called 1464: for memory accesses whose size is 8 bytes or larger. */ 1465: 1466: int 1467: mem_aligned_8 (mem) 1468: register rtx mem; 1469: { 1470: register rtx addr; 1471: register rtx base; 1472: register rtx offset; 1473: 1474: if (GET_CODE (mem) != MEM) 1475: return 0; /* It's gotta be a MEM! */ 1476: 1477: addr = XEXP (mem, 0); 1478: 1479: /* Now that all misaligned double parms are copied on function entry, 1480: we can assume any 64-bit object is 64-bit aligned except those which 1481: are at unaligned offsets from the stack or frame pointer. If the 1482: TARGET_UNALIGNED_DOUBLES switch is given, we do not make this 1483: assumption. */ 1484: 1485: /* See what register we use in the address. */ 1486: base = 0; 1487: if (GET_CODE (addr) == PLUS) 1488: { 1489: if (GET_CODE (XEXP (addr, 0)) == REG 1490: && GET_CODE (XEXP (addr, 1)) == CONST_INT) 1491: { 1492: base = XEXP (addr, 0); 1493: offset = XEXP (addr, 1); 1494: } 1495: } 1496: else if (GET_CODE (addr) == REG) 1497: { 1498: base = addr; 1499: offset = const0_rtx; 1500: } 1501: 1502: /* If it's the stack or frame pointer, check offset alignment. 1503: We can have improper alignment in the function entry code. */ 1504: if (base 1505: && (REGNO (base) == FRAME_POINTER_REGNUM 1506: || REGNO (base) == STACK_POINTER_REGNUM)) 1507: { 1.1.1.3 ! root 1508: if (((INTVAL (offset) - SPARC_STACK_BIAS) & 0x7) == 0) 1.1 root 1509: return 1; 1510: } 1511: /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES 1512: is true, in which case we can only assume that an access is aligned if 1.1.1.3 ! root 1513: it is to a constant address, or the address involves a LO_SUM. ! 1514: ! 1515: We used to assume an address was aligned if MEM_IN_STRUCT_P was true. ! 1516: That assumption was deleted so that gcc generated code can be used with ! 1517: memory allocators that only guarantee 4 byte alignment. */ ! 1518: else if (! TARGET_UNALIGNED_DOUBLES || CONSTANT_P (addr) ! 1519: || GET_CODE (addr) == LO_SUM) 1.1 root 1520: return 1; 1521: 1522: /* An obviously unaligned address. */ 1523: return 0; 1524: } 1525: 1526: enum optype { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP }; 1527: 1528: /* Output assembler code to perform a doubleword move insn 1529: with operands OPERANDS. This is very similar to the following 1530: output_move_quad function. */ 1531: 1532: char * 1533: output_move_double (operands) 1534: rtx *operands; 1535: { 1536: register rtx op0 = operands[0]; 1537: register rtx op1 = operands[1]; 1538: register enum optype optype0; 1539: register enum optype optype1; 1540: rtx latehalf[2]; 1541: rtx addreg0 = 0; 1542: rtx addreg1 = 0; 1.1.1.2 root 1543: int highest_first = 0; 1544: int no_addreg1_decrement = 0; 1.1 root 1545: 1546: /* First classify both operands. */ 1547: 1548: if (REG_P (op0)) 1549: optype0 = REGOP; 1550: else if (offsettable_memref_p (op0)) 1551: optype0 = OFFSOP; 1552: else if (GET_CODE (op0) == MEM) 1553: optype0 = MEMOP; 1554: else 1555: optype0 = RNDOP; 1556: 1557: if (REG_P (op1)) 1558: optype1 = REGOP; 1559: else if (CONSTANT_P (op1)) 1560: optype1 = CNSTOP; 1561: else if (offsettable_memref_p (op1)) 1562: optype1 = OFFSOP; 1563: else if (GET_CODE (op1) == MEM) 1564: optype1 = MEMOP; 1565: else 1566: optype1 = RNDOP; 1567: 1568: /* Check for the cases that the operand constraints are not 1569: supposed to allow to happen. Abort if we get one, 1570: because generating code for these cases is painful. */ 1571: 1572: if (optype0 == RNDOP || optype1 == RNDOP 1573: || (optype0 == MEM && optype1 == MEM)) 1574: abort (); 1575: 1576: /* If an operand is an unoffsettable memory ref, find a register 1577: we can increment temporarily to make it refer to the second word. */ 1578: 1579: if (optype0 == MEMOP) 1580: addreg0 = find_addr_reg (XEXP (op0, 0)); 1581: 1582: if (optype1 == MEMOP) 1583: addreg1 = find_addr_reg (XEXP (op1, 0)); 1584: 1585: /* Ok, we can do one word at a time. 1586: Set up in LATEHALF the operands to use for the 1587: high-numbered (least significant) word and in some cases alter the 1588: operands in OPERANDS to be suitable for the low-numbered word. */ 1589: 1590: if (optype0 == REGOP) 1591: latehalf[0] = gen_rtx (REG, SImode, REGNO (op0) + 1); 1592: else if (optype0 == OFFSOP) 1593: latehalf[0] = adj_offsettable_operand (op0, 4); 1594: else 1595: latehalf[0] = op0; 1596: 1597: if (optype1 == REGOP) 1598: latehalf[1] = gen_rtx (REG, SImode, REGNO (op1) + 1); 1599: else if (optype1 == OFFSOP) 1600: latehalf[1] = adj_offsettable_operand (op1, 4); 1601: else if (optype1 == CNSTOP) 1.1.1.3 ! root 1602: { ! 1603: if (TARGET_V9) ! 1604: { ! 1605: if (arith_double_operand (op1, DImode)) ! 1606: { ! 1607: operands[1] = gen_rtx (CONST_INT, VOIDmode, ! 1608: CONST_DOUBLE_LOW (op1)); ! 1609: return "mov %1,%0"; ! 1610: } ! 1611: else ! 1612: { ! 1613: /* The only way to handle CONST_DOUBLEs or other 64 bit ! 1614: constants here is to use a temporary, such as is done ! 1615: for the V9 DImode sethi insn pattern. This is not ! 1616: a practical solution, so abort if we reach here. ! 1617: The md file should always force such constants to ! 1618: memory. */ ! 1619: abort (); ! 1620: } ! 1621: } ! 1622: else ! 1623: split_double (op1, &operands[1], &latehalf[1]); ! 1624: } 1.1 root 1625: else 1626: latehalf[1] = op1; 1627: 1628: /* Easy case: try moving both words at once. Check for moving between 1629: an even/odd register pair and a memory location. */ 1630: if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP 1.1.1.3 ! root 1631: && (TARGET_V9 || (REGNO (op0) & 1) == 0)) 1.1 root 1632: || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP 1.1.1.3 ! root 1633: && (TARGET_V9 || (REGNO (op1) & 1) == 0))) 1.1 root 1634: { 1.1.1.3 ! root 1635: register rtx mem,reg; 1.1 root 1636: 1637: if (optype0 == REGOP) 1.1.1.3 ! root 1638: mem = op1, reg = op0; 1.1 root 1639: else 1.1.1.3 ! root 1640: mem = op0, reg = op1; 1.1 root 1641: 1.1.1.3 ! root 1642: /* In v9, ldd can be used for word aligned addresses, so technically ! 1643: some of this logic is unneeded. We still avoid ldd if the address ! 1644: is obviously unaligned though. */ ! 1645: ! 1646: if (mem_aligned_8 (mem) ! 1647: /* If this is a floating point register higher than %f31, ! 1648: then we *must* use an aligned load, since `ld' will not accept ! 1649: the register number. */ ! 1650: || (TARGET_V9 && REGNO (reg) >= 64)) ! 1651: { ! 1652: if (FP_REG_P (reg) || ! TARGET_V9) ! 1653: return (mem == op1 ? "ldd %1,%0" : "std %1,%0"); ! 1654: else ! 1655: return (mem == op1 ? "ldx %1,%0" : "stx %1,%0"); ! 1656: } ! 1657: } ! 1658: ! 1659: if (TARGET_V9) ! 1660: { ! 1661: if (optype0 == REGOP && optype1 == REGOP) ! 1662: { ! 1663: if (FP_REG_P (op0)) ! 1664: return "fmovd %1,%0"; ! 1665: else ! 1666: return "mov %1,%0"; ! 1667: } 1.1 root 1668: } 1669: 1670: /* If the first move would clobber the source of the second one, 1671: do them in the other order. */ 1672: 1673: /* Overlapping registers. */ 1674: if (optype0 == REGOP && optype1 == REGOP 1675: && REGNO (op0) == REGNO (latehalf[1])) 1676: { 1677: /* Do that word. */ 1678: output_asm_insn (singlemove_string (latehalf), latehalf); 1679: /* Do low-numbered word. */ 1680: return singlemove_string (operands); 1681: } 1682: /* Loading into a register which overlaps a register used in the address. */ 1683: else if (optype0 == REGOP && optype1 != REGOP 1684: && reg_overlap_mentioned_p (op0, op1)) 1685: { 1.1.1.2 root 1686: /* If both halves of dest are used in the src memory address, 1687: add the two regs and put them in the low reg (op0). 1688: Then it works to load latehalf first. */ 1689: if (reg_mentioned_p (op0, XEXP (op1, 0)) 1690: && reg_mentioned_p (latehalf[0], XEXP (op1, 0))) 1691: { 1692: rtx xops[2]; 1693: xops[0] = latehalf[0]; 1694: xops[1] = op0; 1695: output_asm_insn ("add %1,%0,%1", xops); 1696: operands[1] = gen_rtx (MEM, DImode, op0); 1697: latehalf[1] = adj_offsettable_operand (operands[1], 4); 1698: addreg1 = 0; 1699: highest_first = 1; 1700: } 1701: /* Only one register in the dest is used in the src memory address, 1702: and this is the first register of the dest, so we want to do 1703: the late half first here also. */ 1704: else if (! reg_mentioned_p (latehalf[0], XEXP (op1, 0))) 1705: highest_first = 1; 1706: /* Only one register in the dest is used in the src memory address, 1707: and this is the second register of the dest, so we want to do 1708: the late half last. If addreg1 is set, and addreg1 is the same 1709: register as latehalf, then we must suppress the trailing decrement, 1710: because it would clobber the value just loaded. */ 1711: else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0])) 1712: no_addreg1_decrement = 1; 1.1 root 1713: } 1714: 1.1.1.2 root 1715: /* Normal case: do the two words, low-numbered first. 1716: Overlap case (highest_first set): do high-numbered word first. */ 1.1 root 1717: 1.1.1.2 root 1718: if (! highest_first) 1719: output_asm_insn (singlemove_string (operands), operands); 1.1 root 1720: 1721: /* Make any unoffsettable addresses point at high-numbered word. */ 1722: if (addreg0) 1723: output_asm_insn ("add %0,0x4,%0", &addreg0); 1724: if (addreg1) 1725: output_asm_insn ("add %0,0x4,%0", &addreg1); 1726: 1727: /* Do that word. */ 1728: output_asm_insn (singlemove_string (latehalf), latehalf); 1729: 1730: /* Undo the adds we just did. */ 1731: if (addreg0) 1732: output_asm_insn ("add %0,-0x4,%0", &addreg0); 1.1.1.2 root 1733: if (addreg1 && ! no_addreg1_decrement) 1.1 root 1734: output_asm_insn ("add %0,-0x4,%0", &addreg1); 1735: 1.1.1.2 root 1736: if (highest_first) 1737: output_asm_insn (singlemove_string (operands), operands); 1738: 1.1 root 1739: return ""; 1740: } 1741: 1742: /* Output assembler code to perform a quadword move insn 1743: with operands OPERANDS. This is very similar to the preceding 1744: output_move_double function. */ 1745: 1746: char * 1747: output_move_quad (operands) 1748: rtx *operands; 1749: { 1750: register rtx op0 = operands[0]; 1751: register rtx op1 = operands[1]; 1752: register enum optype optype0; 1753: register enum optype optype1; 1754: rtx wordpart[4][2]; 1755: rtx addreg0 = 0; 1756: rtx addreg1 = 0; 1757: 1758: /* First classify both operands. */ 1759: 1760: if (REG_P (op0)) 1761: optype0 = REGOP; 1762: else if (offsettable_memref_p (op0)) 1763: optype0 = OFFSOP; 1764: else if (GET_CODE (op0) == MEM) 1765: optype0 = MEMOP; 1766: else 1767: optype0 = RNDOP; 1768: 1769: if (REG_P (op1)) 1770: optype1 = REGOP; 1771: else if (CONSTANT_P (op1)) 1772: optype1 = CNSTOP; 1773: else if (offsettable_memref_p (op1)) 1774: optype1 = OFFSOP; 1775: else if (GET_CODE (op1) == MEM) 1776: optype1 = MEMOP; 1777: else 1778: optype1 = RNDOP; 1779: 1780: /* Check for the cases that the operand constraints are not 1781: supposed to allow to happen. Abort if we get one, 1782: because generating code for these cases is painful. */ 1783: 1784: if (optype0 == RNDOP || optype1 == RNDOP 1785: || (optype0 == MEM && optype1 == MEM)) 1786: abort (); 1787: 1788: /* If an operand is an unoffsettable memory ref, find a register 1789: we can increment temporarily to make it refer to the later words. */ 1790: 1791: if (optype0 == MEMOP) 1792: addreg0 = find_addr_reg (XEXP (op0, 0)); 1793: 1794: if (optype1 == MEMOP) 1795: addreg1 = find_addr_reg (XEXP (op1, 0)); 1796: 1797: /* Ok, we can do one word at a time. 1798: Set up in wordpart the operands to use for each word of the arguments. */ 1799: 1800: if (optype0 == REGOP) 1801: { 1802: wordpart[0][0] = gen_rtx (REG, SImode, REGNO (op0) + 0); 1803: wordpart[1][0] = gen_rtx (REG, SImode, REGNO (op0) + 1); 1804: wordpart[2][0] = gen_rtx (REG, SImode, REGNO (op0) + 2); 1805: wordpart[3][0] = gen_rtx (REG, SImode, REGNO (op0) + 3); 1806: } 1807: else if (optype0 == OFFSOP) 1808: { 1809: wordpart[0][0] = adj_offsettable_operand (op0, 0); 1810: wordpart[1][0] = adj_offsettable_operand (op0, 4); 1811: wordpart[2][0] = adj_offsettable_operand (op0, 8); 1812: wordpart[3][0] = adj_offsettable_operand (op0, 12); 1813: } 1814: else 1815: { 1816: wordpart[0][0] = op0; 1817: wordpart[1][0] = op0; 1818: wordpart[2][0] = op0; 1819: wordpart[3][0] = op0; 1820: } 1821: 1822: if (optype1 == REGOP) 1823: { 1824: wordpart[0][1] = gen_rtx (REG, SImode, REGNO (op1) + 0); 1825: wordpart[1][1] = gen_rtx (REG, SImode, REGNO (op1) + 1); 1826: wordpart[2][1] = gen_rtx (REG, SImode, REGNO (op1) + 2); 1827: wordpart[3][1] = gen_rtx (REG, SImode, REGNO (op1) + 3); 1828: } 1829: else if (optype1 == OFFSOP) 1830: { 1831: wordpart[0][1] = adj_offsettable_operand (op1, 0); 1832: wordpart[1][1] = adj_offsettable_operand (op1, 4); 1833: wordpart[2][1] = adj_offsettable_operand (op1, 8); 1834: wordpart[3][1] = adj_offsettable_operand (op1, 12); 1835: } 1836: else if (optype1 == CNSTOP) 1837: { 1.1.1.2 root 1838: REAL_VALUE_TYPE r; 1839: long l[4]; 1840: 1841: /* This only works for TFmode floating point constants. */ 1842: if (GET_CODE (op1) != CONST_DOUBLE || GET_MODE (op1) != TFmode) 1843: abort (); 1844: 1845: REAL_VALUE_FROM_CONST_DOUBLE (r, op1); 1846: REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l); 1847: 1848: wordpart[0][1] = GEN_INT (l[0]); 1849: wordpart[1][1] = GEN_INT (l[1]); 1850: wordpart[2][1] = GEN_INT (l[2]); 1851: wordpart[3][1] = GEN_INT (l[3]); 1.1 root 1852: } 1853: else 1854: { 1855: wordpart[0][1] = op1; 1856: wordpart[1][1] = op1; 1857: wordpart[2][1] = op1; 1858: wordpart[3][1] = op1; 1859: } 1860: 1861: /* Easy case: try moving the quad as two pairs. Check for moving between 1.1.1.3 ! root 1862: an even/odd register pair and a memory location. ! 1863: Also handle new v9 fp regs here. */ 1.1 root 1864: /* ??? Should also handle the case of non-offsettable addresses here. 1865: We can at least do the first pair as a ldd/std, and then do the third 1866: and fourth words individually. */ 1867: if ((optype0 == REGOP && optype1 == OFFSOP && (REGNO (op0) & 1) == 0) 1868: || (optype0 == OFFSOP && optype1 == REGOP && (REGNO (op1) & 1) == 0)) 1869: { 1.1.1.3 ! root 1870: rtx mem, reg; 1.1 root 1871: 1872: if (optype0 == REGOP) 1.1.1.3 ! root 1873: mem = op1, reg = op0; 1.1 root 1874: else 1.1.1.3 ! root 1875: mem = op0, reg = op1; 1.1 root 1876: 1.1.1.3 ! root 1877: if (mem_aligned_8 (mem) ! 1878: /* If this is a floating point register higher than %f31, ! 1879: then we *must* use an aligned load, since `ld' will not accept ! 1880: the register number. */ ! 1881: || (TARGET_V9 && REGNO (reg) >= 64)) 1.1 root 1882: { 1.1.1.3 ! root 1883: if (TARGET_V9 && FP_REG_P (reg)) ! 1884: { ! 1885: if ((REGNO (reg) & 3) != 0) ! 1886: abort (); ! 1887: return (mem == op1 ? "ldq %1,%0" : "stq %1,%0"); ! 1888: } 1.1 root 1889: operands[2] = adj_offsettable_operand (mem, 8); 1890: if (mem == op1) 1.1.1.3 ! root 1891: return TARGET_V9 ? "ldx %1,%0;ldx %2,%R0" : "ldd %1,%0;ldd %2,%S0"; 1.1 root 1892: else 1.1.1.3 ! root 1893: return TARGET_V9 ? "stx %1,%0;stx %R1,%2" : "std %1,%0;std %S1,%2"; 1.1 root 1894: } 1895: } 1896: 1897: /* If the first move would clobber the source of the second one, 1898: do them in the other order. */ 1899: 1900: /* Overlapping registers. */ 1901: if (optype0 == REGOP && optype1 == REGOP 1902: && (REGNO (op0) == REGNO (wordpart[1][3]) 1903: || REGNO (op0) == REGNO (wordpart[1][2]) 1904: || REGNO (op0) == REGNO (wordpart[1][1]))) 1905: { 1906: /* Do fourth word. */ 1907: output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]); 1908: /* Do the third word. */ 1909: output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]); 1910: /* Do the second word. */ 1911: output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]); 1912: /* Do lowest-numbered word. */ 1913: return singlemove_string (wordpart[0]); 1914: } 1915: /* Loading into a register which overlaps a register used in the address. */ 1916: if (optype0 == REGOP && optype1 != REGOP 1917: && reg_overlap_mentioned_p (op0, op1)) 1918: { 1919: /* ??? Not implemented yet. This is a bit complicated, because we 1920: must load which ever part overlaps the address last. If the address 1921: is a double-reg address, then there are two parts which need to 1922: be done last, which is impossible. We would need a scratch register 1923: in that case. */ 1924: abort (); 1925: } 1926: 1927: /* Normal case: move the four words in lowest to higest address order. */ 1928: 1929: output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]); 1930: 1931: /* Make any unoffsettable addresses point at the second word. */ 1932: if (addreg0) 1933: output_asm_insn ("add %0,0x4,%0", &addreg0); 1934: if (addreg1) 1935: output_asm_insn ("add %0,0x4,%0", &addreg1); 1936: 1937: /* Do the second word. */ 1938: output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]); 1939: 1940: /* Make any unoffsettable addresses point at the third word. */ 1941: if (addreg0) 1942: output_asm_insn ("add %0,0x4,%0", &addreg0); 1943: if (addreg1) 1944: output_asm_insn ("add %0,0x4,%0", &addreg1); 1945: 1946: /* Do the third word. */ 1947: output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]); 1948: 1949: /* Make any unoffsettable addresses point at the fourth word. */ 1950: if (addreg0) 1951: output_asm_insn ("add %0,0x4,%0", &addreg0); 1952: if (addreg1) 1953: output_asm_insn ("add %0,0x4,%0", &addreg1); 1954: 1955: /* Do the fourth word. */ 1956: output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]); 1957: 1958: /* Undo the adds we just did. */ 1959: if (addreg0) 1960: output_asm_insn ("add %0,-0xc,%0", &addreg0); 1961: if (addreg1) 1962: output_asm_insn ("add %0,-0xc,%0", &addreg1); 1963: 1964: return ""; 1965: } 1966: 1967: /* Output assembler code to perform a doubleword move insn with operands 1968: OPERANDS, one of which must be a floating point register. */ 1969: 1970: char * 1971: output_fp_move_double (operands) 1972: rtx *operands; 1973: { 1974: if (FP_REG_P (operands[0])) 1975: { 1976: if (FP_REG_P (operands[1])) 1.1.1.3 ! root 1977: { ! 1978: if (TARGET_V9) ! 1979: return "fmovd %1,%0"; ! 1980: else ! 1981: return "fmovs %1,%0\n\tfmovs %R1,%R0"; ! 1982: } 1.1 root 1983: else if (GET_CODE (operands[1]) == REG) 1984: abort (); 1985: else 1986: return output_move_double (operands); 1987: } 1988: else if (FP_REG_P (operands[1])) 1989: { 1990: if (GET_CODE (operands[0]) == REG) 1991: abort (); 1992: else 1993: return output_move_double (operands); 1994: } 1995: else abort (); 1996: } 1997: 1998: /* Output assembler code to perform a quadword move insn with operands 1999: OPERANDS, one of which must be a floating point register. */ 2000: 2001: char * 2002: output_fp_move_quad (operands) 2003: rtx *operands; 2004: { 2005: register rtx op0 = operands[0]; 2006: register rtx op1 = operands[1]; 2007: 2008: if (FP_REG_P (op0)) 2009: { 2010: if (FP_REG_P (op1)) 1.1.1.3 ! root 2011: { ! 2012: if (TARGET_V9) ! 2013: return "fmovq %1,%0"; ! 2014: else ! 2015: return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0"; ! 2016: } 1.1 root 2017: else if (GET_CODE (op1) == REG) 2018: abort (); 2019: else 2020: return output_move_quad (operands); 2021: } 2022: else if (FP_REG_P (op1)) 2023: { 2024: if (GET_CODE (op0) == REG) 2025: abort (); 2026: else 2027: return output_move_quad (operands); 2028: } 2029: else 2030: abort (); 2031: } 2032: 2033: /* Return a REG that occurs in ADDR with coefficient 1. 2034: ADDR can be effectively incremented by incrementing REG. */ 2035: 2036: static rtx 2037: find_addr_reg (addr) 2038: rtx addr; 2039: { 2040: while (GET_CODE (addr) == PLUS) 2041: { 2042: /* We absolutely can not fudge the frame pointer here, because the 2043: frame pointer must always be 8 byte aligned. It also confuses 2044: debuggers. */ 2045: if (GET_CODE (XEXP (addr, 0)) == REG 2046: && REGNO (XEXP (addr, 0)) != FRAME_POINTER_REGNUM) 2047: addr = XEXP (addr, 0); 2048: else if (GET_CODE (XEXP (addr, 1)) == REG 2049: && REGNO (XEXP (addr, 1)) != FRAME_POINTER_REGNUM) 2050: addr = XEXP (addr, 1); 2051: else if (CONSTANT_P (XEXP (addr, 0))) 2052: addr = XEXP (addr, 1); 2053: else if (CONSTANT_P (XEXP (addr, 1))) 2054: addr = XEXP (addr, 0); 2055: else 2056: abort (); 2057: } 2058: if (GET_CODE (addr) == REG) 2059: return addr; 2060: abort (); 2061: } 2062: 1.1.1.2 root 2063: #if 0 /* not currently used */ 2064: 1.1 root 2065: void 2066: output_sized_memop (opname, mode, signedp) 2067: char *opname; 2068: enum machine_mode mode; 2069: int signedp; 2070: { 2071: static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" }; 2072: static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" }; 2073: static char *st_size_suffix[] = { "b", "h", "", "?", "d" }; 2074: char **opnametab, *modename; 2075: 2076: if (opname[0] == 'l') 2077: if (signedp) 2078: opnametab = ld_size_suffix_s; 2079: else 2080: opnametab = ld_size_suffix_u; 2081: else 2082: opnametab = st_size_suffix; 2083: modename = opnametab[GET_MODE_SIZE (mode) >> 1]; 2084: 2085: fprintf (asm_out_file, "\t%s%s", opname, modename); 2086: } 2087: 2088: void 2089: output_move_with_extension (operands) 2090: rtx *operands; 2091: { 2092: if (GET_MODE (operands[2]) == HImode) 2093: output_asm_insn ("sll %2,0x10,%0", operands); 2094: else if (GET_MODE (operands[2]) == QImode) 2095: output_asm_insn ("sll %2,0x18,%0", operands); 2096: else 2097: abort (); 2098: } 1.1.1.2 root 2099: #endif /* not currently used */ 1.1 root 2100: 2101: #if 0 2102: /* ??? These are only used by the movstrsi pattern, but we get better code 2103: in general without that, because emit_block_move can do just as good a 2104: job as this function does when alignment and size are known. When they 2105: aren't known, a call to strcpy may be faster anyways, because it is 2106: likely to be carefully crafted assembly language code, and below we just 2107: do a byte-wise copy. 2108: 2109: Also, emit_block_move expands into multiple read/write RTL insns, which 2110: can then be optimized, whereas our movstrsi pattern can not be optimized 2111: at all. */ 2112: 2113: /* Load the address specified by OPERANDS[3] into the register 2114: specified by OPERANDS[0]. 2115: 2116: OPERANDS[3] may be the result of a sum, hence it could either be: 2117: 2118: (1) CONST 2119: (2) REG 2120: (2) REG + CONST_INT 2121: (3) REG + REG + CONST_INT 2122: (4) REG + REG (special case of 3). 2123: 2124: Note that (3) is not a legitimate address. 2125: All cases are handled here. */ 2126: 2127: void 2128: output_load_address (operands) 2129: rtx *operands; 2130: { 2131: rtx base, offset; 2132: 2133: if (CONSTANT_P (operands[3])) 2134: { 2135: output_asm_insn ("set %3,%0", operands); 2136: return; 2137: } 2138: 2139: if (REG_P (operands[3])) 2140: { 2141: if (REGNO (operands[0]) != REGNO (operands[3])) 2142: output_asm_insn ("mov %3,%0", operands); 2143: return; 2144: } 2145: 2146: if (GET_CODE (operands[3]) != PLUS) 2147: abort (); 2148: 2149: base = XEXP (operands[3], 0); 2150: offset = XEXP (operands[3], 1); 2151: 2152: if (GET_CODE (base) == CONST_INT) 2153: { 2154: rtx tmp = base; 2155: base = offset; 2156: offset = tmp; 2157: } 2158: 2159: if (GET_CODE (offset) != CONST_INT) 2160: { 2161: /* Operand is (PLUS (REG) (REG)). */ 2162: base = operands[3]; 2163: offset = const0_rtx; 2164: } 2165: 2166: if (REG_P (base)) 2167: { 2168: operands[6] = base; 2169: operands[7] = offset; 2170: if (SMALL_INT (offset)) 2171: output_asm_insn ("add %6,%7,%0", operands); 2172: else 2173: output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands); 2174: } 2175: else if (GET_CODE (base) == PLUS) 2176: { 2177: operands[6] = XEXP (base, 0); 2178: operands[7] = XEXP (base, 1); 2179: operands[8] = offset; 2180: 2181: if (SMALL_INT (offset)) 2182: output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands); 2183: else 2184: output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands); 2185: } 2186: else 2187: abort (); 2188: } 2189: 2190: /* Output code to place a size count SIZE in register REG. 2191: ALIGN is the size of the unit of transfer. 2192: 2193: Because block moves are pipelined, we don't include the 2194: first element in the transfer of SIZE to REG. */ 2195: 2196: static void 2197: output_size_for_block_move (size, reg, align) 2198: rtx size, reg; 2199: rtx align; 2200: { 2201: rtx xoperands[3]; 2202: 2203: xoperands[0] = reg; 2204: xoperands[1] = size; 2205: xoperands[2] = align; 2206: if (GET_CODE (size) == REG) 2207: output_asm_insn ("sub %1,%2,%0", xoperands); 2208: else 2209: { 2210: xoperands[1] 2211: = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align)); 2212: output_asm_insn ("set %1,%0", xoperands); 2213: } 2214: } 2215: 2216: /* Emit code to perform a block move. 2217: 2218: OPERANDS[0] is the destination. 2219: OPERANDS[1] is the source. 2220: OPERANDS[2] is the size. 2221: OPERANDS[3] is the alignment safe to use. 2222: OPERANDS[4] is a register we can safely clobber as a temp. */ 2223: 2224: char * 2225: output_block_move (operands) 2226: rtx *operands; 2227: { 2228: /* A vector for our computed operands. Note that load_output_address 2229: makes use of (and can clobber) up to the 8th element of this vector. */ 2230: rtx xoperands[10]; 2231: rtx zoperands[10]; 2232: static int movstrsi_label = 0; 2233: int i; 2234: rtx temp1 = operands[4]; 2235: rtx sizertx = operands[2]; 2236: rtx alignrtx = operands[3]; 2237: int align = INTVAL (alignrtx); 2238: char label3[30], label5[30]; 2239: 2240: xoperands[0] = operands[0]; 2241: xoperands[1] = operands[1]; 2242: xoperands[2] = temp1; 2243: 2244: /* We can't move more than this many bytes at a time because we have only 2245: one register, %g1, to move them through. */ 2246: if (align > UNITS_PER_WORD) 2247: { 2248: align = UNITS_PER_WORD; 2249: alignrtx = gen_rtx (CONST_INT, VOIDmode, UNITS_PER_WORD); 2250: } 2251: 2252: /* We consider 8 ld/st pairs, for a total of 16 inline insns to be 2253: reasonable here. (Actually will emit a maximum of 18 inline insns for 2254: the case of size == 31 and align == 4). */ 2255: 2256: if (GET_CODE (sizertx) == CONST_INT && (INTVAL (sizertx) / align) <= 8 2257: && memory_address_p (QImode, plus_constant_for_output (xoperands[0], 2258: INTVAL (sizertx))) 2259: && memory_address_p (QImode, plus_constant_for_output (xoperands[1], 2260: INTVAL (sizertx)))) 2261: { 2262: int size = INTVAL (sizertx); 2263: int offset = 0; 2264: 2265: /* We will store different integers into this particular RTX. */ 2266: xoperands[2] = rtx_alloc (CONST_INT); 2267: PUT_MODE (xoperands[2], VOIDmode); 2268: 2269: /* This case is currently not handled. Abort instead of generating 2270: bad code. */ 1.1.1.3 ! root 2271: if (align > UNITS_PER_WORD) 1.1 root 2272: abort (); 2273: 1.1.1.3 ! root 2274: if (TARGET_V9 && align >= 8) ! 2275: { ! 2276: for (i = (size >> 3) - 1; i >= 0; i--) ! 2277: { ! 2278: INTVAL (xoperands[2]) = (i << 3) + offset; ! 2279: output_asm_insn ("ldx [%a1+%2],%%g1\n\tstx %%g1,[%a0+%2]", ! 2280: xoperands); ! 2281: } ! 2282: offset += (size & ~0x7); ! 2283: size = size & 0x7; ! 2284: if (size == 0) ! 2285: return ""; ! 2286: } ! 2287: 1.1 root 2288: if (align >= 4) 2289: { 2290: for (i = (size >> 2) - 1; i >= 0; i--) 2291: { 2292: INTVAL (xoperands[2]) = (i << 2) + offset; 2293: output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]", 2294: xoperands); 2295: } 2296: offset += (size & ~0x3); 2297: size = size & 0x3; 2298: if (size == 0) 2299: return ""; 2300: } 2301: 2302: if (align >= 2) 2303: { 2304: for (i = (size >> 1) - 1; i >= 0; i--) 2305: { 2306: INTVAL (xoperands[2]) = (i << 1) + offset; 2307: output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]", 2308: xoperands); 2309: } 2310: offset += (size & ~0x1); 2311: size = size & 0x1; 2312: if (size == 0) 2313: return ""; 2314: } 2315: 2316: if (align >= 1) 2317: { 2318: for (i = size - 1; i >= 0; i--) 2319: { 2320: INTVAL (xoperands[2]) = i + offset; 2321: output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]", 2322: xoperands); 2323: } 2324: return ""; 2325: } 2326: 2327: /* We should never reach here. */ 2328: abort (); 2329: } 2330: 2331: /* If the size isn't known to be a multiple of the alignment, 2332: we have to do it in smaller pieces. If we could determine that 2333: the size was a multiple of 2 (or whatever), we could be smarter 2334: about this. */ 2335: if (GET_CODE (sizertx) != CONST_INT) 2336: align = 1; 2337: else 2338: { 2339: int size = INTVAL (sizertx); 2340: while (size % align) 2341: align >>= 1; 2342: } 2343: 2344: if (align != INTVAL (alignrtx)) 2345: alignrtx = gen_rtx (CONST_INT, VOIDmode, align); 2346: 2347: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++); 2348: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align); 2349: xoperands[5] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++); 2350: 2351: ASM_GENERATE_INTERNAL_LABEL (label3, "Lm", INTVAL (xoperands[3])); 2352: ASM_GENERATE_INTERNAL_LABEL (label5, "Lm", INTVAL (xoperands[5])); 2353: 2354: /* This is the size of the transfer. Emit code to decrement the size 2355: value by ALIGN, and store the result in the temp1 register. */ 2356: output_size_for_block_move (sizertx, temp1, alignrtx); 2357: 2358: /* Must handle the case when the size is zero or negative, so the first thing 2359: we do is compare the size against zero, and only copy bytes if it is 2360: zero or greater. Note that we have already subtracted off the alignment 2361: once, so we must copy 1 alignment worth of bytes if the size is zero 2362: here. 2363: 2364: The SUN assembler complains about labels in branch delay slots, so we 2365: do this before outputting the load address, so that there will always 2366: be a harmless insn between the branch here and the next label emitted 2367: below. */ 2368: 2369: { 2370: char pattern[100]; 2371: 2372: sprintf (pattern, "cmp %%2,0\n\tbl %s", &label5[1]); 2373: output_asm_insn (pattern, xoperands); 2374: } 2375: 2376: zoperands[0] = operands[0]; 2377: zoperands[3] = plus_constant_for_output (operands[0], align); 2378: output_load_address (zoperands); 2379: 2380: /* ??? This might be much faster if the loops below were preconditioned 2381: and unrolled. 2382: 2383: That is, at run time, copy enough bytes one at a time to ensure that the 2384: target and source addresses are aligned to the the largest possible 2385: alignment. Then use a preconditioned unrolled loop to copy say 16 2386: bytes at a time. Then copy bytes one at a time until finish the rest. */ 2387: 2388: /* Output the first label separately, so that it is spaced properly. */ 2389: 2390: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "Lm", INTVAL (xoperands[3])); 2391: 2392: { 2393: char pattern[200]; 1.1.1.3 ! root 2394: register char *ld_suffix = ((align == 1) ? "ub" : (align == 2) ? "uh" ! 2395: : (align == 8 && TARGET_V9) ? "x" : ""); ! 2396: register char *st_suffix = ((align == 1) ? "b" : (align == 2) ? "h" ! 2397: : (align == 8 && TARGET_V9) ? "x" : ""); 1.1 root 2398: 2399: sprintf (pattern, "ld%s [%%1+%%2],%%%%g1\n\tsubcc %%2,%%4,%%2\n\tbge %s\n\tst%s %%%%g1,[%%0+%%2]\n%s:", ld_suffix, &label3[1], st_suffix, &label5[1]); 2400: output_asm_insn (pattern, xoperands); 2401: } 2402: 2403: return ""; 2404: } 2405: #endif 2406: 2407: /* Output reasonable peephole for set-on-condition-code insns. 2408: Note that these insns assume a particular way of defining 2409: labels. Therefore, *both* sparc.h and this function must 2410: be changed if a new syntax is needed. */ 2411: 2412: char * 2413: output_scc_insn (operands, insn) 2414: rtx operands[]; 2415: rtx insn; 2416: { 2417: static char string[100]; 2418: rtx label = 0, next = insn; 2419: int need_label = 0; 2420: 2421: /* Try doing a jump optimization which jump.c can't do for us 2422: because we did not expose that setcc works by using branches. 2423: 2424: If this scc insn is followed by an unconditional branch, then have 2425: the jump insn emitted here jump to that location, instead of to 2426: the end of the scc sequence as usual. */ 2427: 2428: do 2429: { 2430: if (GET_CODE (next) == CODE_LABEL) 2431: label = next; 2432: next = NEXT_INSN (next); 2433: if (next == 0) 2434: break; 2435: } 2436: while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL); 2437: 2438: /* If we are in a sequence, and the following insn is a sequence also, 2439: then just following the current insn's next field will take us to the 2440: first insn of the next sequence, which is the wrong place. We don't 2441: want to optimize with a branch that has had its delay slot filled. 2442: Avoid this by verifying that NEXT_INSN (PREV_INSN (next)) == next 2443: which fails only if NEXT is such a branch. */ 2444: 2445: if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next) 2446: && (! final_sequence || NEXT_INSN (PREV_INSN (next)) == next)) 2447: label = JUMP_LABEL (next); 2448: /* If not optimizing, jump label fields are not set. To be safe, always 2449: check here to whether label is still zero. */ 2450: if (label == 0) 2451: { 2452: label = gen_label_rtx (); 2453: need_label = 1; 2454: } 2455: 2456: LABEL_NUSES (label) += 1; 2457: 2458: operands[2] = label; 2459: 2460: /* If we are in a delay slot, assume it is the delay slot of an fpcc 2461: insn since our type isn't allowed anywhere else. */ 2462: 2463: /* ??? Fpcc instructions no longer have delay slots, so this code is 2464: probably obsolete. */ 2465: 2466: /* The fastest way to emit code for this is an annulled branch followed 2467: by two move insns. This will take two cycles if the branch is taken, 2468: and three cycles if the branch is not taken. 2469: 2470: However, if we are in the delay slot of another branch, this won't work, 2471: because we can't put a branch in the delay slot of another branch. 2472: The above sequence would effectively take 3 or 4 cycles respectively 2473: since a no op would have be inserted between the two branches. 2474: In this case, we want to emit a move, annulled branch, and then the 2475: second move. This sequence always takes 3 cycles, and hence is faster 2476: when we are in a branch delay slot. */ 2477: 2478: if (final_sequence) 2479: { 2480: strcpy (string, "mov 0,%0\n\t"); 1.1.1.3 ! root 2481: strcat (string, output_cbranch (operands[1], 0, 2, 0, 1, 0)); 1.1 root 2482: strcat (string, "\n\tmov 1,%0"); 2483: } 2484: else 2485: { 1.1.1.3 ! root 2486: strcpy (string, output_cbranch (operands[1], 0, 2, 0, 1, 0)); 1.1 root 2487: strcat (string, "\n\tmov 1,%0\n\tmov 0,%0"); 2488: } 2489: 2490: if (need_label) 2491: strcat (string, "\n%l2:"); 2492: 2493: return string; 2494: } 2495: 1.1.1.3 ! root 2496: /* Vectors to keep interesting information about registers where it can easily ! 2497: be got. We use to use the actual mode value as the bit number, but there ! 2498: are more than 32 modes now. Instead we use two tables: one indexed by ! 2499: hard register number, and one indexed by mode. */ ! 2500: ! 2501: /* The purpose of sparc_mode_class is to shrink the range of modes so that ! 2502: they all fit (as bit numbers) in a 32 bit word (again). Each real mode is ! 2503: mapped into one sparc_mode_class mode. */ ! 2504: ! 2505: enum sparc_mode_class { ! 2506: C_MODE, CCFP_MODE, ! 2507: S_MODE, D_MODE, T_MODE, O_MODE, ! 2508: SF_MODE, DF_MODE, TF_MODE, OF_MODE ! 2509: }; 1.1 root 2510: 2511: /* Modes for condition codes. */ 1.1.1.3 ! root 2512: #define C_MODES ((1 << (int) C_MODE) | (1 << (int) CCFP_MODE)) ! 2513: #define CCFP_MODES (1 << (int) CCFP_MODE) ! 2514: ! 2515: /* Modes for single-word and smaller quantities. */ ! 2516: #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE)) ! 2517: ! 2518: /* Modes for double-word and smaller quantities. */ ! 2519: #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE)) ! 2520: ! 2521: /* Modes for quad-word and smaller quantities. */ ! 2522: #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE)) 1.1 root 2523: 2524: /* Modes for single-float quantities. We must allow any single word or 2525: smaller quantity. This is because the fix/float conversion instructions 2526: take integer inputs/outputs from the float registers. */ 2527: #define SF_MODES (S_MODES) 2528: 1.1.1.3 ! root 2529: /* Modes for double-float and smaller quantities. */ ! 2530: #define DF_MODES (S_MODES | D_MODES) 1.1 root 2531: 1.1.1.3 ! root 2532: /* ??? Sparc64 fp regs cannot hold DImode values. */ ! 2533: #define DF_MODES64 (SF_MODES | DF_MODE /* | D_MODE*/) 1.1 root 2534: 1.1.1.3 ! root 2535: /* Modes for double-float only quantities. */ ! 2536: /* ??? Sparc64 fp regs cannot hold DImode values. */ ! 2537: #define DF_ONLY_MODES ((1 << (int) DF_MODE) /*| (1 << (int) D_MODE)*/) ! 2538: ! 2539: /* Modes for double-float and larger quantities. */ ! 2540: #define DF_UP_MODES (DF_ONLY_MODES | TF_ONLY_MODES) ! 2541: ! 2542: /* Modes for quad-float only quantities. */ ! 2543: #define TF_ONLY_MODES (1 << (int) TF_MODE) ! 2544: ! 2545: /* Modes for quad-float and smaller quantities. */ ! 2546: #define TF_MODES (DF_MODES | TF_ONLY_MODES) ! 2547: ! 2548: /* ??? Sparc64 fp regs cannot hold DImode values. */ ! 2549: #define TF_MODES64 (DF_MODES64 | TF_ONLY_MODES) ! 2550: ! 2551: /* Value is 1 if register/mode pair is acceptable on sparc. ! 2552: The funny mixture of D and T modes is because integer operations 1.1 root 2553: do not specially operate on tetra quantities, so non-quad-aligned 2554: registers can hold quadword quantities (except %o4 and %i4 because 2555: they cross fixed registers. */ 2556: 1.1.1.3 ! root 2557: /* This points to either the 32 bit or the 64 bit version. */ ! 2558: int *hard_regno_mode_classes; ! 2559: ! 2560: static int hard_32bit_mode_classes[] = { 1.1 root 2561: C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, 2562: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES, 2563: T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, 2564: T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES, 2565: 2566: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, 2567: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, 2568: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, 1.1.1.3 ! root 2569: TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES, ! 2570: }; ! 2571: ! 2572: static int hard_64bit_mode_classes[] = { ! 2573: C_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, ! 2574: T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, ! 2575: T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, ! 2576: T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, ! 2577: ! 2578: TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, ! 2579: TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, ! 2580: TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, ! 2581: TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, ! 2582: ! 2583: /* The remaining registers do not exist on a non-v9 sparc machine. ! 2584: FP regs f32 to f63. Only the even numbered registers actually exist, ! 2585: and none can hold SFmode/SImode values. */ ! 2586: DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, ! 2587: DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, ! 2588: DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, ! 2589: DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0, ! 2590: ! 2591: /* %fcc[0123] */ ! 2592: CCFP_MODE, CCFP_MODE, CCFP_MODE, CCFP_MODE ! 2593: }; ! 2594: ! 2595: int sparc_mode_class [NUM_MACHINE_MODES]; ! 2596: ! 2597: static void ! 2598: sparc_init_modes () ! 2599: { ! 2600: int i; ! 2601: ! 2602: sparc_arch_type = TARGET_V9 ? ARCH_64BIT : ARCH_32BIT; ! 2603: ! 2604: for (i = 0; i < NUM_MACHINE_MODES; i++) ! 2605: { ! 2606: switch (GET_MODE_CLASS (i)) ! 2607: { ! 2608: case MODE_INT: ! 2609: case MODE_PARTIAL_INT: ! 2610: case MODE_COMPLEX_INT: ! 2611: if (GET_MODE_SIZE (i) <= 4) ! 2612: sparc_mode_class[i] = 1 << (int) S_MODE; ! 2613: else if (GET_MODE_SIZE (i) == 8) ! 2614: sparc_mode_class[i] = 1 << (int) D_MODE; ! 2615: else if (GET_MODE_SIZE (i) == 16) ! 2616: sparc_mode_class[i] = 1 << (int) T_MODE; ! 2617: else if (GET_MODE_SIZE (i) == 32) ! 2618: sparc_mode_class[i] = 1 << (int) O_MODE; ! 2619: else ! 2620: sparc_mode_class[i] = 0; ! 2621: break; ! 2622: case MODE_FLOAT: ! 2623: case MODE_COMPLEX_FLOAT: ! 2624: if (GET_MODE_SIZE (i) <= 4) ! 2625: sparc_mode_class[i] = 1 << (int) SF_MODE; ! 2626: else if (GET_MODE_SIZE (i) == 8) ! 2627: sparc_mode_class[i] = 1 << (int) DF_MODE; ! 2628: else if (GET_MODE_SIZE (i) == 16) ! 2629: sparc_mode_class[i] = 1 << (int) TF_MODE; ! 2630: else if (GET_MODE_SIZE (i) == 32) ! 2631: sparc_mode_class[i] = 1 << (int) OF_MODE; ! 2632: else ! 2633: sparc_mode_class[i] = 0; ! 2634: break; ! 2635: case MODE_CC: ! 2636: default: ! 2637: /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so ! 2638: we must explicitly check for them here. */ ! 2639: if (i == (int) CCFPmode || i == (int) CCFPEmode) ! 2640: sparc_mode_class[i] = 1 << (int) CCFP_MODE; ! 2641: else if (i == (int) CCmode || i == (int) CC_NOOVmode ! 2642: #ifdef SPARCV9 ! 2643: || i == (int) CCXmode ! 2644: || i == (int) CCX_NOOVmode ! 2645: #endif ! 2646: ) ! 2647: sparc_mode_class[i] = 1 << (int) C_MODE; ! 2648: else ! 2649: sparc_mode_class[i] = 0; ! 2650: break; ! 2651: } ! 2652: } ! 2653: ! 2654: if (TARGET_V9) ! 2655: hard_regno_mode_classes = hard_64bit_mode_classes; ! 2656: else ! 2657: hard_regno_mode_classes = hard_32bit_mode_classes; ! 2658: } 1.1 root 2659: 1.1.1.3 ! root 2660: /* Save non call used registers from LOW to HIGH at BASE+OFFSET. ! 2661: N_REGS is the number of 4-byte regs saved thus far. This applies even to ! 2662: v9 int regs as it simplifies the code. */ ! 2663: 1.1 root 2664: #ifdef __GNUC__ 1.1.1.3 ! root 2665: __inline__ 1.1 root 2666: #endif 2667: static int 1.1.1.3 ! root 2668: save_regs (file, low, high, base, offset, n_regs) 1.1 root 2669: FILE *file; 2670: int low, high; 2671: char *base; 2672: int offset; 1.1.1.3 ! root 2673: int n_regs; 1.1 root 2674: { 2675: int i; 2676: 1.1.1.3 ! root 2677: if (TARGET_V9 && high <= 32) ! 2678: { ! 2679: for (i = low; i < high; i++) ! 2680: { ! 2681: if (regs_ever_live[i] && ! call_used_regs[i]) ! 2682: fprintf (file, "\tstx %s,[%s+%d]\n", ! 2683: reg_names[i], base, offset + 4 * n_regs), ! 2684: n_regs += 2; ! 2685: } ! 2686: } ! 2687: else 1.1 root 2688: { 1.1.1.3 ! root 2689: for (i = low; i < high; i += 2) ! 2690: { ! 2691: if (regs_ever_live[i] && ! call_used_regs[i]) ! 2692: if (regs_ever_live[i+1] && ! call_used_regs[i+1]) ! 2693: fprintf (file, "\tstd %s,[%s+%d]\n", ! 2694: reg_names[i], base, offset + 4 * n_regs), ! 2695: n_regs += 2; ! 2696: else ! 2697: fprintf (file, "\tst %s,[%s+%d]\n", ! 2698: reg_names[i], base, offset + 4 * n_regs), ! 2699: n_regs += 2; ! 2700: else if (regs_ever_live[i+1] && ! call_used_regs[i+1]) ! 2701: fprintf (file, "\tst %s,[%s+%d]\n", ! 2702: reg_names[i+1], base, offset + 4 * n_regs + 4), ! 2703: n_regs += 2; ! 2704: } 1.1 root 2705: } 1.1.1.3 ! root 2706: return n_regs; 1.1 root 2707: } 2708: 1.1.1.3 ! root 2709: /* Restore non call used registers from LOW to HIGH at BASE+OFFSET. ! 2710: ! 2711: N_REGS is the number of 4-byte regs saved thus far. This applies even to ! 2712: v9 int regs as it simplifies the code. */ ! 2713: 1.1 root 2714: #ifdef __GNUC__ 1.1.1.3 ! root 2715: __inline__ 1.1 root 2716: #endif 2717: static int 1.1.1.3 ! root 2718: restore_regs (file, low, high, base, offset, n_regs) 1.1 root 2719: FILE *file; 2720: int low, high; 2721: char *base; 2722: int offset; 1.1.1.3 ! root 2723: int n_regs; 1.1 root 2724: { 2725: int i; 2726: 1.1.1.3 ! root 2727: if (TARGET_V9 && high <= 32) 1.1 root 2728: { 1.1.1.3 ! root 2729: for (i = low; i < high; i++) ! 2730: { ! 2731: if (regs_ever_live[i] && ! call_used_regs[i]) ! 2732: fprintf (file, "\tldx [%s+%d], %s\n", ! 2733: base, offset + 4 * n_regs, reg_names[i]), ! 2734: n_regs += 2; ! 2735: } 1.1 root 2736: } 1.1.1.3 ! root 2737: else ! 2738: { ! 2739: for (i = low; i < high; i += 2) ! 2740: { ! 2741: if (regs_ever_live[i] && ! call_used_regs[i]) ! 2742: if (regs_ever_live[i+1] && ! call_used_regs[i+1]) ! 2743: fprintf (file, "\tldd [%s+%d], %s\n", ! 2744: base, offset + 4 * n_regs, reg_names[i]), ! 2745: n_regs += 2; ! 2746: else ! 2747: fprintf (file, "\tld [%s+%d],%s\n", ! 2748: base, offset + 4 * n_regs, reg_names[i]), ! 2749: n_regs += 2; ! 2750: else if (regs_ever_live[i+1] && ! call_used_regs[i+1]) ! 2751: fprintf (file, "\tld [%s+%d],%s\n", ! 2752: base, offset + 4 * n_regs + 4, reg_names[i+1]), ! 2753: n_regs += 2; ! 2754: } ! 2755: } ! 2756: return n_regs; 1.1 root 2757: } 2758: 2759: /* Static variables we want to share between prologue and epilogue. */ 2760: 1.1.1.3 ! root 2761: /* Number of live general or floating point registers needed to be saved ! 2762: (as 4-byte quantities). This is only done if TARGET_EPILOGUE. */ ! 2763: static int num_gfregs; ! 2764: ! 2765: /* Compute the frame size required by the function. This function is called ! 2766: during the reload pass and also by output_function_prologue(). */ 1.1 root 2767: 2768: int 2769: compute_frame_size (size, leaf_function) 2770: int size; 2771: int leaf_function; 2772: { 1.1.1.3 ! root 2773: int n_regs = 0, i; 1.1 root 2774: int outgoing_args_size = (current_function_outgoing_args_size 1.1.1.3 ! root 2775: #ifndef SPARCV9 ! 2776: + REG_PARM_STACK_SPACE (current_function_decl) ! 2777: #endif ! 2778: ); 1.1 root 2779: 1.1.1.3 ! root 2780: if (TARGET_EPILOGUE) 1.1 root 2781: { 1.1.1.3 ! root 2782: /* N_REGS is the number of 4-byte regs saved thus far. This applies ! 2783: even to v9 int regs to be consistent with save_regs/restore_regs. */ ! 2784: ! 2785: if (TARGET_V9) ! 2786: { ! 2787: for (i = 0; i < 8; i++) ! 2788: if (regs_ever_live[i] && ! call_used_regs[i]) ! 2789: n_regs += 2; ! 2790: } ! 2791: else ! 2792: { ! 2793: for (i = 0; i < 8; i += 2) ! 2794: if ((regs_ever_live[i] && ! call_used_regs[i]) ! 2795: || (regs_ever_live[i+1] && ! call_used_regs[i+1])) ! 2796: n_regs += 2; ! 2797: } ! 2798: ! 2799: for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2) 1.1 root 2800: if ((regs_ever_live[i] && ! call_used_regs[i]) 2801: || (regs_ever_live[i+1] && ! call_used_regs[i+1])) 1.1.1.3 ! root 2802: n_regs += 2; 1.1 root 2803: } 2804: 2805: /* Set up values for use in `function_epilogue'. */ 1.1.1.3 ! root 2806: num_gfregs = n_regs; 1.1 root 2807: 1.1.1.3 ! root 2808: if (leaf_function && n_regs == 0 ! 2809: && size == 0 && current_function_outgoing_args_size == 0) ! 2810: { ! 2811: actual_fsize = apparent_fsize = 0; ! 2812: } ! 2813: else ! 2814: { ! 2815: /* We subtract STARTING_FRAME_OFFSET, remember it's negative. ! 2816: The stack bias (if any) is taken out to undo its effects. */ ! 2817: apparent_fsize = (size - STARTING_FRAME_OFFSET + SPARC_STACK_BIAS + 7) & -8; ! 2818: apparent_fsize += n_regs * 4; ! 2819: actual_fsize = apparent_fsize + ((outgoing_args_size + 7) & -8); ! 2820: } 1.1 root 2821: 2822: /* Make sure nothing can clobber our register windows. 2823: If a SAVE must be done, or there is a stack-local variable, 1.1.1.3 ! root 2824: the register window area must be allocated. ! 2825: ??? For v9 we need an additional 8 bytes of reserved space, apparently ! 2826: it's needed by v8 as well. */ 1.1 root 2827: if (leaf_function == 0 || size > 0) 1.1.1.3 ! root 2828: actual_fsize += (16 * UNITS_PER_WORD) + 8; 1.1 root 2829: 1.1.1.3 ! root 2830: return SPARC_STACK_ALIGN (actual_fsize); ! 2831: } ! 2832: ! 2833: /* Build a (32 bit) big number in a register. */ ! 2834: /* ??? We may be able to use the set macro here too. */ ! 2835: ! 2836: static void ! 2837: build_big_number (file, num, reg) ! 2838: FILE *file; ! 2839: int num; ! 2840: char *reg; ! 2841: { ! 2842: if (num >= 0 || ! TARGET_V9) ! 2843: { ! 2844: fprintf (file, "\tsethi %%hi(%d),%s\n", num, reg); ! 2845: if ((num & 0x3ff) != 0) ! 2846: fprintf (file, "\tor %s,%%lo(%d),%s\n", reg, num, reg); ! 2847: } ! 2848: else /* num < 0 && TARGET_V9 */ ! 2849: { ! 2850: /* Sethi does not sign extend, so we must use a little trickery ! 2851: to use it for negative numbers. Invert the constant before ! 2852: loading it in, then use xor immediate to invert the loaded bits ! 2853: (along with the upper 32 bits) to the desired constant. This ! 2854: works because the sethi and immediate fields overlap. */ ! 2855: int asize = num; ! 2856: int inv = ~asize; ! 2857: int low = -0x400 + (asize & 0x3FF); ! 2858: ! 2859: fprintf (file, "\tsethi %%hi(%d),%s\n\txor %s,%d,%s\n", ! 2860: inv, reg, reg, low, reg); ! 2861: } 1.1 root 2862: } 2863: 2864: /* Output code for the function prologue. */ 2865: 2866: void 2867: output_function_prologue (file, size, leaf_function) 2868: FILE *file; 2869: int size; 2870: int leaf_function; 2871: { 2872: /* Need to use actual_fsize, since we are also allocating 2873: space for our callee (and our own register save area). */ 2874: actual_fsize = compute_frame_size (size, leaf_function); 2875: 1.1.1.3 ! root 2876: if (leaf_function) ! 2877: { ! 2878: frame_base_name = "%sp"; ! 2879: frame_base_offset = actual_fsize + SPARC_STACK_BIAS; ! 2880: } ! 2881: else ! 2882: { ! 2883: frame_base_name = "%fp"; ! 2884: frame_base_offset = SPARC_STACK_BIAS; ! 2885: } ! 2886: ! 2887: /* This is only for the human reader. */ 1.1 root 2888: fprintf (file, "\t!#PROLOGUE# 0\n"); 1.1.1.3 ! root 2889: 1.1 root 2890: if (actual_fsize == 0) 2891: /* do nothing. */ ; 2892: else if (actual_fsize <= 4096) 2893: { 2894: if (! leaf_function) 2895: fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize); 2896: else 2897: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize); 2898: } 2899: else if (actual_fsize <= 8192) 2900: { 2901: /* For frames in the range 4097..8192, we can use just two insns. */ 2902: if (! leaf_function) 2903: { 2904: fprintf (file, "\tsave %%sp,-4096,%%sp\n"); 2905: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096); 2906: } 2907: else 2908: { 2909: fprintf (file, "\tadd %%sp,-4096,%%sp\n"); 2910: fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096); 2911: } 2912: } 2913: else 2914: { 1.1.1.3 ! root 2915: build_big_number (file, -actual_fsize, "%g1"); 1.1 root 2916: if (! leaf_function) 1.1.1.3 ! root 2917: fprintf (file, "\tsave %%sp,%%g1,%%sp\n"); 1.1 root 2918: else 1.1.1.3 ! root 2919: fprintf (file, "\tadd %%sp,%%g1,%%sp\n"); 1.1 root 2920: } 2921: 2922: /* If doing anything with PIC, do it now. */ 2923: if (! flag_pic) 2924: fprintf (file, "\t!#PROLOGUE# 1\n"); 2925: 1.1.1.3 ! root 2926: /* Call saved registers are saved just above the outgoing argument area. */ ! 2927: if (num_gfregs) 1.1 root 2928: { 1.1.1.3 ! root 2929: int offset, n_regs; ! 2930: char *base; 1.1 root 2931: 1.1.1.3 ! root 2932: offset = -apparent_fsize + frame_base_offset; ! 2933: if (offset < -4096 || offset + num_gfregs * 4 > 4096) ! 2934: { ! 2935: /* ??? This might be optimized a little as %g1 might already have a ! 2936: value close enough that a single add insn will do. */ ! 2937: /* ??? Although, all of this is probably only a temporary fix ! 2938: because if %g1 can hold a function result, then ! 2939: output_function_epilogue will lose (the result will get ! 2940: clobbered). */ ! 2941: build_big_number (file, offset, "%g1"); ! 2942: fprintf (file, "\tadd %s,%%g1,%%g1\n", frame_base_name); ! 2943: base = "%g1"; ! 2944: offset = 0; ! 2945: } 1.1 root 2946: else 1.1.1.3 ! root 2947: { ! 2948: base = frame_base_name; ! 2949: } 1.1 root 2950: 2951: if (TARGET_EPILOGUE && ! leaf_function) 1.1.1.3 ! root 2952: /* ??? Originally saved regs 0-15 here. */ ! 2953: n_regs = save_regs (file, 0, 8, base, offset, 0); 1.1 root 2954: else if (leaf_function) 1.1.1.3 ! root 2955: /* ??? Originally saved regs 0-31 here. */ ! 2956: n_regs = save_regs (file, 0, 8, base, offset, 0); 1.1 root 2957: if (TARGET_EPILOGUE) 1.1.1.3 ! root 2958: save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs); 1.1 root 2959: } 2960: 2961: leaf_label = 0; 2962: if (leaf_function && actual_fsize != 0) 2963: { 2964: /* warning ("leaf procedure with frame size %d", actual_fsize); */ 2965: if (! TARGET_EPILOGUE) 2966: leaf_label = gen_label_rtx (); 2967: } 2968: } 2969: 2970: /* Output code for the function epilogue. */ 2971: 2972: void 2973: output_function_epilogue (file, size, leaf_function) 2974: FILE *file; 2975: int size; 2976: int leaf_function; 2977: { 2978: char *ret; 2979: 2980: if (leaf_label) 2981: { 2982: emit_label_after (leaf_label, get_last_insn ()); 2983: final_scan_insn (get_last_insn (), file, 0, 0, 1); 2984: } 2985: 1.1.1.3 ! root 2986: /* Restore any call saved registers. */ ! 2987: if (num_gfregs) 1.1 root 2988: { 1.1.1.3 ! root 2989: int offset, n_regs; ! 2990: char *base; 1.1 root 2991: 1.1.1.3 ! root 2992: offset = -apparent_fsize + frame_base_offset; ! 2993: if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/) ! 2994: { ! 2995: build_big_number (file, offset, "%g1"); ! 2996: fprintf (file, "\tadd %s,%%g1,%%g1\n", frame_base_name); ! 2997: base = "%g1"; ! 2998: offset = 0; ! 2999: } 1.1 root 3000: else 1.1.1.3 ! root 3001: { ! 3002: base = frame_base_name; ! 3003: } 1.1 root 3004: 3005: if (TARGET_EPILOGUE && ! leaf_function) 1.1.1.3 ! root 3006: /* ??? Originally saved regs 0-15 here. */ ! 3007: n_regs = restore_regs (file, 0, 8, base, offset, 0); 1.1 root 3008: else if (leaf_function) 1.1.1.3 ! root 3009: /* ??? Originally saved regs 0-31 here. */ ! 3010: n_regs = restore_regs (file, 0, 8, base, offset, 0); 1.1 root 3011: if (TARGET_EPILOGUE) 1.1.1.3 ! root 3012: restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs); 1.1 root 3013: } 3014: 3015: /* Work out how to skip the caller's unimp instruction if required. */ 3016: if (leaf_function) 1.1.1.3 ! root 3017: ret = (SKIP_CALLERS_UNIMP_P ? "jmp %o7+12" : "retl"); 1.1 root 3018: else 1.1.1.3 ! root 3019: ret = (SKIP_CALLERS_UNIMP_P ? "jmp %i7+12" : "ret"); 1.1 root 3020: 3021: if (TARGET_EPILOGUE || leaf_label) 3022: { 3023: int old_target_epilogue = TARGET_EPILOGUE; 3024: target_flags &= ~old_target_epilogue; 3025: 3026: if (! leaf_function) 3027: { 3028: /* If we wound up with things in our delay slot, flush them here. */ 3029: if (current_function_epilogue_delay_list) 3030: { 3031: rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode), 3032: get_last_insn ()); 3033: PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode, 3034: gen_rtvec (2, 3035: PATTERN (XEXP (current_function_epilogue_delay_list, 0)), 3036: PATTERN (insn))); 3037: final_scan_insn (insn, file, 1, 0, 1); 3038: } 3039: else 3040: fprintf (file, "\t%s\n\trestore\n", ret); 3041: } 3042: /* All of the following cases are for leaf functions. */ 3043: else if (current_function_epilogue_delay_list) 3044: { 3045: /* eligible_for_epilogue_delay_slot ensures that if this is a 3046: leaf function, then we will only have insn in the delay slot 3047: if the frame size is zero, thus no adjust for the stack is 3048: needed here. */ 3049: if (actual_fsize != 0) 3050: abort (); 3051: fprintf (file, "\t%s\n", ret); 3052: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), 3053: file, 1, 0, 1); 3054: } 3055: /* Output 'nop' instead of 'sub %sp,-0,%sp' when no frame, so as to 3056: avoid generating confusing assembly language output. */ 3057: else if (actual_fsize == 0) 3058: fprintf (file, "\t%s\n\tnop\n", ret); 3059: else if (actual_fsize <= 4096) 3060: fprintf (file, "\t%s\n\tsub %%sp,-%d,%%sp\n", ret, actual_fsize); 3061: else if (actual_fsize <= 8192) 3062: fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%sp,-%d,%%sp\n", 3063: ret, actual_fsize - 4096); 3064: else if ((actual_fsize & 0x3ff) == 0) 3065: fprintf (file, "\tsethi %%hi(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n", 3066: actual_fsize, ret); 3067: else 3068: fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n", 3069: actual_fsize, actual_fsize, ret); 3070: target_flags |= old_target_epilogue; 3071: } 3072: } 3073: 1.1.1.3 ! root 3074: /* Do what is necessary for `va_start'. The argument is ignored. ! 3075: !v9: We look at the current function to determine if stdarg or varargs ! 3076: is used and return the address of the first unnamed parameter. ! 3077: v9: We save the argument integer and floating point regs in a buffer, and ! 3078: return the address of this buffer. The rest is handled in va-sparc.h. */ ! 3079: /* ??? This is currently conditioned on #ifdef SPARCV9 because ! 3080: current_function_args_info is different in each compiler. */ ! 3081: ! 3082: #ifdef SPARCV9 ! 3083: ! 3084: rtx ! 3085: sparc_builtin_saveregs (arglist) ! 3086: tree arglist; ! 3087: { ! 3088: tree fntype = TREE_TYPE (current_function_decl); ! 3089: /* First unnamed integer register. */ ! 3090: int first_intreg = current_function_args_info.arg_count[(int) SPARC_ARG_INT]; ! 3091: /* Number of integer registers we need to save. */ ! 3092: int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg); ! 3093: /* First unnamed SFmode float reg (no, you can't pass SFmode floats as ! 3094: unnamed arguments, we just number them that way). We must round up to ! 3095: the next double word float reg - that is the first one to save. */ ! 3096: int first_floatreg = current_function_args_info.arg_count[(int) SPARC_ARG_FLOAT] + 1 & ~1; ! 3097: /* Number of SFmode float regs to save. */ ! 3098: int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg); ! 3099: int ptrsize = GET_MODE_SIZE (Pmode); ! 3100: rtx valist, regbuf, fpregs; ! 3101: int bufsize, adjust, regno; ! 3102: ! 3103: /* Allocate block of memory for the regs. ! 3104: We only allocate as much as we need, but we must ensure quadword float ! 3105: regs are stored with the appropriate alignment. */ ! 3106: /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte? ! 3107: Or can assign_stack_local accept a 0 SIZE argument? */ ! 3108: ! 3109: bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * (UNITS_PER_WORD / 2)); ! 3110: /* Add space in front of the int regs to ensure proper alignment of quadword ! 3111: fp regs. We must add the space in front because va_start assumes this. */ ! 3112: if (n_floatregs >= 4) ! 3113: adjust = ((n_intregs + first_floatreg / 2) % 2) * UNITS_PER_WORD; ! 3114: else ! 3115: adjust = 0; ! 3116: ! 3117: regbuf = assign_stack_local (BLKmode, bufsize + adjust, ! 3118: GET_MODE_BITSIZE (TFmode)); ! 3119: regbuf = gen_rtx (MEM, BLKmode, plus_constant (XEXP (regbuf, 0), adjust)); ! 3120: MEM_IN_STRUCT_P (regbuf) = 1; ! 3121: ! 3122: /* Save int args. ! 3123: This is optimized to only save the regs that are necessary. Explicitly ! 3124: named args need not be saved. */ ! 3125: ! 3126: if (n_intregs > 0) ! 3127: move_block_from_reg (BASE_INCOMING_ARG_REG (SImode) + first_intreg, ! 3128: regbuf, n_intregs, n_intregs * UNITS_PER_WORD); ! 3129: ! 3130: /* Save float args. ! 3131: This is optimized to only save the regs that are necessary. Explicitly ! 3132: named args need not be saved. ! 3133: We explicitly build a pointer to the buffer because it halves the insn ! 3134: count when not optimizing (otherwise the pointer is built for each reg ! 3135: saved). */ ! 3136: ! 3137: fpregs = gen_reg_rtx (Pmode); ! 3138: emit_move_insn (fpregs, plus_constant (XEXP (regbuf, 0), ! 3139: n_intregs * UNITS_PER_WORD)); ! 3140: for (regno = first_floatreg; regno < NPARM_REGS (SFmode); regno += 2) ! 3141: emit_move_insn (gen_rtx (MEM, DFmode, ! 3142: plus_constant (fpregs, ! 3143: GET_MODE_SIZE (SFmode) ! 3144: * (regno - first_floatreg))), ! 3145: gen_rtx (REG, DFmode, ! 3146: BASE_INCOMING_ARG_REG (DFmode) + regno)); ! 3147: ! 3148: /* Return the address of the regbuf. */ ! 3149: ! 3150: return XEXP (regbuf, 0); ! 3151: } ! 3152: ! 3153: #else /* ! SPARCV9 */ 1.1 root 3154: 3155: rtx 3156: sparc_builtin_saveregs (arglist) 3157: tree arglist; 3158: { 3159: tree fntype = TREE_TYPE (current_function_decl); 3160: int stdarg = (TYPE_ARG_TYPES (fntype) != 0 3161: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 3162: != void_type_node)); 3163: int first_reg = current_function_args_info; 3164: rtx address; 3165: int regno; 3166: 3167: #if 0 /* This code seemed to have no effect except to make 3168: varargs not work right when va_list wasn't the first arg. */ 3169: if (! stdarg) 3170: first_reg = 0; 3171: #endif 3172: 1.1.1.3 ! root 3173: for (regno = first_reg; regno < NPARM_REGS (SImode); regno++) 1.1 root 3174: emit_move_insn (gen_rtx (MEM, word_mode, 3175: gen_rtx (PLUS, Pmode, 3176: frame_pointer_rtx, 3177: GEN_INT (STACK_POINTER_OFFSET 3178: + UNITS_PER_WORD * regno))), 3179: gen_rtx (REG, word_mode, BASE_INCOMING_ARG_REG (word_mode) 3180: + regno)); 3181: 3182: address = gen_rtx (PLUS, Pmode, 3183: frame_pointer_rtx, 3184: GEN_INT (STACK_POINTER_OFFSET 3185: + UNITS_PER_WORD * first_reg)); 3186: 3187: return address; 3188: } 1.1.1.3 ! root 3189: ! 3190: #endif /* ! SPARCV9 */ 1.1 root 3191: 3192: /* Return the string to output a conditional branch to LABEL, which is 3193: the operand number of the label. OP is the conditional expression. The 3194: mode of register 0 says what kind of comparison we made. 3195: 1.1.1.3 ! root 3196: FP_COND_REG indicates which fp condition code register to use if this is ! 3197: a floating point branch. ! 3198: 1.1 root 3199: REVERSED is non-zero if we should reverse the sense of the comparison. 3200: 3201: ANNUL is non-zero if we should generate an annulling branch. 3202: 3203: NOOP is non-zero if we have to follow this branch by a noop. */ 3204: 3205: char * 1.1.1.3 ! root 3206: output_cbranch (op, fp_cond_reg, label, reversed, annul, noop) ! 3207: rtx op, fp_cond_reg; 1.1 root 3208: int label; 3209: int reversed, annul, noop; 3210: { 3211: static char string[20]; 3212: enum rtx_code code = GET_CODE (op); 3213: enum machine_mode mode = GET_MODE (XEXP (op, 0)); 1.1.1.3 ! root 3214: static char v8_labelno[] = " %lX"; ! 3215: static char v9_icc_labelno[] = " %%icc,%lX"; ! 3216: static char v9_xcc_labelno[] = " %%xcc,%lX"; ! 3217: static char v9_fcc_labelno[] = " %%fccX,%lY"; ! 3218: char *labelno; ! 3219: int labeloff; 1.1 root 3220: 1.1.1.3 ! root 3221: /* ??? !v9: FP branches cannot be preceded by another floating point insn. 1.1 root 3222: Because there is currently no concept of pre-delay slots, we can fix 3223: this only by always emitting a nop before a floating point branch. */ 3224: 1.1.1.3 ! root 3225: if ((mode == CCFPmode || mode == CCFPEmode) && ! TARGET_V9) 1.1 root 3226: strcpy (string, "nop\n\t"); 1.1.1.3 ! root 3227: else ! 3228: string[0] = '\0'; 1.1 root 3229: 3230: /* If not floating-point or if EQ or NE, we can just reverse the code. */ 3231: if (reversed 3232: && ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE)) 3233: code = reverse_condition (code), reversed = 0; 3234: 3235: /* Start by writing the branch condition. */ 3236: switch (code) 3237: { 3238: case NE: 3239: if (mode == CCFPmode || mode == CCFPEmode) 3240: strcat (string, "fbne"); 3241: else 3242: strcpy (string, "bne"); 3243: break; 3244: 3245: case EQ: 3246: if (mode == CCFPmode || mode == CCFPEmode) 3247: strcat (string, "fbe"); 3248: else 3249: strcpy (string, "be"); 3250: break; 3251: 3252: case GE: 3253: if (mode == CCFPmode || mode == CCFPEmode) 3254: { 3255: if (reversed) 3256: strcat (string, "fbul"); 3257: else 3258: strcat (string, "fbge"); 3259: } 3260: else if (mode == CC_NOOVmode) 3261: strcpy (string, "bpos"); 3262: else 3263: strcpy (string, "bge"); 3264: break; 3265: 3266: case GT: 3267: if (mode == CCFPmode || mode == CCFPEmode) 3268: { 3269: if (reversed) 3270: strcat (string, "fbule"); 3271: else 3272: strcat (string, "fbg"); 3273: } 3274: else 3275: strcpy (string, "bg"); 3276: break; 3277: 3278: case LE: 3279: if (mode == CCFPmode || mode == CCFPEmode) 3280: { 3281: if (reversed) 3282: strcat (string, "fbug"); 3283: else 3284: strcat (string, "fble"); 3285: } 3286: else 3287: strcpy (string, "ble"); 3288: break; 3289: 3290: case LT: 3291: if (mode == CCFPmode || mode == CCFPEmode) 3292: { 3293: if (reversed) 3294: strcat (string, "fbuge"); 3295: else 3296: strcat (string, "fbl"); 3297: } 3298: else if (mode == CC_NOOVmode) 3299: strcpy (string, "bneg"); 3300: else 3301: strcpy (string, "bl"); 3302: break; 3303: 3304: case GEU: 3305: strcpy (string, "bgeu"); 3306: break; 3307: 3308: case GTU: 3309: strcpy (string, "bgu"); 3310: break; 3311: 3312: case LEU: 3313: strcpy (string, "bleu"); 3314: break; 3315: 3316: case LTU: 3317: strcpy (string, "blu"); 3318: break; 3319: } 3320: 3321: /* Now add the annulling, the label, and a possible noop. */ 3322: if (annul) 3323: strcat (string, ",a"); 3324: 1.1.1.3 ! root 3325: /* ??? If v9, optional prediction bit ",pt" or ",pf" goes here. */ ! 3326: ! 3327: if (! TARGET_V9) ! 3328: { ! 3329: labeloff = 3; ! 3330: labelno = v8_labelno; ! 3331: } ! 3332: else ! 3333: { ! 3334: labeloff = 9; ! 3335: if (mode == CCFPmode || mode == CCFPEmode) ! 3336: { ! 3337: labeloff = 10; ! 3338: labelno = v9_fcc_labelno; ! 3339: /* Set the char indicating the number of the fcc reg to use. */ ! 3340: labelno[6] = REGNO (fp_cond_reg) - 96 + '0'; ! 3341: } ! 3342: else if (mode == CCXmode || mode == CCX_NOOVmode) ! 3343: labelno = v9_xcc_labelno; ! 3344: else ! 3345: labelno = v9_icc_labelno; ! 3346: } ! 3347: /* Set the char indicating the number of the operand containing the ! 3348: label_ref. */ ! 3349: labelno[labeloff] = label + '0'; ! 3350: strcat (string, labelno); ! 3351: ! 3352: if (noop) ! 3353: strcat (string, "\n\tnop"); ! 3354: ! 3355: return string; ! 3356: } ! 3357: ! 3358: /* Return the string to output a conditional branch to LABEL, testing ! 3359: register REG. LABEL is the operand number of the label; REG is the ! 3360: operand number of the reg. OP is the conditional expression. The mode ! 3361: of REG says what kind of comparison we made. ! 3362: ! 3363: REVERSED is non-zero if we should reverse the sense of the comparison. ! 3364: ! 3365: ANNUL is non-zero if we should generate an annulling branch. ! 3366: ! 3367: NOOP is non-zero if we have to follow this branch by a noop. */ ! 3368: ! 3369: char * ! 3370: output_v9branch (op, reg, label, reversed, annul, noop) ! 3371: rtx op; ! 3372: int reg, label; ! 3373: int reversed, annul, noop; ! 3374: { ! 3375: static char string[20]; ! 3376: enum rtx_code code = GET_CODE (op); ! 3377: enum machine_mode mode = GET_MODE (XEXP (op, 0)); ! 3378: static char labelno[] = " %X,%lX"; ! 3379: ! 3380: /* If not floating-point or if EQ or NE, we can just reverse the code. */ ! 3381: if (reversed) ! 3382: code = reverse_condition (code), reversed = 0; ! 3383: ! 3384: /* Only 64 bit versions of these instructions exist. */ ! 3385: if (mode != DImode) ! 3386: abort (); ! 3387: ! 3388: /* Start by writing the branch condition. */ ! 3389: ! 3390: switch (code) ! 3391: { ! 3392: case NE: ! 3393: strcpy (string, "brnz"); ! 3394: break; ! 3395: ! 3396: case EQ: ! 3397: strcpy (string, "brz"); ! 3398: break; ! 3399: ! 3400: case GE: ! 3401: strcpy (string, "brgez"); ! 3402: break; ! 3403: ! 3404: case LT: ! 3405: strcpy (string, "brlz"); ! 3406: break; ! 3407: ! 3408: case LE: ! 3409: strcpy (string, "brlez"); ! 3410: break; ! 3411: ! 3412: case GT: ! 3413: strcpy (string, "brgz"); ! 3414: break; ! 3415: ! 3416: default: ! 3417: abort (); ! 3418: } ! 3419: ! 3420: /* Now add the annulling, reg, label, and nop. */ ! 3421: if (annul) ! 3422: strcat (string, ",a"); ! 3423: ! 3424: /* ??? Optional prediction bit ",pt" or ",pf" goes here. */ ! 3425: ! 3426: labelno[2] = reg + '0'; ! 3427: labelno[6] = label + '0'; 1.1 root 3428: strcat (string, labelno); 3429: 3430: if (noop) 3431: strcat (string, "\n\tnop"); 3432: 3433: return string; 3434: } 3435: 3436: /* Output assembler code to return from a function. */ 3437: 1.1.1.3 ! root 3438: /* ??? v9: Update to use the new `return' instruction. Also, add patterns to ! 3439: md file for the `return' instruction. */ ! 3440: 1.1 root 3441: char * 3442: output_return (operands) 3443: rtx *operands; 3444: { 3445: if (leaf_label) 3446: { 3447: operands[0] = leaf_label; 3448: return "b,a %l0"; 3449: } 3450: else if (leaf_function) 3451: { 3452: /* If we didn't allocate a frame pointer for the current function, 3453: the stack pointer might have been adjusted. Output code to 3454: restore it now. */ 3455: 3456: operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize); 3457: 3458: /* Use sub of negated value in first two cases instead of add to 3459: allow actual_fsize == 4096. */ 3460: 3461: if (actual_fsize <= 4096) 3462: { 1.1.1.3 ! root 3463: if (SKIP_CALLERS_UNIMP_P) 1.1 root 3464: return "jmp %%o7+12\n\tsub %%sp,-%0,%%sp"; 3465: else 3466: return "retl\n\tsub %%sp,-%0,%%sp"; 3467: } 3468: else if (actual_fsize <= 8192) 3469: { 3470: operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize - 4096); 1.1.1.3 ! root 3471: if (SKIP_CALLERS_UNIMP_P) 1.1 root 3472: return "sub %%sp,-4096,%%sp\n\tjmp %%o7+12\n\tsub %%sp,-%0,%%sp"; 3473: else 3474: return "sub %%sp,-4096,%%sp\n\tretl\n\tsub %%sp,-%0,%%sp"; 3475: } 1.1.1.3 ! root 3476: else if (SKIP_CALLERS_UNIMP_P) 1.1 root 3477: { 3478: if ((actual_fsize & 0x3ff) != 0) 3479: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp"; 3480: else 3481: return "sethi %%hi(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp"; 3482: } 3483: else 3484: { 3485: if ((actual_fsize & 0x3ff) != 0) 3486: return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp"; 3487: else 3488: return "sethi %%hi(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp"; 3489: } 3490: } 3491: else 3492: { 1.1.1.3 ! root 3493: if (SKIP_CALLERS_UNIMP_P) 1.1 root 3494: return "jmp %%i7+12\n\trestore"; 3495: else 3496: return "ret\n\trestore"; 3497: } 3498: } 3499: 3500: /* Leaf functions and non-leaf functions have different needs. */ 3501: 3502: static int 3503: reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER; 3504: 3505: static int 3506: reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER; 3507: 3508: static int *reg_alloc_orders[] = { 3509: reg_leaf_alloc_order, 3510: reg_nonleaf_alloc_order}; 3511: 3512: void 3513: order_regs_for_local_alloc () 3514: { 3515: static int last_order_nonleaf = 1; 3516: 3517: if (regs_ever_live[15] != last_order_nonleaf) 3518: { 3519: last_order_nonleaf = !last_order_nonleaf; 3520: bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order, 3521: FIRST_PSEUDO_REGISTER * sizeof (int)); 3522: } 3523: } 3524: 3525: /* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1. 3526: This makes them candidates for using ldd and std insns. 3527: 3528: Note reg1 and reg2 *must* be hard registers. To be sure we will 3529: abort if we are passed pseudo registers. */ 3530: 3531: int 3532: registers_ok_for_ldd_peep (reg1, reg2) 3533: rtx reg1, reg2; 3534: { 3535: /* We might have been passed a SUBREG. */ 3536: if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG) 3537: return 0; 3538: 3539: if (REGNO (reg1) % 2 != 0) 3540: return 0; 3541: 3542: return (REGNO (reg1) == REGNO (reg2) - 1); 3543: } 3544: 3545: /* Return 1 if addr1 and addr2 are suitable for use in an ldd or 3546: std insn. 3547: 3548: This can only happen when addr1 and addr2 are consecutive memory 3549: locations (addr1 + 4 == addr2). addr1 must also be aligned on a 3550: 64 bit boundary (addr1 % 8 == 0). 3551: 3552: We know %sp and %fp are kept aligned on a 64 bit boundary. Other 3553: registers are assumed to *never* be properly aligned and are 3554: rejected. 3555: 3556: Knowing %sp and %fp are kept aligned on a 64 bit boundary, we 3557: need only check that the offset for addr1 % 8 == 0. */ 3558: 3559: int 3560: addrs_ok_for_ldd_peep (addr1, addr2) 3561: rtx addr1, addr2; 3562: { 3563: int reg1, offset1; 3564: 3565: /* Extract a register number and offset (if used) from the first addr. */ 3566: if (GET_CODE (addr1) == PLUS) 3567: { 3568: /* If not a REG, return zero. */ 3569: if (GET_CODE (XEXP (addr1, 0)) != REG) 3570: return 0; 3571: else 3572: { 3573: reg1 = REGNO (XEXP (addr1, 0)); 3574: /* The offset must be constant! */ 3575: if (GET_CODE (XEXP (addr1, 1)) != CONST_INT) 3576: return 0; 3577: offset1 = INTVAL (XEXP (addr1, 1)); 3578: } 3579: } 3580: else if (GET_CODE (addr1) != REG) 3581: return 0; 3582: else 3583: { 3584: reg1 = REGNO (addr1); 3585: /* This was a simple (mem (reg)) expression. Offset is 0. */ 3586: offset1 = 0; 3587: } 3588: 3589: /* Make sure the second address is a (mem (plus (reg) (const_int). */ 3590: if (GET_CODE (addr2) != PLUS) 3591: return 0; 3592: 3593: if (GET_CODE (XEXP (addr2, 0)) != REG 3594: || GET_CODE (XEXP (addr2, 1)) != CONST_INT) 3595: return 0; 3596: 3597: /* Only %fp and %sp are allowed. Additionally both addresses must 3598: use the same register. */ 3599: if (reg1 != FRAME_POINTER_REGNUM && reg1 != STACK_POINTER_REGNUM) 3600: return 0; 3601: 3602: if (reg1 != REGNO (XEXP (addr2, 0))) 3603: return 0; 3604: 3605: /* The first offset must be evenly divisible by 8 to ensure the 3606: address is 64 bit aligned. */ 3607: if (offset1 % 8 != 0) 3608: return 0; 3609: 3610: /* The offset for the second addr must be 4 more than the first addr. */ 3611: if (INTVAL (XEXP (addr2, 1)) != offset1 + 4) 3612: return 0; 3613: 3614: /* All the tests passed. addr1 and addr2 are valid for ldd and std 3615: instructions. */ 3616: return 1; 3617: } 3618: 3619: /* Return 1 if reg is a pseudo, or is the first register in 3620: a hard register pair. This makes it a candidate for use in 3621: ldd and std insns. */ 3622: 3623: int 3624: register_ok_for_ldd (reg) 3625: rtx reg; 3626: { 3627: /* We might have been passed a SUBREG. */ 3628: if (GET_CODE (reg) != REG) 3629: return 0; 3630: 3631: if (REGNO (reg) < FIRST_PSEUDO_REGISTER) 3632: return (REGNO (reg) % 2 == 0); 3633: else 3634: return 1; 3635: } 3636: 3637: /* Print operand X (an rtx) in assembler syntax to file FILE. 3638: CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. 3639: For `%' followed by punctuation, CODE is the punctuation and X is null. */ 3640: 3641: void 3642: print_operand (file, x, code) 3643: FILE *file; 3644: rtx x; 3645: int code; 3646: { 3647: switch (code) 3648: { 3649: case '#': 3650: /* Output a 'nop' if there's nothing for the delay slot. */ 3651: if (dbr_sequence_length () == 0) 3652: fputs ("\n\tnop", file); 3653: return; 3654: case '*': 3655: /* Output an annul flag if there's nothing for the delay slot and we 3656: are optimizing. This is always used with '(' below. */ 3657: /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch; 3658: this is a dbx bug. So, we only do this when optimizing. */ 3659: if (dbr_sequence_length () == 0 && optimize) 3660: fputs (",a", file); 3661: return; 3662: case '(': 3663: /* Output a 'nop' if there's nothing for the delay slot and we are 3664: not optimizing. This is always used with '*' above. */ 3665: if (dbr_sequence_length () == 0 && ! optimize) 3666: fputs ("\n\tnop", file); 3667: return; 1.1.1.3 ! root 3668: case '_': ! 3669: /* Output the Medium/Anywhere code model base register. */ ! 3670: fputs (MEDANY_BASE_REG, file); ! 3671: return; ! 3672: case '@': ! 3673: /* Print out what we are using as the frame pointer. This might ! 3674: be %fp, or might be %sp+offset. */ ! 3675: /* ??? What if offset is too big? Perhaps the caller knows it isn't? */ ! 3676: fprintf (file, "%s+%d", frame_base_name, frame_base_offset); ! 3677: return; 1.1 root 3678: case 'Y': 3679: /* Adjust the operand to take into account a RESTORE operation. */ 3680: if (GET_CODE (x) != REG) 3681: output_operand_lossage ("Invalid %%Y operand"); 3682: else if (REGNO (x) < 8) 3683: fputs (reg_names[REGNO (x)], file); 3684: else if (REGNO (x) >= 24 && REGNO (x) < 32) 3685: fputs (reg_names[REGNO (x)-16], file); 3686: else 3687: output_operand_lossage ("Invalid %%Y operand"); 3688: return; 3689: case 'R': 3690: /* Print out the second register name of a register pair or quad. 3691: I.e., R (%o0) => %o1. */ 3692: fputs (reg_names[REGNO (x)+1], file); 3693: return; 3694: case 'S': 3695: /* Print out the third register name of a register quad. 3696: I.e., S (%o0) => %o2. */ 3697: fputs (reg_names[REGNO (x)+2], file); 3698: return; 3699: case 'T': 3700: /* Print out the fourth register name of a register quad. 3701: I.e., T (%o0) => %o3. */ 3702: fputs (reg_names[REGNO (x)+3], file); 3703: return; 3704: case 'm': 3705: /* Print the operand's address only. */ 3706: output_address (XEXP (x, 0)); 3707: return; 3708: case 'r': 3709: /* In this case we need a register. Use %g0 if the 3710: operand is const0_rtx. */ 3711: if (x == const0_rtx 3712: || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x)))) 3713: { 3714: fputs ("%g0", file); 3715: return; 3716: } 3717: else 3718: break; 3719: 1.1.1.3 ! root 3720: case 'A': 1.1 root 3721: switch (GET_CODE (x)) 3722: { 3723: case IOR: fputs ("or", file); break; 3724: case AND: fputs ("and", file); break; 3725: case XOR: fputs ("xor", file); break; 3726: default: output_operand_lossage ("Invalid %%A operand"); 3727: } 3728: return; 3729: 3730: case 'B': 3731: switch (GET_CODE (x)) 3732: { 3733: case IOR: fputs ("orn", file); break; 3734: case AND: fputs ("andn", file); break; 3735: case XOR: fputs ("xnor", file); break; 3736: default: output_operand_lossage ("Invalid %%B operand"); 3737: } 3738: return; 3739: 1.1.1.3 ! root 3740: /* This is used by the conditional move instructions. */ ! 3741: case 'C': ! 3742: switch (GET_CODE (x)) ! 3743: { ! 3744: case NE: fputs ("ne", file); break; ! 3745: case EQ: fputs ("e", file); break; ! 3746: case GE: fputs ("ge", file); break; ! 3747: case GT: fputs ("g", file); break; ! 3748: case LE: fputs ("le", file); break; ! 3749: case LT: fputs ("l", file); break; ! 3750: case GEU: fputs ("geu", file); break; ! 3751: case GTU: fputs ("gu", file); break; ! 3752: case LEU: fputs ("leu", file); break; ! 3753: case LTU: fputs ("lu", file); break; ! 3754: default: output_operand_lossage ("Invalid %%C operand"); ! 3755: } ! 3756: return; ! 3757: ! 3758: /* This is used by the movr instruction pattern. */ ! 3759: case 'D': ! 3760: switch (GET_CODE (x)) ! 3761: { ! 3762: case NE: fputs ("ne", file); break; ! 3763: case EQ: fputs ("e", file); break; ! 3764: case GE: fputs ("gez", file); break; ! 3765: case LT: fputs ("lz", file); break; ! 3766: case LE: fputs ("lez", file); break; ! 3767: case GT: fputs ("gz", file); break; ! 3768: default: output_operand_lossage ("Invalid %%D operand"); ! 3769: } ! 3770: return; ! 3771: 1.1 root 3772: case 'b': 3773: { 3774: /* Print a sign-extended character. */ 3775: int i = INTVAL (x) & 0xff; 3776: if (i & 0x80) 3777: i |= 0xffffff00; 3778: fprintf (file, "%d", i); 3779: return; 3780: } 3781: 3782: case 0: 3783: /* Do nothing special. */ 3784: break; 3785: 3786: default: 3787: /* Undocumented flag. */ 3788: output_operand_lossage ("invalid operand output code"); 3789: } 3790: 3791: if (GET_CODE (x) == REG) 3792: fputs (reg_names[REGNO (x)], file); 3793: else if (GET_CODE (x) == MEM) 3794: { 3795: fputc ('[', file); 3796: if (CONSTANT_P (XEXP (x, 0))) 3797: /* Poor Sun assembler doesn't understand absolute addressing. */ 3798: fputs ("%g0+", file); 3799: output_address (XEXP (x, 0)); 3800: fputc (']', file); 3801: } 3802: else if (GET_CODE (x) == HIGH) 3803: { 3804: fputs ("%hi(", file); 3805: output_addr_const (file, XEXP (x, 0)); 3806: fputc (')', file); 3807: } 3808: else if (GET_CODE (x) == LO_SUM) 3809: { 3810: print_operand (file, XEXP (x, 0), 0); 3811: fputs ("+%lo(", file); 3812: output_addr_const (file, XEXP (x, 1)); 3813: fputc (')', file); 3814: } 3815: else if (GET_CODE (x) == CONST_DOUBLE 3816: && (GET_MODE (x) == VOIDmode 3817: || GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)) 3818: { 3819: if (CONST_DOUBLE_HIGH (x) == 0) 3820: fprintf (file, "%u", CONST_DOUBLE_LOW (x)); 3821: else if (CONST_DOUBLE_HIGH (x) == -1 3822: && CONST_DOUBLE_LOW (x) < 0) 3823: fprintf (file, "%d", CONST_DOUBLE_LOW (x)); 3824: else 3825: output_operand_lossage ("long long constant not a valid immediate operand"); 3826: } 3827: else if (GET_CODE (x) == CONST_DOUBLE) 3828: output_operand_lossage ("floating point constant not a valid immediate operand"); 3829: else { output_addr_const (file, x); } 3830: } 3831: 3832: /* This function outputs assembler code for VALUE to FILE, where VALUE is 3833: a 64 bit (DImode) value. */ 3834: 3835: /* ??? If there is a 64 bit counterpart to .word that the assembler 3836: understands, then using that would simply this code greatly. */ 1.1.1.3 ! root 3837: /* ??? We only output .xword's for symbols and only then in environments ! 3838: where the assembler can handle them. */ 1.1 root 3839: 3840: void 3841: output_double_int (file, value) 3842: FILE *file; 3843: rtx value; 3844: { 3845: if (GET_CODE (value) == CONST_INT) 3846: { 3847: if (INTVAL (value) < 0) 3848: ASM_OUTPUT_INT (file, constm1_rtx); 3849: else 3850: ASM_OUTPUT_INT (file, const0_rtx); 3851: ASM_OUTPUT_INT (file, value); 3852: } 3853: else if (GET_CODE (value) == CONST_DOUBLE) 3854: { 3855: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode, 3856: CONST_DOUBLE_HIGH (value))); 3857: ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode, 3858: CONST_DOUBLE_LOW (value))); 3859: } 3860: else if (GET_CODE (value) == SYMBOL_REF 3861: || GET_CODE (value) == CONST 1.1.1.3 ! root 3862: || GET_CODE (value) == PLUS ! 3863: || (TARGET_V9 && ! 3864: (GET_CODE (value) == LABEL_REF ! 3865: || GET_CODE (value) == MINUS))) 1.1 root 3866: { 1.1.1.3 ! root 3867: if (!TARGET_V9 || TARGET_ENV32) ! 3868: { ! 3869: ASM_OUTPUT_INT (file, const0_rtx); ! 3870: ASM_OUTPUT_INT (file, value); ! 3871: } ! 3872: else ! 3873: { ! 3874: fprintf (file, "\t%s\t", ASM_LONGLONG); ! 3875: output_addr_const (file, value); ! 3876: fprintf (file, "\n"); ! 3877: } 1.1 root 3878: } 3879: else 3880: abort (); 3881: } 3882: 1.1.1.3 ! root 3883: /* Return the value of a code used in the .proc pseudo-op that says ! 3884: what kind of result this function returns. For non-C types, we pick ! 3885: the closest C type. */ ! 3886: 1.1 root 3887: #ifndef CHAR_TYPE_SIZE 3888: #define CHAR_TYPE_SIZE BITS_PER_UNIT 3889: #endif 3890: 3891: #ifndef SHORT_TYPE_SIZE 3892: #define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2) 3893: #endif 3894: 3895: #ifndef INT_TYPE_SIZE 3896: #define INT_TYPE_SIZE BITS_PER_WORD 3897: #endif 3898: 3899: #ifndef LONG_TYPE_SIZE 3900: #define LONG_TYPE_SIZE BITS_PER_WORD 3901: #endif 3902: 3903: #ifndef LONG_LONG_TYPE_SIZE 3904: #define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2) 3905: #endif 3906: 3907: #ifndef FLOAT_TYPE_SIZE 3908: #define FLOAT_TYPE_SIZE BITS_PER_WORD 3909: #endif 3910: 3911: #ifndef DOUBLE_TYPE_SIZE 3912: #define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) 3913: #endif 3914: 3915: #ifndef LONG_DOUBLE_TYPE_SIZE 3916: #define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) 3917: #endif 3918: 3919: unsigned long 3920: sparc_type_code (type) 3921: register tree type; 3922: { 3923: register unsigned long qualifiers = 0; 3924: register unsigned shift = 6; 3925: 1.1.1.3 ! root 3926: /* Only the first 30 bits of the qualifer are valid. We must refrain from ! 3927: setting more, since some assemblers will give an error for this. Also, ! 3928: we must be careful to avoid shifts of 32 bits or more to avoid getting ! 3929: unpredictable results. */ ! 3930: 1.1 root 3931: for (;;) 3932: { 3933: switch (TREE_CODE (type)) 3934: { 3935: case ERROR_MARK: 3936: return qualifiers; 3937: 3938: case ARRAY_TYPE: 1.1.1.3 ! root 3939: if (shift < 30) ! 3940: qualifiers |= (3 << shift); 1.1 root 3941: shift += 2; 3942: type = TREE_TYPE (type); 3943: break; 3944: 3945: case FUNCTION_TYPE: 3946: case METHOD_TYPE: 1.1.1.3 ! root 3947: if (shift < 30) ! 3948: qualifiers |= (2 << shift); 1.1 root 3949: shift += 2; 3950: type = TREE_TYPE (type); 3951: break; 3952: 3953: case POINTER_TYPE: 3954: case REFERENCE_TYPE: 3955: case OFFSET_TYPE: 1.1.1.3 ! root 3956: if (shift < 30) ! 3957: qualifiers |= (1 << shift); 1.1 root 3958: shift += 2; 3959: type = TREE_TYPE (type); 3960: break; 3961: 3962: case RECORD_TYPE: 3963: return (qualifiers | 8); 3964: 3965: case UNION_TYPE: 1.1.1.3 ! root 3966: case QUAL_UNION_TYPE: 1.1 root 3967: return (qualifiers | 9); 3968: 3969: case ENUMERAL_TYPE: 3970: return (qualifiers | 10); 3971: 3972: case VOID_TYPE: 3973: return (qualifiers | 16); 3974: 3975: case INTEGER_TYPE: 1.1.1.2 root 3976: /* If this is a range type, consider it to be the underlying 3977: type. */ 3978: if (TREE_TYPE (type) != 0) 3979: { 3980: type = TREE_TYPE (type); 3981: break; 3982: } 3983: 1.1 root 3984: /* Carefully distinguish all the standard types of C, 1.1.1.3 ! root 3985: without messing up if the language is not C. We do this by ! 3986: testing TYPE_PRECISION and TREE_UNSIGNED. The old code used to ! 3987: look at both the names and the above fields, but that's redundant. ! 3988: Any type whose size is between two C types will be considered ! 3989: to be the wider of the two types. Also, we do not have a ! 3990: special code to use for "long long", so anything wider than ! 3991: long is treated the same. Note that we can't distinguish ! 3992: between "int" and "long" in this code if they are the same ! 3993: size, but that's fine, since neither can the assembler. */ ! 3994: ! 3995: if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE) ! 3996: return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2)); 1.1 root 3997: 1.1.1.3 ! root 3998: else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE) ! 3999: return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3)); 1.1 root 4000: 1.1.1.3 ! root 4001: else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE) 1.1 root 4002: return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4)); 4003: 1.1.1.3 ! root 4004: else 1.1 root 4005: return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5)); 4006: 4007: case REAL_TYPE: 4008: /* Carefully distinguish all the standard types of C, 4009: without messing up if the language is not C. */ 1.1.1.3 ! root 4010: 1.1 root 4011: if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE) 4012: return (qualifiers | 6); 1.1.1.3 ! root 4013: ! 4014: else ! 4015: return (qualifiers | 7); 1.1 root 4016: 4017: case COMPLEX_TYPE: /* GNU Fortran COMPLEX type. */ 4018: /* ??? We need to distinguish between double and float complex types, 4019: but I don't know how yet because I can't reach this code from 4020: existing front-ends. */ 4021: return (qualifiers | 7); /* Who knows? */ 4022: 4023: case CHAR_TYPE: /* GNU Pascal CHAR type. Not used in C. */ 4024: case BOOLEAN_TYPE: /* GNU Fortran BOOLEAN type. */ 4025: case FILE_TYPE: /* GNU Pascal FILE type. */ 1.1.1.2 root 4026: case SET_TYPE: /* GNU Pascal SET type. */ 1.1 root 4027: case LANG_TYPE: /* ? */ 1.1.1.2 root 4028: return qualifiers; 1.1 root 4029: 4030: default: 4031: abort (); /* Not a type! */ 4032: } 4033: } 4034: } 4035: 1.1.1.3 ! root 4036: /* Nested function support. */ ! 4037: ! 4038: /* Emit RTL insns to initialize the variable parts of a trampoline. ! 4039: FNADDR is an RTX for the address of the function's pure code. ! 4040: CXT is an RTX for the static chain value for the function. ! 4041: ! 4042: This takes 16 insns: 2 shifts & 2 ands (to split up addresses), 4 sethi ! 4043: (to load in opcodes), 4 iors (to merge address and opcodes), and 4 writes ! 4044: (to store insns). This is a bit excessive. Perhaps a different ! 4045: mechanism would be better here. ! 4046: ! 4047: Emit 3 FLUSH instructions (UNSPEC_VOLATILE 3) to synchonize the data ! 4048: and instruction caches. ! 4049: ! 4050: ??? v9: We assume the top 32 bits of function addresses are 0. */ ! 4051: ! 4052: void ! 4053: sparc_initialize_trampoline (tramp, fnaddr, cxt) ! 4054: rtx tramp, fnaddr, cxt; ! 4055: { ! 4056: rtx high_cxt = expand_shift (RSHIFT_EXPR, SImode, cxt, ! 4057: size_int (10), 0, 1); ! 4058: rtx high_fn = expand_shift (RSHIFT_EXPR, SImode, fnaddr, ! 4059: size_int (10), 0, 1); ! 4060: rtx low_cxt = expand_and (cxt, gen_rtx (CONST_INT, VOIDmode, 0x3ff), 0); ! 4061: rtx low_fn = expand_and (fnaddr, gen_rtx (CONST_INT, VOIDmode, 0x3ff), 0); ! 4062: rtx g1_sethi = gen_rtx (HIGH, SImode, ! 4063: gen_rtx (CONST_INT, VOIDmode, 0x03000000)); ! 4064: rtx g2_sethi = gen_rtx (HIGH, SImode, ! 4065: gen_rtx (CONST_INT, VOIDmode, 0x05000000)); ! 4066: rtx g1_ori = gen_rtx (HIGH, SImode, ! 4067: gen_rtx (CONST_INT, VOIDmode, 0x82106000)); ! 4068: rtx g2_ori = gen_rtx (HIGH, SImode, ! 4069: gen_rtx (CONST_INT, VOIDmode, 0x8410A000)); ! 4070: rtx tem = gen_reg_rtx (SImode); ! 4071: emit_move_insn (tem, g1_sethi); ! 4072: emit_insn (gen_iorsi3 (high_fn, high_fn, tem)); ! 4073: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 0)), high_fn); ! 4074: emit_move_insn (tem, g1_ori); ! 4075: emit_insn (gen_iorsi3 (low_fn, low_fn, tem)); ! 4076: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 4)), low_fn); ! 4077: emit_move_insn (tem, g2_sethi); ! 4078: emit_insn (gen_iorsi3 (high_cxt, high_cxt, tem)); ! 4079: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 8)), high_cxt); ! 4080: emit_move_insn (tem, g2_ori); ! 4081: emit_insn (gen_iorsi3 (low_cxt, low_cxt, tem)); ! 4082: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 16)), low_cxt); ! 4083: emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, ! 4084: gen_rtvec (1, plus_constant (tramp, 0)), ! 4085: 3)); ! 4086: emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, ! 4087: gen_rtvec (1, plus_constant (tramp, 8)), ! 4088: 3)); ! 4089: emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, ! 4090: gen_rtvec (1, plus_constant (tramp, 16)), ! 4091: 3)); ! 4092: } ! 4093: ! 4094: void ! 4095: sparc64_initialize_trampoline (tramp, fnaddr, cxt) ! 4096: rtx tramp, fnaddr, cxt; ! 4097: { ! 4098: rtx fnaddrdi = gen_reg_rtx (Pmode); ! 4099: rtx fnaddrsi = (emit_move_insn (fnaddrdi, fnaddr), ! 4100: gen_rtx (SUBREG, SImode, fnaddrdi, 0)); ! 4101: rtx cxtdi = gen_reg_rtx (Pmode); ! 4102: rtx cxtsi = (emit_move_insn (cxtdi, cxt), ! 4103: gen_rtx (SUBREG, SImode, cxtdi, 0)); ! 4104: rtx high_cxt = expand_shift (RSHIFT_EXPR, SImode, cxtsi, ! 4105: size_int (10), 0, 1); ! 4106: rtx high_fn = expand_shift (RSHIFT_EXPR, SImode, fnaddrsi, ! 4107: size_int (10), 0, 1); ! 4108: rtx low_cxt = expand_and (cxtsi, gen_rtx (CONST_INT, VOIDmode, 0x3ff), 0); ! 4109: rtx low_fn = expand_and (fnaddrsi, gen_rtx (CONST_INT, VOIDmode, 0x3ff), 0); ! 4110: rtx g1_sethi = gen_rtx (HIGH, SImode, ! 4111: gen_rtx (CONST_INT, VOIDmode, 0x03000000)); ! 4112: rtx g2_sethi = gen_rtx (HIGH, SImode, ! 4113: gen_rtx (CONST_INT, VOIDmode, 0x05000000)); ! 4114: rtx g1_ori = gen_rtx (HIGH, SImode, ! 4115: gen_rtx (CONST_INT, VOIDmode, 0x82106000)); ! 4116: rtx g2_ori = gen_rtx (HIGH, SImode, ! 4117: gen_rtx (CONST_INT, VOIDmode, 0x8410A000)); ! 4118: rtx tem = gen_reg_rtx (SImode); ! 4119: emit_move_insn (tem, g2_sethi); ! 4120: emit_insn (gen_iorsi3 (high_fn, high_fn, tem)); ! 4121: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 0)), high_fn); ! 4122: emit_move_insn (tem, g2_ori); ! 4123: emit_insn (gen_iorsi3 (low_fn, low_fn, tem)); ! 4124: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 4)), low_fn); ! 4125: emit_move_insn (tem, g1_sethi); ! 4126: emit_insn (gen_iorsi3 (high_cxt, high_cxt, tem)); ! 4127: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 8)), high_cxt); ! 4128: emit_move_insn (tem, g1_ori); ! 4129: emit_insn (gen_iorsi3 (low_cxt, low_cxt, tem)); ! 4130: emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 16)), low_cxt); ! 4131: emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, ! 4132: gen_rtvec (1, plus_constant (tramp, 0)), ! 4133: 3)); ! 4134: emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, ! 4135: gen_rtvec (1, plus_constant (tramp, 8)), ! 4136: 3)); ! 4137: emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, ! 4138: gen_rtvec (1, plus_constant (tramp, 16)), ! 4139: 3)); ! 4140: } ! 4141: 1.1 root 4142: /* Subroutines to support a flat (single) register window calling 4143: convention. */ 4144: 4145: /* Single-register window sparc stack frames look like: 4146: 4147: Before call After call 4148: +-----------------------+ +-----------------------+ 1.1.1.3 ! root 4149: high | | | | ! 4150: mem | caller's temps. | | caller's temps. | 1.1 root 4151: | | | | 4152: +-----------------------+ +-----------------------+ 4153: | | | | 4154: | arguments on stack. | | arguments on stack. | 1.1.1.3 ! root 4155: | | | | ! 4156: +-----------------------+FP+92->+-----------------------+ 1.1 root 4157: | 6 words to save | | 6 words to save | 4158: | arguments passed | | arguments passed | 4159: | in registers, even | | in registers, even | 1.1.1.3 ! root 4160: | if not passed. | | if not passed. | ! 4161: SP+68->+-----------------------+FP+68->+-----------------------+ ! 4162: | 1 word struct addr | | 1 word struct addr | ! 4163: +-----------------------+FP+64->+-----------------------+ ! 4164: | | | | ! 4165: | 16 word reg save area | | 16 word reg save area | ! 4166: | | | | ! 4167: SP->+-----------------------+ FP->+-----------------------+ ! 4168: | 4 word area for | ! 4169: | fp/alu reg moves | ! 4170: FP-16->+-----------------------+ ! 4171: | | ! 4172: | local variables | ! 4173: | | ! 4174: +-----------------------+ ! 4175: | | 1.1 root 4176: | fp register save | 1.1.1.3 ! root 4177: | | ! 4178: +-----------------------+ ! 4179: | | 1.1 root 4180: | gp register save | 4181: | | 1.1.1.3 ! root 4182: +-----------------------+ ! 4183: | | 1.1 root 4184: | alloca allocations | 1.1.1.3 ! root 4185: | | ! 4186: +-----------------------+ ! 4187: | | 1.1 root 4188: | arguments on stack | 1.1.1.3 ! root 4189: | | ! 4190: SP+92->+-----------------------+ 1.1 root 4191: | 6 words to save | 1.1.1.3 ! root 4192: | arguments passed | 1.1 root 4193: | in registers, even | 1.1.1.3 ! root 4194: low | if not passed. | ! 4195: memory SP+68->+-----------------------+ ! 4196: | 1 word struct addr | ! 4197: SP+64->+-----------------------+ ! 4198: | | ! 4199: I 16 word reg save area | ! 4200: | | ! 4201: SP->+-----------------------+ */ 1.1 root 4202: 1.1.1.3 ! root 4203: /* Structure to be filled in by sparc_flat_compute_frame_size with register 1.1 root 4204: save masks, and offsets for the current function. */ 4205: 4206: struct sparc_frame_info 4207: { 4208: unsigned long total_size; /* # bytes that the entire frame takes up. */ 4209: unsigned long var_size; /* # bytes that variables take up. */ 4210: unsigned long args_size; /* # bytes that outgoing arguments take up. */ 4211: unsigned long extra_size; /* # bytes of extra gunk. */ 4212: unsigned int gp_reg_size; /* # bytes needed to store gp regs. */ 4213: unsigned int fp_reg_size; /* # bytes needed to store fp regs. */ 1.1.1.3 ! root 4214: unsigned long gmask; /* Mask of saved gp registers. */ 1.1 root 4215: unsigned long fmask; /* Mask of saved fp registers. */ 1.1.1.3 ! root 4216: unsigned long reg_offset; /* Offset from new sp to store regs. */ 1.1 root 4217: int initialized; /* Nonzero if frame size already calculated. */ 4218: }; 4219: 1.1.1.3 ! root 4220: /* Current frame information calculated by sparc_flat_compute_frame_size. */ 1.1 root 4221: struct sparc_frame_info current_frame_info; 4222: 4223: /* Zero structure to initialize current_frame_info. */ 4224: struct sparc_frame_info zero_frame_info; 4225: 4226: /* Tell prologue and epilogue if register REGNO should be saved / restored. */ 4227: 1.1.1.3 ! root 4228: #define RETURN_ADDR_REGNUM 15 ! 4229: #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) ! 4230: #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) ! 4231: 1.1 root 4232: #define MUST_SAVE_REGISTER(regno) \ 4233: ((regs_ever_live[regno] && !call_used_regs[regno]) \ 4234: || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \ 1.1.1.3 ! root 4235: || (regno == RETURN_ADDR_REGNUM && regs_ever_live[RETURN_ADDR_REGNUM])) 1.1 root 4236: 4237: /* Return the bytes needed to compute the frame pointer from the current 4238: stack pointer. */ 4239: 4240: unsigned long 1.1.1.3 ! root 4241: sparc_flat_compute_frame_size (size) 1.1 root 4242: int size; /* # of var. bytes allocated. */ 4243: { 4244: int regno; 4245: unsigned long total_size; /* # bytes that the entire frame takes up. */ 4246: unsigned long var_size; /* # bytes that variables take up. */ 4247: unsigned long args_size; /* # bytes that outgoing arguments take up. */ 4248: unsigned long extra_size; /* # extra bytes. */ 4249: unsigned int gp_reg_size; /* # bytes needed to store gp regs. */ 4250: unsigned int fp_reg_size; /* # bytes needed to store fp regs. */ 1.1.1.3 ! root 4251: unsigned long gmask; /* Mask of saved gp registers. */ 1.1 root 4252: unsigned long fmask; /* Mask of saved fp registers. */ 1.1.1.3 ! root 4253: unsigned long reg_offset; /* Offset to register save area. */ ! 4254: int need_aligned_p; /* 1 if need the save area 8 byte aligned. */ 1.1 root 4255: 4256: /* This is the size of the 16 word reg save area, 1 word struct addr 4257: area, and 4 word fp/alu register copy area. */ 4258: extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0); 4259: var_size = size; 4260: /* Also include the size needed for the 6 parameter registers. */ 4261: args_size = current_function_outgoing_args_size + 24; 4262: total_size = var_size + args_size + extra_size; 4263: gp_reg_size = 0; 4264: fp_reg_size = 0; 1.1.1.3 ! root 4265: gmask = 0; 1.1 root 4266: fmask = 0; 1.1.1.3 ! root 4267: reg_offset = 0; ! 4268: need_aligned_p = 0; 1.1 root 4269: 4270: /* Calculate space needed for gp registers. */ 4271: for (regno = 1; regno <= 31; regno++) 4272: { 4273: if (MUST_SAVE_REGISTER (regno)) 4274: { 1.1.1.3 ! root 4275: /* If we need to save two regs in a row, ensure there's room to bump ! 4276: up the address to align it to a doubleword boundary. */ 1.1 root 4277: if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1)) 4278: { 4279: if (gp_reg_size % 8 != 0) 1.1.1.3 ! root 4280: gp_reg_size += 4; 1.1 root 4281: gp_reg_size += 2 * UNITS_PER_WORD; 1.1.1.3 ! root 4282: gmask |= 3 << regno; 1.1 root 4283: regno++; 1.1.1.3 ! root 4284: need_aligned_p = 1; 1.1 root 4285: } 4286: else 4287: { 4288: gp_reg_size += UNITS_PER_WORD; 1.1.1.3 ! root 4289: gmask |= 1 << regno; 1.1 root 4290: } 4291: } 4292: } 4293: 4294: /* Calculate space needed for fp registers. */ 4295: for (regno = 32; regno <= 63; regno++) 4296: { 4297: if (regs_ever_live[regno] && !call_used_regs[regno]) 4298: { 4299: fp_reg_size += UNITS_PER_WORD; 4300: fmask |= 1 << (regno - 32); 4301: } 4302: } 4303: 1.1.1.3 ! root 4304: if (gmask || fmask) ! 4305: { ! 4306: int n; ! 4307: reg_offset = FIRST_PARM_OFFSET(0) + args_size; ! 4308: /* Ensure save area is 8 byte aligned if we need it. */ ! 4309: n = reg_offset % 8; ! 4310: if (need_aligned_p && n != 0) ! 4311: { ! 4312: total_size += 8 - n; ! 4313: reg_offset += 8 - n; ! 4314: } ! 4315: total_size += gp_reg_size + fp_reg_size; ! 4316: } 1.1 root 4317: 1.1.1.3 ! root 4318: /* ??? This looks a little suspicious. Clarify. */ 1.1 root 4319: if (total_size == extra_size) 4320: total_size = extra_size = 0; 4321: 4322: total_size = SPARC_STACK_ALIGN (total_size); 4323: 4324: /* Save other computed information. */ 4325: current_frame_info.total_size = total_size; 4326: current_frame_info.var_size = var_size; 4327: current_frame_info.args_size = args_size; 4328: current_frame_info.extra_size = extra_size; 4329: current_frame_info.gp_reg_size = gp_reg_size; 4330: current_frame_info.fp_reg_size = fp_reg_size; 1.1.1.3 ! root 4331: current_frame_info.gmask = gmask; 1.1 root 4332: current_frame_info.fmask = fmask; 1.1.1.3 ! root 4333: current_frame_info.reg_offset = reg_offset; 1.1 root 4334: current_frame_info.initialized = reload_completed; 4335: 4336: /* Ok, we're done. */ 4337: return total_size; 4338: } 4339: 1.1.1.3 ! root 4340: /* Save/restore registers in GMASK and FMASK at register BASE_REG plus offset ! 4341: OFFSET. ! 4342: ! 4343: BASE_REG must be 8 byte aligned. This allows us to test OFFSET for ! 4344: appropriate alignment and use DOUBLEWORD_OP when we can. We assume ! 4345: [BASE_REG+OFFSET] will always be a valid address. ! 4346: ! 4347: WORD_OP is either "st" for save, "ld" for restore. ! 4348: DOUBLEWORD_OP is either "std" for save, "ldd" for restore. */ 1.1 root 4349: 4350: void 1.1.1.3 ! root 4351: sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doubleword_op) ! 4352: FILE *file; ! 4353: char *base_reg; ! 4354: unsigned int offset; ! 4355: unsigned long gmask; ! 4356: unsigned long fmask; ! 4357: char *word_op; ! 4358: char *doubleword_op; 1.1 root 4359: { 4360: int regno; 4361: 1.1.1.3 ! root 4362: if (gmask == 0 && fmask == 0) 1.1 root 4363: return; 4364: 1.1.1.3 ! root 4365: /* Save registers starting from high to low. We've already saved the ! 4366: previous frame pointer and previous return address for the debugger's ! 4367: sake. The debugger allows us to not need a nop in the epilog if at least ! 4368: one register is reloaded in addition to return address. */ 1.1 root 4369: 1.1.1.3 ! root 4370: if (gmask) 1.1 root 4371: { 4372: for (regno = 1; regno <= 31; regno++) 4373: { 1.1.1.3 ! root 4374: if ((gmask & (1L << regno)) != 0) 1.1 root 4375: { 1.1.1.3 ! root 4376: if ((regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0)) 1.1 root 4377: { 1.1.1.3 ! root 4378: /* We can save two registers in a row. If we're not at a ! 4379: double word boundary, move to one. ! 4380: sparc_flat_compute_frame_size ensures there's room to do ! 4381: this. */ ! 4382: if (offset % 8 != 0) ! 4383: offset += UNITS_PER_WORD; ! 4384: 1.1 root 4385: if (word_op[0] == 's') 4386: fprintf (file, "\t%s %s,[%s+%d]\n", 4387: doubleword_op, reg_names[regno], 1.1.1.3 ! root 4388: base_reg, offset); 1.1 root 4389: else 4390: fprintf (file, "\t%s [%s+%d],%s\n", 1.1.1.3 ! root 4391: doubleword_op, base_reg, offset, 1.1 root 4392: reg_names[regno]); 4393: 1.1.1.3 ! root 4394: offset += 2 * UNITS_PER_WORD; 1.1 root 4395: regno++; 4396: } 4397: else 4398: { 4399: if (word_op[0] == 's') 4400: fprintf (file, "\t%s %s,[%s+%d]\n", 4401: word_op, reg_names[regno], 1.1.1.3 ! root 4402: base_reg, offset); 1.1 root 4403: else 4404: fprintf (file, "\t%s [%s+%d],%s\n", 1.1.1.3 ! root 4405: word_op, base_reg, offset, reg_names[regno]); 1.1 root 4406: 1.1.1.3 ! root 4407: offset += UNITS_PER_WORD; 1.1 root 4408: } 4409: } 4410: } 4411: } 4412: 4413: if (fmask) 4414: { 4415: for (regno = 32; regno <= 63; regno++) 4416: { 4417: if ((fmask & (1L << (regno - 32))) != 0) 4418: { 4419: if (word_op[0] == 's') 4420: fprintf (file, "\t%s %s,[%s+%d]\n", 4421: word_op, reg_names[regno], 1.1.1.3 ! root 4422: base_reg, offset); 1.1 root 4423: else 4424: fprintf (file, "\t%s [%s+%d],%s\n", 1.1.1.3 ! root 4425: word_op, base_reg, offset, reg_names[regno]); 1.1 root 4426: 1.1.1.3 ! root 4427: offset += UNITS_PER_WORD; 1.1 root 4428: } 4429: } 4430: } 4431: } 4432: 4433: /* Set up the stack and frame (if desired) for the function. */ 4434: 4435: void 1.1.1.3 ! root 4436: sparc_flat_output_function_prologue (file, size) 1.1 root 4437: FILE *file; 4438: int size; 4439: { 4440: char *sp_str = reg_names[STACK_POINTER_REGNUM]; 1.1.1.3 ! root 4441: unsigned long gmask = current_frame_info.gmask; 1.1 root 4442: 1.1.1.3 ! root 4443: /* This is only for the human reader. */ 1.1 root 4444: fprintf (file, "\t!#PROLOGUE# 0\n"); 1.1.1.3 ! root 4445: fprintf (file, "\t!# vars= %d, regs= %d/%d, args= %d, extra= %d\n", ! 4446: current_frame_info.var_size, ! 4447: current_frame_info.gp_reg_size / 4, ! 4448: current_frame_info.fp_reg_size / 4, ! 4449: current_function_outgoing_args_size, ! 4450: current_frame_info.extra_size); 1.1 root 4451: 4452: size = SPARC_STACK_ALIGN (size); 1.1.1.3 ! root 4453: size = (! current_frame_info.initialized ! 4454: ? sparc_flat_compute_frame_size (size) ! 4455: : current_frame_info.total_size); 1.1 root 4456: 1.1.1.3 ! root 4457: /* These cases shouldn't happen. Catch them now. */ ! 4458: if (size == 0 && (gmask || current_frame_info.fmask)) ! 4459: abort (); ! 4460: ! 4461: /* Allocate our stack frame by decrementing %sp. ! 4462: At present, the only algorithm gdb can use to determine if this is a ! 4463: flat frame is if we always set %i7 if we set %sp. This can be optimized ! 4464: in the future by putting in some sort of debugging information that says ! 4465: this is a `flat' function. However, there is still the case of debugging ! 4466: code without such debugging information (including cases where most fns ! 4467: have such info, but there is one that doesn't). So, always do this now ! 4468: so we don't get a lot of code out there that gdb can't handle. ! 4469: If the frame pointer isn't needn't then that's ok - gdb won't be able to ! 4470: distinguish us from a non-flat function but there won't (and shouldn't) ! 4471: be any differences anyway. The return pc is saved (if necessary) right ! 4472: after %i7 so gdb won't have to look too far to find it. */ ! 4473: if (size > 0) ! 4474: { ! 4475: unsigned int reg_offset = current_frame_info.reg_offset; ! 4476: char *fp_str = reg_names[FRAME_POINTER_REGNUM]; ! 4477: char *t1_str = "%g1"; ! 4478: ! 4479: /* Things get a little tricky if local variables take up more than ~4096 ! 4480: bytes and outgoing arguments take up more than ~4096 bytes. When that ! 4481: happens, the register save area can't be accessed from either end of ! 4482: the frame. Handle this by decrementing %sp to the start of the gp ! 4483: register save area, save the regs, update %i7, and then set %sp to its ! 4484: final value. Given that we only have one scratch register to play ! 4485: with it is the cheapest solution, and it helps gdb out as it won't ! 4486: slow down recognition of flat functions. ! 4487: Don't change the order of insns emitted here without checking with ! 4488: the gdb folk first. */ ! 4489: ! 4490: /* Is the entire register save area offsetable from %sp? */ ! 4491: if (reg_offset < 4096 - 64 * UNITS_PER_WORD) ! 4492: { ! 4493: if (size <= 4096) ! 4494: { ! 4495: fprintf (file, "\tadd %s,%d,%s\n", ! 4496: sp_str, -size, sp_str); ! 4497: if (gmask & FRAME_POINTER_MASK) ! 4498: { ! 4499: fprintf (file, "\tst %s,[%s+%d]\n", ! 4500: fp_str, sp_str, reg_offset); ! 4501: fprintf (file, "\tsub %s,%d,%s\t!# set up frame pointer\n", ! 4502: sp_str, -size, fp_str); ! 4503: reg_offset += 4; ! 4504: } ! 4505: } ! 4506: else ! 4507: { ! 4508: fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n", ! 4509: size, t1_str, sp_str, t1_str, sp_str); ! 4510: if (gmask & FRAME_POINTER_MASK) ! 4511: { ! 4512: fprintf (file, "\tst %s,[%s+%d]\n", ! 4513: fp_str, sp_str, reg_offset); ! 4514: fprintf (file, "\tadd %s,%s,%s\t!# set up frame pointer\n", ! 4515: sp_str, t1_str, fp_str); ! 4516: reg_offset += 4; ! 4517: } ! 4518: } ! 4519: if (gmask & RETURN_ADDR_MASK) ! 4520: { ! 4521: fprintf (file, "\tst %s,[%s+%d]\n", ! 4522: reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset); ! 4523: reg_offset += 4; ! 4524: } ! 4525: sparc_flat_save_restore (file, sp_str, reg_offset, ! 4526: gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), ! 4527: current_frame_info.fmask, ! 4528: "st", "std"); ! 4529: } 1.1 root 4530: else 1.1.1.3 ! root 4531: { ! 4532: /* Subtract %sp in two steps, but make sure there is always a ! 4533: 64 byte register save area, and %sp is properly aligned. */ ! 4534: /* Amount to decrement %sp by, the first time. */ ! 4535: unsigned int size1 = ((size - reg_offset + 64) + 15) & -16; ! 4536: /* Offset to register save area from %sp. */ ! 4537: unsigned int offset = size1 - (size - reg_offset); ! 4538: ! 4539: if (size1 <= 4096) ! 4540: { ! 4541: fprintf (file, "\tadd %s,%d,%s\n", ! 4542: sp_str, -size1, sp_str); ! 4543: if (gmask & FRAME_POINTER_MASK) ! 4544: { ! 4545: fprintf (file, "\tst %s,[%s+%d]\n\tsub %s,%d,%s\t!# set up frame pointer\n", ! 4546: fp_str, sp_str, offset, sp_str, -size1, fp_str); ! 4547: offset += 4; ! 4548: } ! 4549: } ! 4550: else ! 4551: { ! 4552: fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n", ! 4553: size1, t1_str, sp_str, t1_str, sp_str); ! 4554: if (gmask & FRAME_POINTER_MASK) ! 4555: { ! 4556: fprintf (file, "\tst %s,[%s+%d]\n\tadd %s,%s,%s\t!# set up frame pointer\n", ! 4557: fp_str, sp_str, offset, sp_str, t1_str, fp_str); ! 4558: offset += 4; ! 4559: } ! 4560: } ! 4561: if (gmask & RETURN_ADDR_MASK) ! 4562: { ! 4563: fprintf (file, "\tst %s,[%s+%d]\n", ! 4564: reg_names[RETURN_ADDR_REGNUM], sp_str, offset); ! 4565: offset += 4; ! 4566: } ! 4567: sparc_flat_save_restore (file, sp_str, offset, ! 4568: gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), ! 4569: current_frame_info.fmask, ! 4570: "st", "std"); ! 4571: fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n", ! 4572: size - size1, t1_str, sp_str, t1_str, sp_str); ! 4573: } 1.1 root 4574: } 1.1.1.3 ! root 4575: ! 4576: fprintf (file, "\t!#PROLOGUE# 1\n"); 1.1 root 4577: } 4578: 4579: /* Do any necessary cleanup after a function to restore stack, frame, 4580: and regs. */ 4581: 4582: void 1.1.1.3 ! root 4583: sparc_flat_output_function_epilogue (file, size) 1.1 root 4584: FILE *file; 4585: int size; 4586: { 4587: rtx epilogue_delay = current_function_epilogue_delay_list; 4588: int noepilogue = FALSE; 4589: 1.1.1.3 ! root 4590: /* This is only for the human reader. */ ! 4591: fprintf (file, "\t!#EPILOGUE#\n"); ! 4592: 1.1 root 4593: /* The epilogue does not depend on any registers, but the stack 4594: registers, so we assume that if we have 1 pending nop, it can be 4595: ignored, and 2 it must be filled (2 nops occur for integer 4596: multiply and divide). */ 4597: 4598: size = SPARC_STACK_ALIGN (size); 1.1.1.3 ! root 4599: size = (!current_frame_info.initialized ! 4600: ? sparc_flat_compute_frame_size (size) 1.1 root 4601: : current_frame_info.total_size); 4602: 1.1.1.3 ! root 4603: if (size == 0 && epilogue_delay == 0) 1.1 root 4604: { 4605: rtx insn = get_last_insn (); 4606: 4607: /* If the last insn was a BARRIER, we don't have to write any code 4608: because a jump (aka return) was put there. */ 4609: if (GET_CODE (insn) == NOTE) 4610: insn = prev_nonnote_insn (insn); 4611: if (insn && GET_CODE (insn) == BARRIER) 4612: noepilogue = TRUE; 4613: } 4614: 4615: if (!noepilogue) 4616: { 1.1.1.3 ! root 4617: unsigned int reg_offset = current_frame_info.reg_offset; ! 4618: unsigned int size1; ! 4619: char *sp_str = reg_names[STACK_POINTER_REGNUM]; ! 4620: char *fp_str = reg_names[FRAME_POINTER_REGNUM]; ! 4621: char *t1_str = "%g1"; ! 4622: 1.1 root 4623: /* In the reload sequence, we don't need to fill the load delay 4624: slots for most of the loads, also see if we can fill the final 4625: delay slot if not otherwise filled by the reload sequence. */ 4626: 1.1.1.3 ! root 4627: if (size > 4095) ! 4628: fprintf (file, "\tset %d,%s\n", size, t1_str); 1.1 root 4629: 4630: if (frame_pointer_needed) 4631: { 1.1.1.3 ! root 4632: if (size > 4095) ! 4633: fprintf (file,"\tsub %s,%s,%s\t\t!# sp not trusted here\n", 1.1 root 4634: fp_str, t1_str, sp_str); 4635: else 1.1.1.3 ! root 4636: fprintf (file,"\tsub %s,%d,%s\t\t!# sp not trusted here\n", ! 4637: fp_str, size, sp_str); 1.1 root 4638: } 4639: 1.1.1.3 ! root 4640: /* Is the entire register save area offsetable from %sp? */ ! 4641: if (reg_offset < 4096 - 64 * UNITS_PER_WORD) ! 4642: { ! 4643: size1 = 0; ! 4644: } ! 4645: else ! 4646: { ! 4647: /* Restore %sp in two steps, but make sure there is always a ! 4648: 64 byte register save area, and %sp is properly aligned. */ ! 4649: /* Amount to increment %sp by, the first time. */ ! 4650: size1 = ((reg_offset - 64 - 16) + 15) & -16; ! 4651: /* Offset to register save area from %sp. */ ! 4652: reg_offset = size1 - reg_offset; ! 4653: ! 4654: fprintf (file, "\tset %d,%s\n\tadd %s,%s,%s\n", ! 4655: size1, t1_str, sp_str, t1_str, sp_str); ! 4656: } ! 4657: ! 4658: /* We must restore the frame pointer and return address reg first ! 4659: because they are treated specially by the prologue output code. */ ! 4660: if (current_frame_info.gmask & FRAME_POINTER_MASK) ! 4661: { ! 4662: fprintf (file, "\tld [%s+%d],%s\n", ! 4663: sp_str, reg_offset, fp_str); ! 4664: reg_offset += 4; ! 4665: } ! 4666: if (current_frame_info.gmask & RETURN_ADDR_MASK) ! 4667: { ! 4668: fprintf (file, "\tld [%s+%d],%s\n", ! 4669: sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]); ! 4670: reg_offset += 4; ! 4671: } ! 4672: ! 4673: /* Restore any remaining saved registers. */ ! 4674: sparc_flat_save_restore (file, sp_str, reg_offset, ! 4675: current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), ! 4676: current_frame_info.fmask, ! 4677: "ld", "ldd"); ! 4678: ! 4679: /* If we had to increment %sp in two steps, record it so the second ! 4680: restoration in the epilogue finishes up. */ ! 4681: if (size1 > 0) ! 4682: { ! 4683: size -= size1; ! 4684: if (size > 4095) ! 4685: fprintf (file, "\tset %d,%s\n", ! 4686: size, t1_str); ! 4687: } 1.1 root 4688: 4689: if (current_function_returns_struct) 4690: fprintf (file, "\tjmp %%o7+12\n"); 4691: else 4692: fprintf (file, "\tretl\n"); 4693: 4694: /* If the only register saved is the return address, we need a 4695: nop, unless we have an instruction to put into it. Otherwise 4696: we don't since reloading multiple registers doesn't reference 4697: the register being loaded. */ 4698: 4699: if (epilogue_delay) 4700: { 1.1.1.3 ! root 4701: if (size) 1.1 root 4702: abort (); 4703: final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); 4704: } 4705: 1.1.1.3 ! root 4706: else if (size > 4095) 1.1 root 4707: fprintf (file, "\tadd %s,%s,%s\n", sp_str, t1_str, sp_str); 4708: 1.1.1.3 ! root 4709: else if (size > 0) ! 4710: fprintf (file, "\tadd %s,%d,%s\n", sp_str, size, sp_str); 1.1 root 4711: 4712: else 4713: fprintf (file, "\tnop\n"); 4714: } 4715: 4716: /* Reset state info for each function. */ 4717: current_frame_info = zero_frame_info; 4718: } 4719: 4720: /* Define the number of delay slots needed for the function epilogue. 4721: 4722: On the sparc, we need a slot if either no stack has been allocated, 4723: or the only register saved is the return register. */ 4724: 4725: int 1.1.1.3 ! root 4726: sparc_flat_epilogue_delay_slots () 1.1 root 4727: { 4728: if (!current_frame_info.initialized) 1.1.1.3 ! root 4729: (void) sparc_flat_compute_frame_size (get_frame_size ()); 1.1 root 4730: 4731: if (current_frame_info.total_size == 0) 4732: return 1; 4733: 4734: return 0; 4735: } 4736: 4737: /* Return true is TRIAL is a valid insn for the epilogue delay slot. 4738: Any single length instruction which doesn't reference the stack or frame 4739: pointer is OK. */ 4740: 4741: int 1.1.1.3 ! root 4742: sparc_flat_eligible_for_epilogue_delay (trial, slot) 1.1 root 4743: rtx trial; 4744: int slot; 4745: { 4746: if (get_attr_length (trial) == 1 4747: && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial)) 4748: && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial))) 4749: return 1; 4750: return 0; 4751: } 1.1.1.3 ! root 4752: ! 4753: /* Adjust the cost of a scheduling dependency. Return the new cost of ! 4754: a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ ! 4755: ! 4756: int ! 4757: supersparc_adjust_cost (insn, link, dep_insn, cost) ! 4758: rtx insn; ! 4759: rtx link; ! 4760: rtx dep_insn; ! 4761: int cost; ! 4762: { ! 4763: enum attr_type insn_type; ! 4764: ! 4765: if (! recog_memoized (insn)) ! 4766: return 0; ! 4767: ! 4768: insn_type = get_attr_type (insn); ! 4769: ! 4770: if (REG_NOTE_KIND (link) == 0) ! 4771: { ! 4772: /* Data dependency; DEP_INSN writes a register that INSN reads some ! 4773: cycles later. */ ! 4774: ! 4775: /* if a load, then the dependence must be on the memory address; ! 4776: add an extra 'cycle'. Note that the cost could be two cycles ! 4777: if the reg was written late in an instruction group; we can't tell ! 4778: here. */ ! 4779: if (insn_type == TYPE_LOAD || insn_type == TYPE_FPLOAD) ! 4780: return cost + 3; ! 4781: ! 4782: /* Get the delay only if the address of the store is the dependence. */ ! 4783: if (insn_type == TYPE_STORE || insn_type == TYPE_FPSTORE) ! 4784: { ! 4785: rtx pat = PATTERN(insn); ! 4786: rtx dep_pat = PATTERN (dep_insn); ! 4787: ! 4788: if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) ! 4789: return cost; /* This shouldn't happen! */ ! 4790: ! 4791: /* The dependency between the two instructions was on the data that ! 4792: is being stored. Assume that this implies that the address of the ! 4793: store is not dependent. */ ! 4794: if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) ! 4795: return cost; ! 4796: ! 4797: return cost + 3; /* An approximation. */ ! 4798: } ! 4799: ! 4800: /* A shift instruction cannot receive its data from an instruction ! 4801: in the same cycle; add a one cycle penalty. */ ! 4802: if (insn_type == TYPE_SHIFT) ! 4803: return cost + 3; /* Split before cascade into shift. */ ! 4804: } ! 4805: else ! 4806: { ! 4807: /* Anti- or output- dependency; DEP_INSN reads/writes a register that ! 4808: INSN writes some cycles later. */ ! 4809: ! 4810: /* These are only significant for the fpu unit; writing a fp reg before ! 4811: the fpu has finished with it stalls the processor. */ ! 4812: ! 4813: /* Reusing an integer register causes no problems. */ ! 4814: if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT) ! 4815: return 0; ! 4816: } ! 4817: ! 4818: return cost; ! 4819: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.