|
|
1.1 root 1: /* Subroutines used for code generation on the DEC Alpha. 1.1.1.4 ! root 2: Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 1.1.1.3 root 3: Contributed by Richard Kenner ([email protected]) 1.1 root 4: 5: This file is part of GNU CC. 6: 7: GNU CC is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU CC is distributed in the hope that it will be useful, 13: but WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15: GNU General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU CC; see the file COPYING. If not, write to 1.1.1.4 ! root 19: the Free Software Foundation, 59 Temple Place - Suite 330, ! 20: Boston, MA 02111-1307, USA. */ 1.1 root 21: 22: 23: #include <stdio.h> 24: #include "config.h" 25: #include "rtl.h" 26: #include "regs.h" 27: #include "hard-reg-set.h" 28: #include "real.h" 29: #include "insn-config.h" 30: #include "conditions.h" 31: #include "insn-flags.h" 32: #include "output.h" 33: #include "insn-attr.h" 34: #include "flags.h" 35: #include "recog.h" 36: #include "reload.h" 37: #include "expr.h" 38: #include "obstack.h" 39: #include "tree.h" 40: 41: /* Save information from a "cmpxx" operation until the branch or scc is 42: emitted. */ 43: 44: rtx alpha_compare_op0, alpha_compare_op1; 45: int alpha_compare_fp_p; 46: 47: /* Save the name of the current function as used by the assembler. This 48: is used by the epilogue. */ 49: 50: char *alpha_function_name; 51: 1.1.1.2 root 52: /* Non-zero if inside of a function, because the Alpha asm can't 53: handle .files inside of functions. */ 54: 55: static int inside_function = FALSE; 56: 1.1 root 57: /* Nonzero if the current function needs gp. */ 58: 59: int alpha_function_needs_gp; 60: 61: extern char *version_string; 1.1.1.4 ! root 62: extern int rtx_equal_function_value_matters; 1.1.1.3 root 63: 64: /* Declarations of static functions. */ 65: static void alpha_set_memflags_1 PROTO((rtx, int, int, int)); 66: static void add_long_const PROTO((FILE *, HOST_WIDE_INT, int, int, int)); 1.1 root 67: 68: /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ 69: 70: int 71: zap_mask (value) 72: HOST_WIDE_INT value; 73: { 74: int i; 75: 76: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; 77: i++, value >>= 8) 78: if ((value & 0xff) != 0 && (value & 0xff) != 0xff) 79: return 0; 80: 81: return 1; 82: } 83: 84: /* Returns 1 if OP is either the constant zero or a register. If a 85: register, it must be in the proper mode unless MODE is VOIDmode. */ 86: 87: int 88: reg_or_0_operand (op, mode) 89: register rtx op; 90: enum machine_mode mode; 91: { 92: return op == const0_rtx || register_operand (op, mode); 93: } 94: 1.1.1.2 root 95: /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or 96: any register. */ 97: 98: int 99: reg_or_6bit_operand (op, mode) 100: register rtx op; 101: enum machine_mode mode; 102: { 103: return ((GET_CODE (op) == CONST_INT 104: && (unsigned HOST_WIDE_INT) INTVAL (op) < 64) 105: || register_operand (op, mode)); 106: } 107: 108: 1.1 root 109: /* Return 1 if OP is an 8-bit constant or any register. */ 110: 111: int 112: reg_or_8bit_operand (op, mode) 113: register rtx op; 114: enum machine_mode mode; 115: { 116: return ((GET_CODE (op) == CONST_INT 117: && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100) 118: || register_operand (op, mode)); 119: } 120: 1.1.1.3 root 121: /* Return 1 if OP is an 8-bit constant. */ 122: 123: int 124: cint8_operand (op, mode) 125: register rtx op; 126: enum machine_mode mode; 127: { 128: return (GET_CODE (op) == CONST_INT 129: && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100); 130: } 131: 1.1 root 132: /* Return 1 if the operand is a valid second operand to an add insn. */ 133: 134: int 135: add_operand (op, mode) 136: register rtx op; 137: enum machine_mode mode; 138: { 139: if (GET_CODE (op) == CONST_INT) 1.1.1.4 ! root 140: return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K') ! 141: || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L') ! 142: || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O')); 1.1 root 143: 144: return register_operand (op, mode); 145: } 146: 147: /* Return 1 if the operand is a valid second operand to a sign-extending 148: add insn. */ 149: 150: int 151: sext_add_operand (op, mode) 152: register rtx op; 153: enum machine_mode mode; 154: { 155: if (GET_CODE (op) == CONST_INT) 156: return ((unsigned HOST_WIDE_INT) INTVAL (op) < 255 157: || (unsigned HOST_WIDE_INT) (- INTVAL (op)) < 255); 158: 159: return register_operand (op, mode); 160: } 161: 162: /* Return 1 if OP is the constant 4 or 8. */ 163: 164: int 165: const48_operand (op, mode) 166: register rtx op; 167: enum machine_mode mode; 168: { 169: return (GET_CODE (op) == CONST_INT 170: && (INTVAL (op) == 4 || INTVAL (op) == 8)); 171: } 172: 173: /* Return 1 if OP is a valid first operand to an AND insn. */ 174: 175: int 176: and_operand (op, mode) 177: register rtx op; 178: enum machine_mode mode; 179: { 180: if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) 181: return (zap_mask (CONST_DOUBLE_LOW (op)) 182: && zap_mask (CONST_DOUBLE_HIGH (op))); 183: 184: if (GET_CODE (op) == CONST_INT) 185: return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100 186: || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100 187: || zap_mask (INTVAL (op))); 188: 189: return register_operand (op, mode); 190: } 191: 1.1.1.3 root 192: /* Return 1 if OP is a valid first operand to an IOR or XOR insn. */ 193: 194: int 195: or_operand (op, mode) 196: register rtx op; 197: enum machine_mode mode; 198: { 199: if (GET_CODE (op) == CONST_INT) 200: return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100 201: || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100); 202: 203: return register_operand (op, mode); 204: } 205: 1.1 root 206: /* Return 1 if OP is a constant that is the width, in bits, of an integral 207: mode smaller than DImode. */ 208: 209: int 210: mode_width_operand (op, mode) 211: register rtx op; 212: enum machine_mode mode; 213: { 214: return (GET_CODE (op) == CONST_INT 215: && (INTVAL (op) == 8 || INTVAL (op) == 16 || INTVAL (op) == 32)); 216: } 217: 218: /* Return 1 if OP is a constant that is the width of an integral machine mode 219: smaller than an integer. */ 220: 221: int 222: mode_mask_operand (op, mode) 223: register rtx op; 224: enum machine_mode mode; 225: { 226: #if HOST_BITS_PER_WIDE_INT == 32 227: if (GET_CODE (op) == CONST_DOUBLE) 228: return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == -1; 229: #endif 230: 1.1.1.3 root 231: return (GET_CODE (op) == CONST_INT 232: && (INTVAL (op) == 0xff 233: || INTVAL (op) == 0xffff 1.1 root 234: #if HOST_BITS_PER_WIDE_INT == 64 1.1.1.3 root 235: || INTVAL (op) == 0xffffffff 1.1 root 236: #endif 1.1.1.3 root 237: )); 1.1 root 238: } 239: 240: /* Return 1 if OP is a multiple of 8 less than 64. */ 241: 242: int 243: mul8_operand (op, mode) 244: register rtx op; 245: enum machine_mode mode; 246: { 247: return (GET_CODE (op) == CONST_INT 248: && (unsigned HOST_WIDE_INT) INTVAL (op) < 64 249: && (INTVAL (op) & 7) == 0); 250: } 251: 252: /* Return 1 if OP is the constant zero in floating-point. */ 253: 254: int 255: fp0_operand (op, mode) 256: register rtx op; 257: enum machine_mode mode; 258: { 259: return (GET_MODE (op) == mode 260: && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode)); 261: } 262: 263: /* Return 1 if OP is the floating-point constant zero or a register. */ 264: 265: int 266: reg_or_fp0_operand (op, mode) 267: register rtx op; 268: enum machine_mode mode; 269: { 270: return fp0_operand (op, mode) || register_operand (op, mode); 271: } 272: 273: /* Return 1 if OP is a register or a constant integer. */ 274: 275: 276: int 277: reg_or_cint_operand (op, mode) 278: register rtx op; 279: enum machine_mode mode; 280: { 281: return GET_CODE (op) == CONST_INT || register_operand (op, mode); 282: } 283: 1.1.1.3 root 284: /* Return 1 if OP is something that can be reloaded into a register; 285: if it is a MEM, it need not be valid. */ 286: 287: int 288: some_operand (op, mode) 289: register rtx op; 290: enum machine_mode mode; 291: { 292: if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) 293: return 0; 294: 295: switch (GET_CODE (op)) 296: { 297: case REG: case MEM: case CONST_DOUBLE: 298: case CONST_INT: case LABEL_REF: case SYMBOL_REF: case CONST: 299: return 1; 300: 301: case SUBREG: 302: return some_operand (SUBREG_REG (op), VOIDmode); 303: } 304: 305: return 0; 306: } 307: 1.1 root 308: /* Return 1 if OP is a valid operand for the source of a move insn. */ 309: 310: int 311: input_operand (op, mode) 312: register rtx op; 313: enum machine_mode mode; 314: { 315: if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) 316: return 0; 317: 318: if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode) 319: return 0; 320: 321: switch (GET_CODE (op)) 322: { 323: case LABEL_REF: 324: case SYMBOL_REF: 325: case CONST: 1.1.1.4 ! root 326: /* This handles both the Windows/NT and OSF cases. */ ! 327: return mode == ptr_mode || mode == DImode; 1.1 root 328: 329: case REG: 330: return 1; 331: 332: case SUBREG: 333: if (register_operand (op, mode)) 334: return 1; 335: /* ... fall through ... */ 336: case MEM: 337: return mode != HImode && mode != QImode && general_operand (op, mode); 338: 339: case CONST_DOUBLE: 340: return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode); 341: 342: case CONST_INT: 343: return mode == QImode || mode == HImode || add_operand (op, mode); 344: } 345: 346: return 0; 347: } 348: 349: /* Return 1 if OP is a SYMBOL_REF for a function known to be in this 350: file. */ 351: 352: int 353: current_file_function_operand (op, mode) 354: rtx op; 355: enum machine_mode mode; 356: { 357: return (GET_CODE (op) == SYMBOL_REF 1.1.1.4 ! root 358: && ! profile_flag && ! profile_block_flag 1.1 root 359: && (SYMBOL_REF_FLAG (op) 360: || op == XEXP (DECL_RTL (current_function_decl), 0))); 361: } 362: 1.1.1.3 root 363: /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ 364: 365: int 366: call_operand (op, mode) 367: rtx op; 368: enum machine_mode mode; 369: { 370: if (mode != Pmode) 371: return 0; 372: 1.1.1.4 ! root 373: return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG); 1.1.1.3 root 374: } 375: 1.1 root 376: /* Return 1 if OP is a valid Alpha comparison operator. Here we know which 377: comparisons are valid in which insn. */ 378: 379: int 380: alpha_comparison_operator (op, mode) 381: register rtx op; 382: enum machine_mode mode; 383: { 384: enum rtx_code code = GET_CODE (op); 385: 386: if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<') 387: return 0; 388: 389: return (code == EQ || code == LE || code == LT 390: || (mode == DImode && (code == LEU || code == LTU))); 391: } 392: 393: /* Return 1 if OP is a signed comparison operation. */ 394: 395: int 396: signed_comparison_operator (op, mode) 397: register rtx op; 398: enum machine_mode mode; 399: { 400: switch (GET_CODE (op)) 401: { 402: case EQ: case NE: case LE: case LT: case GE: case GT: 403: return 1; 404: } 405: 406: return 0; 407: } 408: 409: /* Return 1 if this is a divide or modulus operator. */ 410: 411: int 412: divmod_operator (op, mode) 413: register rtx op; 414: enum machine_mode mode; 415: { 416: switch (GET_CODE (op)) 417: { 418: case DIV: case MOD: case UDIV: case UMOD: 419: return 1; 420: } 421: 422: return 0; 423: } 424: 425: /* Return 1 if this memory address is a known aligned register plus 426: a constant. It must be a valid address. This means that we can do 427: this as an aligned reference plus some offset. 428: 429: Take into account what reload will do. 430: 431: We could say that out-of-range stack slots are alignable, but that would 432: complicate get_aligned_mem and it isn't worth the trouble since few 433: functions have large stack space. */ 434: 435: int 436: aligned_memory_operand (op, mode) 437: register rtx op; 438: enum machine_mode mode; 439: { 440: if (GET_CODE (op) == SUBREG) 441: { 442: if (GET_MODE (op) != mode) 443: return 0; 444: op = SUBREG_REG (op); 445: mode = GET_MODE (op); 446: } 447: 448: if (reload_in_progress && GET_CODE (op) == REG 449: && REGNO (op) >= FIRST_PSEUDO_REGISTER) 450: op = reg_equiv_mem[REGNO (op)]; 451: 452: if (GET_CODE (op) != MEM || GET_MODE (op) != mode 453: || ! memory_address_p (mode, XEXP (op, 0))) 454: return 0; 455: 456: op = XEXP (op, 0); 457: 458: if (GET_CODE (op) == PLUS) 459: op = XEXP (op, 0); 460: 461: return (GET_CODE (op) == REG 1.1.1.3 root 462: && (REGNO (op) == STACK_POINTER_REGNUM 463: || op == hard_frame_pointer_rtx 1.1 root 464: || (REGNO (op) >= FIRST_VIRTUAL_REGISTER 465: && REGNO (op) <= LAST_VIRTUAL_REGISTER))); 466: } 467: 468: /* Similar, but return 1 if OP is a MEM which is not alignable. */ 469: 470: int 471: unaligned_memory_operand (op, mode) 472: register rtx op; 473: enum machine_mode mode; 474: { 475: if (GET_CODE (op) == SUBREG) 476: { 477: if (GET_MODE (op) != mode) 478: return 0; 479: op = SUBREG_REG (op); 480: mode = GET_MODE (op); 481: } 482: 483: if (reload_in_progress && GET_CODE (op) == REG 484: && REGNO (op) >= FIRST_PSEUDO_REGISTER) 485: op = reg_equiv_mem[REGNO (op)]; 486: 487: if (GET_CODE (op) != MEM || GET_MODE (op) != mode) 488: return 0; 489: 490: op = XEXP (op, 0); 491: 492: if (! memory_address_p (mode, op)) 493: return 1; 494: 495: if (GET_CODE (op) == PLUS) 496: op = XEXP (op, 0); 497: 498: return (GET_CODE (op) != REG 1.1.1.3 root 499: || (REGNO (op) != STACK_POINTER_REGNUM 500: && op != hard_frame_pointer_rtx 1.1 root 501: && (REGNO (op) < FIRST_VIRTUAL_REGISTER 502: || REGNO (op) > LAST_VIRTUAL_REGISTER))); 503: } 504: 505: /* Return 1 if OP is any memory location. During reload a pseudo matches. */ 506: 507: int 508: any_memory_operand (op, mode) 509: register rtx op; 510: enum machine_mode mode; 511: { 512: return (GET_CODE (op) == MEM 513: || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) 514: || (reload_in_progress && GET_CODE (op) == REG 515: && REGNO (op) >= FIRST_PSEUDO_REGISTER) 516: || (reload_in_progress && GET_CODE (op) == SUBREG 517: && GET_CODE (SUBREG_REG (op)) == REG 518: && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)); 519: } 520: 521: /* REF is an alignable memory location. Place an aligned SImode 522: reference into *PALIGNED_MEM and the number of bits to shift into 523: *PBITNUM. */ 524: 525: void 526: get_aligned_mem (ref, paligned_mem, pbitnum) 527: rtx ref; 528: rtx *paligned_mem, *pbitnum; 529: { 530: rtx base; 531: HOST_WIDE_INT offset = 0; 532: 533: if (GET_CODE (ref) == SUBREG) 534: { 535: offset = SUBREG_WORD (ref) * UNITS_PER_WORD; 536: if (BYTES_BIG_ENDIAN) 537: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) 538: - MIN (UNITS_PER_WORD, 539: GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); 540: ref = SUBREG_REG (ref); 541: } 542: 543: if (GET_CODE (ref) == REG) 544: ref = reg_equiv_mem[REGNO (ref)]; 545: 546: if (reload_in_progress) 547: base = find_replacement (&XEXP (ref, 0)); 548: else 549: base = XEXP (ref, 0); 550: 551: if (GET_CODE (base) == PLUS) 552: offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); 553: 554: *paligned_mem = gen_rtx (MEM, SImode, 555: plus_constant (base, offset & ~3)); 556: MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref); 557: MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref); 558: RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref); 559: 560: *pbitnum = GEN_INT ((offset & 3) * 8); 561: } 562: 563: /* Similar, but just get the address. Handle the two reload cases. */ 564: 565: rtx 566: get_unaligned_address (ref) 567: rtx ref; 568: { 569: rtx base; 570: HOST_WIDE_INT offset = 0; 571: 572: if (GET_CODE (ref) == SUBREG) 573: { 574: offset = SUBREG_WORD (ref) * UNITS_PER_WORD; 575: if (BYTES_BIG_ENDIAN) 576: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) 577: - MIN (UNITS_PER_WORD, 578: GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); 579: ref = SUBREG_REG (ref); 580: } 581: 582: if (GET_CODE (ref) == REG) 583: ref = reg_equiv_mem[REGNO (ref)]; 584: 585: if (reload_in_progress) 586: base = find_replacement (&XEXP (ref, 0)); 587: else 588: base = XEXP (ref, 0); 589: 590: if (GET_CODE (base) == PLUS) 591: offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); 592: 593: return plus_constant (base, offset); 594: } 595: 596: /* Subfunction of the following function. Update the flags of any MEM 597: found in part of X. */ 598: 599: static void 600: alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) 601: rtx x; 602: int in_struct_p, volatile_p, unchanging_p; 603: { 604: int i; 605: 606: switch (GET_CODE (x)) 607: { 608: case SEQUENCE: 609: case PARALLEL: 610: for (i = XVECLEN (x, 0) - 1; i >= 0; i--) 611: alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, 612: unchanging_p); 613: break; 614: 615: case INSN: 616: alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p, 617: unchanging_p); 618: break; 619: 620: case SET: 621: alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p, 622: unchanging_p); 623: alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, 624: unchanging_p); 625: break; 626: 627: case MEM: 628: MEM_IN_STRUCT_P (x) = in_struct_p; 629: MEM_VOLATILE_P (x) = volatile_p; 630: RTX_UNCHANGING_P (x) = unchanging_p; 631: break; 632: } 633: } 634: 635: /* Given INSN, which is either an INSN or a SEQUENCE generated to 636: perform a memory operation, look for any MEMs in either a SET_DEST or 637: a SET_SRC and copy the in-struct, unchanging, and volatile flags from 638: REF into each of the MEMs found. If REF is not a MEM, don't do 639: anything. */ 640: 641: void 642: alpha_set_memflags (insn, ref) 643: rtx insn; 644: rtx ref; 645: { 646: /* Note that it is always safe to get these flags, though they won't 647: be what we think if REF is not a MEM. */ 648: int in_struct_p = MEM_IN_STRUCT_P (ref); 649: int volatile_p = MEM_VOLATILE_P (ref); 650: int unchanging_p = RTX_UNCHANGING_P (ref); 651: 652: if (GET_CODE (ref) != MEM 653: || (! in_struct_p && ! volatile_p && ! unchanging_p)) 654: return; 655: 656: alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p); 657: } 658: 659: /* Try to output insns to set TARGET equal to the constant C if it can be 1.1.1.4 ! root 660: done in less than N insns. Do all computations in MODE. Returns the place ! 661: where the output has been placed if it can be done and the insns have been ! 662: emitted. If it would take more than N insns, zero is returned and no ! 663: insns and emitted. */ 1.1 root 664: 1.1.1.4 ! root 665: rtx ! 666: alpha_emit_set_const (target, mode, c, n) 1.1 root 667: rtx target; 1.1.1.4 ! root 668: enum machine_mode mode; 1.1 root 669: HOST_WIDE_INT c; 670: int n; 671: { 672: HOST_WIDE_INT new = c; 673: int i, bits; 1.1.1.4 ! root 674: /* Use a pseudo if highly optimizing and still generating RTL. */ ! 675: rtx subtarget ! 676: = (flag_expensive_optimizations && rtx_equal_function_value_matters ! 677: ? 0 : target); ! 678: rtx temp; 1.1 root 679: 680: #if HOST_BITS_PER_WIDE_INT == 64 681: /* We are only called for SImode and DImode. If this is SImode, ensure that 682: we are sign extended to a full word. This does not make any sense when 683: cross-compiling on a narrow machine. */ 684: 1.1.1.4 ! root 685: if (mode == SImode) 1.1 root 686: c = (c & 0xffffffff) - 2 * (c & 0x80000000); 687: #endif 688: 689: /* If this is a sign-extended 32-bit constant, we can do this in at most 690: three insns, so do it if we have enough insns left. We always have 1.1.1.4 ! root 691: a sign-extended 32-bit constant when compiling on a narrow machine. ! 692: Note that we cannot handle the constant 0x80000000. */ 1.1 root 693: 1.1.1.4 ! root 694: if ((HOST_BITS_PER_WIDE_INT != 64 ! 695: || c >> 31 == -1 || c >> 31 == 0) ! 696: && c != 0x80000000U) 1.1 root 697: { 698: HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); 699: HOST_WIDE_INT tmp1 = c - low; 700: HOST_WIDE_INT high 701: = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); 702: HOST_WIDE_INT extra = 0; 703: 704: /* If HIGH will be interpreted as negative but the constant is 705: positive, we must adjust it to do two ldha insns. */ 706: 707: if ((high & 0x8000) != 0 && c >= 0) 708: { 709: extra = 0x4000; 710: tmp1 -= 0x40000000; 711: high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); 712: } 713: 714: if (c == low || (low == 0 && extra == 0)) 1.1.1.4 ! root 715: return copy_to_suggested_reg (GEN_INT (c), target, mode); ! 716: else if (n >= 2 + (extra != 0) ! 717: /* We can't do this when SImode if HIGH required adjustment. ! 718: This is because the code relies on an implicit overflow ! 719: which is invisible to the RTL. We can thus get incorrect ! 720: code if the two ldah instructions are combined. */ ! 721: && ! (mode == SImode && extra != 0)) 1.1 root 722: { 1.1.1.4 ! root 723: temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode); ! 724: 1.1 root 725: if (extra != 0) 1.1.1.4 ! root 726: temp = expand_binop (mode, add_optab, temp, GEN_INT (extra << 16), ! 727: subtarget, 0, OPTAB_WIDEN); 1.1 root 728: 1.1.1.4 ! root 729: return expand_binop (mode, add_optab, temp, GEN_INT (high << 16), ! 730: target, 0, OPTAB_WIDEN); 1.1 root 731: } 732: } 733: 1.1.1.4 ! root 734: /* If we couldn't do it that way, try some other methods. But if we have ! 735: no instructions left, don't bother. Likewise, if this is SImode and ! 736: we can't make pseudos, we can't do anything since the expand_binop ! 737: and expand_unop calls will widen and try to make pseudos. */ 1.1 root 738: 1.1.1.4 ! root 739: if (n == 1 ! 740: || (mode == SImode && ! rtx_equal_function_value_matters)) 1.1 root 741: return 0; 742: 1.1.1.4 ! root 743: #if HOST_BITS_PER_WIDE_INT == 64 1.1 root 744: /* First, see if can load a value into the target that is the same as the 745: constant except that all bytes that are 0 are changed to be 0xff. If we 746: can, then we can do a ZAPNOT to obtain the desired constant. */ 747: 748: for (i = 0; i < 64; i += 8) 749: if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0) 750: new |= (HOST_WIDE_INT) 0xff << i; 751: 1.1.1.4 ! root 752: /* We are only called for SImode and DImode. If this is SImode, ensure that ! 753: we are sign extended to a full word. */ ! 754: ! 755: if (mode == SImode) ! 756: new = (new & 0xffffffff) - 2 * (new & 0x80000000); ! 757: ! 758: if (new != c ! 759: && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0) ! 760: return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new), ! 761: target, 0, OPTAB_WIDEN); ! 762: #endif 1.1 root 763: 1.1.1.4 ! root 764: /* Next, see if we can load a related constant and then shift and possibly 1.1 root 765: negate it to get the constant we want. Try this once each increasing 766: numbers of insns. */ 767: 768: for (i = 1; i < n; i++) 769: { 770: /* First try complementing. */ 1.1.1.4 ! root 771: if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0) ! 772: return expand_unop (mode, one_cmpl_optab, temp, target, 0); 1.1 root 773: 1.1.1.4 ! root 774: /* Next try to form a constant and do a left shift. We can do this 1.1 root 775: if some low-order bits are zero; the exact_log2 call below tells 776: us that information. The bits we are shifting out could be any 777: value, but here we'll just try the 0- and sign-extended forms of 778: the constant. To try to increase the chance of having the same 779: constant in more than one insn, start at the highest number of 780: bits to shift, but try all possibilities in case a ZAPNOT will 781: be useful. */ 782: 783: if ((bits = exact_log2 (c & - c)) > 0) 784: for (; bits > 0; bits--) 1.1.1.4 ! root 785: if ((temp = (alpha_emit_set_const ! 786: (subtarget, mode, ! 787: (unsigned HOST_WIDE_INT) c >> bits, i))) != 0 ! 788: || ((temp = (alpha_emit_set_const ! 789: (subtarget, mode, ! 790: ((unsigned HOST_WIDE_INT) c) >> bits, i))) ! 791: != 0)) ! 792: return expand_binop (mode, ashl_optab, temp, GEN_INT (bits), ! 793: target, 0, OPTAB_WIDEN); 1.1 root 794: 795: /* Now try high-order zero bits. Here we try the shifted-in bits as 1.1.1.4 ! root 796: all zero and all ones. Be careful to avoid shifting outside the ! 797: mode and to avoid shifting outside the host wide int size. */ 1.1 root 798: 1.1.1.4 ! root 799: if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) ! 800: - floor_log2 (c) - 1)) > 0) 1.1 root 801: for (; bits > 0; bits--) 1.1.1.4 ! root 802: if ((temp = alpha_emit_set_const (subtarget, mode, ! 803: c << bits, i)) != 0 ! 804: || ((temp = (alpha_emit_set_const ! 805: (subtarget, mode, ! 806: ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)), ! 807: i))) ! 808: != 0)) ! 809: return expand_binop (mode, lshr_optab, temp, GEN_INT (bits), ! 810: target, 1, OPTAB_WIDEN); 1.1 root 811: 812: /* Now try high-order 1 bits. We get that with a sign-extension. 1.1.1.4 ! root 813: But one bit isn't enough here. Be careful to avoid shifting outside ! 814: the mode and to avoid shifting outside the host wide int size. */ 1.1 root 815: 1.1.1.4 ! root 816: if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) ! 817: - floor_log2 (~ c) - 2)) > 0) 1.1 root 818: for (; bits > 0; bits--) 1.1.1.4 ! root 819: if ((temp = alpha_emit_set_const (subtarget, mode, ! 820: c << bits, i)) != 0 ! 821: || ((temp = (alpha_emit_set_const ! 822: (subtarget, mode, ! 823: ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)), ! 824: i))) ! 825: != 0)) ! 826: return expand_binop (mode, ashr_optab, temp, GEN_INT (bits), ! 827: target, 0, OPTAB_WIDEN); 1.1 root 828: } 829: 830: return 0; 831: } 832: 833: /* Adjust the cost of a scheduling dependency. Return the new cost of 834: a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ 835: 836: int 837: alpha_adjust_cost (insn, link, dep_insn, cost) 838: rtx insn; 839: rtx link; 840: rtx dep_insn; 841: int cost; 842: { 843: rtx set; 844: 845: /* If the dependence is an anti-dependence, there is no cost. For an 846: output dependence, there is sometimes a cost, but it doesn't seem 847: worth handling those few cases. */ 848: 849: if (REG_NOTE_KIND (link) != 0) 850: return 0; 851: 852: /* If INSN is a store insn and DEP_INSN is setting the data being stored, 853: we can sometimes lower the cost. */ 854: 855: if (recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_ST 856: && (set = single_set (dep_insn)) != 0 857: && GET_CODE (PATTERN (insn)) == SET 858: && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) 859: switch (get_attr_type (dep_insn)) 860: { 861: case TYPE_LD: 862: /* No savings here. */ 863: return cost; 864: 865: case TYPE_IMULL: 866: case TYPE_IMULQ: 867: /* In these cases, we save one cycle. */ 868: return cost - 2; 869: 870: default: 871: /* In all other cases, we save two cycles. */ 872: return MAX (0, cost - 4); 873: } 874: 875: /* Another case that needs adjustment is an arithmetic or logical 876: operation. It's cost is usually one cycle, but we default it to 877: two in the MD file. The only case that it is actually two is 878: for the address in loads and stores. */ 879: 880: if (recog_memoized (dep_insn) >= 0 881: && get_attr_type (dep_insn) == TYPE_IADDLOG) 882: switch (get_attr_type (insn)) 883: { 884: case TYPE_LD: 885: case TYPE_ST: 886: return cost; 887: 888: default: 889: return 2; 890: } 891: 892: /* The final case is when a compare feeds into an integer branch. The cost 893: is only one cycle in that case. */ 894: 895: if (recog_memoized (dep_insn) >= 0 896: && get_attr_type (dep_insn) == TYPE_ICMP 897: && recog_memoized (insn) >= 0 898: && get_attr_type (insn) == TYPE_IBR) 899: return 2; 900: 901: /* Otherwise, return the default cost. */ 902: 903: return cost; 904: } 905: 906: /* Print an operand. Recognize special options, documented below. */ 907: 908: void 909: print_operand (file, x, code) 910: FILE *file; 911: rtx x; 912: char code; 913: { 914: int i; 915: 916: switch (code) 917: { 918: case 'r': 919: /* If this operand is the constant zero, write it as "$31". */ 920: if (GET_CODE (x) == REG) 921: fprintf (file, "%s", reg_names[REGNO (x)]); 922: else if (x == CONST0_RTX (GET_MODE (x))) 923: fprintf (file, "$31"); 924: else 925: output_operand_lossage ("invalid %%r value"); 926: 927: break; 928: 929: case 'R': 930: /* Similar, but for floating-point. */ 931: if (GET_CODE (x) == REG) 932: fprintf (file, "%s", reg_names[REGNO (x)]); 933: else if (x == CONST0_RTX (GET_MODE (x))) 934: fprintf (file, "$f31"); 935: else 936: output_operand_lossage ("invalid %%R value"); 937: 938: break; 939: 940: case 'N': 941: /* Write the 1's complement of a constant. */ 942: if (GET_CODE (x) != CONST_INT) 943: output_operand_lossage ("invalid %%N value"); 944: 945: fprintf (file, "%ld", ~ INTVAL (x)); 946: break; 947: 948: case 'P': 949: /* Write 1 << C, for a constant C. */ 950: if (GET_CODE (x) != CONST_INT) 951: output_operand_lossage ("invalid %%P value"); 952: 953: fprintf (file, "%ld", (HOST_WIDE_INT) 1 << INTVAL (x)); 954: break; 955: 956: case 'h': 957: /* Write the high-order 16 bits of a constant, sign-extended. */ 958: if (GET_CODE (x) != CONST_INT) 959: output_operand_lossage ("invalid %%h value"); 960: 961: fprintf (file, "%ld", INTVAL (x) >> 16); 962: break; 963: 964: case 'L': 965: /* Write the low-order 16 bits of a constant, sign-extended. */ 966: if (GET_CODE (x) != CONST_INT) 967: output_operand_lossage ("invalid %%L value"); 968: 969: fprintf (file, "%ld", (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000)); 970: break; 971: 972: case 'm': 973: /* Write mask for ZAP insn. */ 974: if (GET_CODE (x) == CONST_DOUBLE) 975: { 976: HOST_WIDE_INT mask = 0; 977: HOST_WIDE_INT value; 978: 979: value = CONST_DOUBLE_LOW (x); 980: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; 981: i++, value >>= 8) 982: if (value & 0xff) 983: mask |= (1 << i); 984: 985: value = CONST_DOUBLE_HIGH (x); 986: for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; 987: i++, value >>= 8) 988: if (value & 0xff) 989: mask |= (1 << (i + sizeof (int))); 990: 991: fprintf (file, "%ld", mask & 0xff); 992: } 993: 994: else if (GET_CODE (x) == CONST_INT) 995: { 996: HOST_WIDE_INT mask = 0, value = INTVAL (x); 997: 998: for (i = 0; i < 8; i++, value >>= 8) 999: if (value & 0xff) 1000: mask |= (1 << i); 1001: 1002: fprintf (file, "%ld", mask); 1003: } 1004: else 1005: output_operand_lossage ("invalid %%m value"); 1006: break; 1007: 1008: case 'M': 1009: /* 'b', 'w', or 'l' as the value of the constant. */ 1010: if (GET_CODE (x) != CONST_INT 1011: || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32)) 1012: output_operand_lossage ("invalid %%M value"); 1013: 1014: fprintf (file, "%s", 1015: INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l"); 1016: break; 1017: 1018: case 'U': 1019: /* Similar, except do it from the mask. */ 1020: if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff) 1021: fprintf (file, "b"); 1022: else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff) 1023: fprintf (file, "w"); 1024: #if HOST_BITS_PER_WIDE_INT == 32 1025: else if (GET_CODE (x) == CONST_DOUBLE 1026: && CONST_DOUBLE_HIGH (x) == 0 1027: && CONST_DOUBLE_LOW (x) == -1) 1028: fprintf (file, "l"); 1029: #else 1030: else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) 1031: fprintf (file, "l"); 1032: #endif 1033: else 1034: output_operand_lossage ("invalid %%U value"); 1035: break; 1036: 1037: case 's': 1038: /* Write the constant value divided by 8. */ 1039: if (GET_CODE (x) != CONST_INT 1040: && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 1041: && (INTVAL (x) & 7) != 8) 1042: output_operand_lossage ("invalid %%s value"); 1043: 1044: fprintf (file, "%ld", INTVAL (x) / 8); 1045: break; 1046: 1047: case 'S': 1048: /* Same, except compute (64 - c) / 8 */ 1049: 1050: if (GET_CODE (x) != CONST_INT 1051: && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 1052: && (INTVAL (x) & 7) != 8) 1053: output_operand_lossage ("invalid %%s value"); 1054: 1055: fprintf (file, "%ld", (64 - INTVAL (x)) / 8); 1056: break; 1057: 1058: case 'C': 1059: /* Write out comparison name. */ 1060: if (GET_RTX_CLASS (GET_CODE (x)) != '<') 1061: output_operand_lossage ("invalid %%C value"); 1062: 1063: if (GET_CODE (x) == LEU) 1064: fprintf (file, "ule"); 1065: else if (GET_CODE (x) == LTU) 1066: fprintf (file, "ult"); 1067: else 1068: fprintf (file, "%s", GET_RTX_NAME (GET_CODE (x))); 1069: break; 1070: 1071: case 'D': 1072: /* Similar, but write reversed code. We can't get an unsigned code 1073: here. */ 1074: if (GET_RTX_CLASS (GET_CODE (x)) != '<') 1075: output_operand_lossage ("invalid %%D value"); 1076: 1077: fprintf (file, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x)))); 1078: break; 1079: 1.1.1.4 ! root 1080: case 'c': ! 1081: /* Similar to `c', but swap. We can't get unsigned here either. */ ! 1082: if (GET_RTX_CLASS (GET_CODE (x)) != '<') ! 1083: output_operand_lossage ("invalid %%D value"); ! 1084: ! 1085: fprintf (file, "%s", GET_RTX_NAME (swap_condition (GET_CODE (x)))); ! 1086: break; ! 1087: ! 1088: case 'd': ! 1089: /* Similar, but reverse and swap. We can't get unsigned here either. */ ! 1090: if (GET_RTX_CLASS (GET_CODE (x)) != '<') ! 1091: output_operand_lossage ("invalid %%D value"); ! 1092: ! 1093: fprintf (file, "%s", ! 1094: GET_RTX_NAME (swap_condition (reverse_condition ((GET_CODE (x)))))); ! 1095: break; ! 1096: 1.1 root 1097: case 'E': 1098: /* Write the divide or modulus operator. */ 1099: switch (GET_CODE (x)) 1100: { 1101: case DIV: 1102: fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q"); 1103: break; 1104: case UDIV: 1105: fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q"); 1106: break; 1107: case MOD: 1108: fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q"); 1109: break; 1110: case UMOD: 1111: fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q"); 1112: break; 1113: default: 1114: output_operand_lossage ("invalid %%E value"); 1115: break; 1116: } 1117: break; 1118: 1119: case 'A': 1120: /* Write "_u" for unaligned access. */ 1121: if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND) 1122: fprintf (file, "_u"); 1123: break; 1124: 1125: case 0: 1126: if (GET_CODE (x) == REG) 1127: fprintf (file, "%s", reg_names[REGNO (x)]); 1128: else if (GET_CODE (x) == MEM) 1129: output_address (XEXP (x, 0)); 1130: else 1131: output_addr_const (file, x); 1132: break; 1133: 1134: default: 1135: output_operand_lossage ("invalid %%xn code"); 1136: } 1137: } 1138: 1139: /* Do what is necessary for `va_start'. The argument is ignored; 1140: We look at the current function to determine if stdarg or varargs 1141: is used and fill in an initial va_list. A pointer to this constructor 1142: is returned. */ 1143: 1144: struct rtx_def * 1145: alpha_builtin_saveregs (arglist) 1146: tree arglist; 1147: { 1148: rtx block, addr, argsize; 1149: tree fntype = TREE_TYPE (current_function_decl); 1150: int stdarg = (TYPE_ARG_TYPES (fntype) != 0 1151: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 1152: != void_type_node)); 1153: 1154: /* Compute the current position into the args, taking into account 1.1.1.3 root 1155: both registers and memory. Both of these are already included in 1156: current_function_args_info. */ 1157: 1158: argsize = GEN_INT (current_function_args_info * UNITS_PER_WORD); 1.1 root 1159: 1.1.1.3 root 1160: /* SETUP_INCOMING_VARARGS moves the starting address base up by 48, 1161: storing fp arg registers in the first 48 bytes, and the integer arg 1162: registers in the next 48 bytes. This is only done, however, if any 1163: integer registers need to be stored. 1164: 1165: If no integer registers need be stored, then we must subtract 48 in 1166: order to account for the integer arg registers which are counted in 1167: argsize above, but which are not actually stored on the stack. */ 1168: 1.1.1.4 ! root 1169: addr = (current_function_args_info <= 5 + stdarg 1.1.1.3 root 1170: ? plus_constant (virtual_incoming_args_rtx, 6 * UNITS_PER_WORD) 1171: : plus_constant (virtual_incoming_args_rtx, - (6 * UNITS_PER_WORD))); 1.1 root 1172: 1.1.1.4 ! root 1173: addr = force_operand (addr, NULL_RTX); ! 1174: 1.1 root 1175: /* Allocate the va_list constructor */ 1176: block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD); 1177: RTX_UNCHANGING_P (block) = 1; 1178: RTX_UNCHANGING_P (XEXP (block, 0)) = 1; 1179: 1.1.1.4 ! root 1180: /* Store the address of the first integer register in the __base member. */ ! 1181: ! 1182: #ifdef POINTERS_EXTEND_UNSIGNED ! 1183: addr = convert_memory_address (ptr_mode, addr); ! 1184: #endif ! 1185: ! 1186: emit_move_insn (change_address (block, ptr_mode, XEXP (block, 0)), addr); 1.1 root 1187: 1188: /* Store the argsize as the __va_offset member. */ 1.1.1.4 ! root 1189: emit_move_insn (change_address (block, TYPE_MODE (integer_type_node), 1.1 root 1190: plus_constant (XEXP (block, 0), 1.1.1.4 ! root 1191: POINTER_SIZE/BITS_PER_UNIT)), ! 1192: argsize); 1.1 root 1193: 1194: /* Return the address of the va_list constructor, but don't put it in a 1195: register. Doing so would fail when not optimizing and produce worse 1196: code when optimizing. */ 1197: return XEXP (block, 0); 1198: } 1199: 1200: /* This page contains routines that are used to determine what the function 1201: prologue and epilogue code will do and write them out. */ 1202: 1203: /* Compute the size of the save area in the stack. */ 1204: 1205: int 1206: alpha_sa_size () 1207: { 1208: int size = 0; 1209: int i; 1210: 1211: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1212: if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i]) 1213: size++; 1214: 1215: /* If some registers were saved but not reg 26, reg 26 must also 1216: be saved, so leave space for it. */ 1217: if (size != 0 && ! regs_ever_live[26]) 1218: size++; 1219: 1.1.1.3 root 1220: /* Our size must be even (multiple of 16 bytes). */ 1221: if (size & 1) 1222: size ++; 1223: 1.1 root 1224: return size * 8; 1225: } 1226: 1227: /* Return 1 if this function can directly return via $26. */ 1228: 1229: int 1230: direct_return () 1231: { 1232: return (reload_completed && alpha_sa_size () == 0 1233: && get_frame_size () == 0 1.1.1.4 ! root 1234: && current_function_outgoing_args_size == 0 1.1 root 1235: && current_function_pretend_args_size == 0); 1236: } 1237: 1238: /* Write a version stamp. Don't write anything if we are running as a 1239: cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */ 1240: 1.1.1.4 ! root 1241: #if !defined(CROSS_COMPILE) && !defined(_WIN32) 1.1 root 1242: #include <stamp.h> 1243: #endif 1244: 1245: void 1246: alpha_write_verstamp (file) 1247: FILE *file; 1248: { 1249: #ifdef MS_STAMP 1250: char *p; 1251: 1252: fprintf (file, "\t.verstamp %d %d ", MS_STAMP, LS_STAMP); 1253: for (p = version_string; *p != ' ' && *p != 0; p++) 1254: fprintf (file, "%c", *p == '.' ? ' ' : *p); 1255: fprintf (file, "\n"); 1256: #endif 1257: } 1.1.1.2 root 1258: 1259: /* Write code to add constant C to register number IN_REG (possibly 31) 1.1.1.3 root 1260: and put the result into OUT_REG. Use TEMP_REG as a scratch register; 1261: usually this will be OUT_REG, but should not be if OUT_REG is 1262: STACK_POINTER_REGNUM, since it must be updated in a single instruction. 1263: Write the code to FILE. */ 1.1.1.2 root 1264: 1265: static void 1.1.1.3 root 1266: add_long_const (file, c, in_reg, out_reg, temp_reg) 1.1.1.2 root 1267: FILE *file; 1.1.1.3 root 1268: HOST_WIDE_INT c; 1269: int in_reg, out_reg, temp_reg; 1.1.1.2 root 1270: { 1271: HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); 1272: HOST_WIDE_INT tmp1 = c - low; 1273: HOST_WIDE_INT high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); 1274: HOST_WIDE_INT extra = 0; 1275: 1276: /* We don't have code to write out constants larger than 32 bits. */ 1277: #if HOST_BITS_PER_LONG_INT == 64 1278: if ((unsigned HOST_WIDE_INT) c >> 32 != 0) 1279: abort (); 1280: #endif 1281: 1282: /* If HIGH will be interpreted as negative, we must adjust it to do two 1283: ldha insns. Note that we will never be building a negative constant 1284: here. */ 1285: 1286: if (high & 0x8000) 1287: { 1288: extra = 0x4000; 1289: tmp1 -= 0x40000000; 1290: high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); 1291: } 1292: 1293: if (low != 0) 1294: { 1.1.1.3 root 1295: int result_reg = (extra == 0 && high == 0) ? out_reg : temp_reg; 1296: 1.1.1.2 root 1297: if (low >= 0 && low < 255) 1.1.1.3 root 1298: fprintf (file, "\taddq $%d,%d,$%d\n", in_reg, low, result_reg); 1.1.1.2 root 1299: else 1.1.1.3 root 1300: fprintf (file, "\tlda $%d,%d($%d)\n", result_reg, low, in_reg); 1301: 1302: in_reg = result_reg; 1.1.1.2 root 1303: } 1304: 1305: if (extra) 1306: { 1.1.1.3 root 1307: int result_reg = (high == 0) ? out_reg : temp_reg; 1308: 1309: fprintf (file, "\tldah $%d,%d($%d)\n", result_reg, extra, in_reg); 1310: in_reg = result_reg; 1.1.1.2 root 1311: } 1312: 1313: if (high) 1314: fprintf (file, "\tldah $%d,%d($%d)\n", out_reg, high, in_reg); 1315: } 1.1 root 1316: 1317: /* Write function prologue. */ 1318: 1319: void 1320: output_prolog (file, size) 1321: FILE *file; 1322: int size; 1323: { 1.1.1.3 root 1324: HOST_WIDE_INT out_args_size 1325: = ALPHA_ROUND (current_function_outgoing_args_size); 1326: HOST_WIDE_INT sa_size = alpha_sa_size (); 1327: HOST_WIDE_INT frame_size 1328: = (out_args_size + sa_size 1329: + ALPHA_ROUND (size + current_function_pretend_args_size)); 1330: HOST_WIDE_INT reg_offset = out_args_size; 1.1.1.2 root 1331: HOST_WIDE_INT start_reg_offset = reg_offset; 1332: HOST_WIDE_INT actual_start_reg_offset = start_reg_offset; 1.1.1.3 root 1333: int int_reg_save_area_size = 0; 1.1 root 1334: rtx insn; 1335: unsigned reg_mask = 0; 1336: int i; 1337: 1.1.1.3 root 1338: /* Ecoff can handle multiple .file directives, so put out file and lineno. 1.1.1.2 root 1339: We have to do that before the .ent directive as we cannot switch 1340: files within procedures with native ecoff because line numbers are 1341: linked to procedure descriptors. 1342: Outputting the lineno helps debugging of one line functions as they 1343: would otherwise get no line number at all. Please note that we would 1.1.1.4 ! root 1344: like to put out last_linenum from final.c, but it is not accessible. */ 1.1.1.2 root 1345: 1346: if (write_symbols == SDB_DEBUG) 1347: { 1348: ASM_OUTPUT_SOURCE_FILENAME (file, 1349: DECL_SOURCE_FILE (current_function_decl)); 1350: if (debug_info_level != DINFO_LEVEL_TERSE) 1.1.1.3 root 1351: ASM_OUTPUT_SOURCE_LINE (file, 1352: DECL_SOURCE_LINE (current_function_decl)); 1.1.1.2 root 1353: } 1354: 1355: /* The assembly language programmer's guide states that the second argument 1356: to the .ent directive, the lex_level, is ignored by the assembler, 1357: so we might as well omit it. */ 1358: 1359: fprintf (file, "\t.ent "); 1360: assemble_name (file, alpha_function_name); 1361: fprintf (file, "\n"); 1362: ASM_OUTPUT_LABEL (file, alpha_function_name); 1363: inside_function = TRUE; 1364: 1365: /* Set up offsets to alpha virtual arg/local debugging pointer. */ 1366: 1367: alpha_auto_offset = -frame_size + current_function_pretend_args_size; 1368: alpha_arg_offset = -frame_size + 48; 1369: 1.1 root 1370: /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. 1371: Even if we are a static function, we still need to do this in case 1.1.1.4 ! root 1372: our address is taken and passed to something like qsort. ! 1373: ! 1374: We never need a GP for Windows/NT. */ 1.1 root 1375: 1376: alpha_function_needs_gp = 0; 1377: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 1378: if ((GET_CODE (insn) == CALL_INSN) 1379: || (GET_RTX_CLASS (GET_CODE (insn)) == 'i' 1380: && GET_CODE (PATTERN (insn)) != USE 1381: && GET_CODE (PATTERN (insn)) != CLOBBER 1.1.1.2 root 1382: && (get_attr_type (insn) == TYPE_LDSYM 1383: || get_attr_type (insn) == TYPE_ISUBR))) 1.1 root 1384: { 1385: alpha_function_needs_gp = 1; 1386: break; 1387: } 1388: 1.1.1.4 ! root 1389: if (WINDOWS_NT == 0) ! 1390: { ! 1391: if (alpha_function_needs_gp) ! 1392: fprintf (file, "\tldgp $29,0($27)\n"); 1.1 root 1393: 1.1.1.4 ! root 1394: /* Put a label after the GP load so we can enter the function at it. */ ! 1395: assemble_name (file, alpha_function_name); ! 1396: fprintf (file, "..ng:\n"); ! 1397: } 1.1 root 1398: 1399: /* Adjust the stack by the frame size. If the frame size is > 4096 1400: bytes, we need to be sure we probe somewhere in the first and last 1401: 4096 bytes (we can probably get away without the latter test) and 1402: every 8192 bytes in between. If the frame size is > 32768, we 1403: do this in a loop. Otherwise, we generate the explicit probe 1404: instructions. 1405: 1406: Note that we are only allowed to adjust sp once in the prologue. */ 1407: 1408: if (frame_size < 32768) 1409: { 1410: if (frame_size > 4096) 1411: { 1412: int probed = 4096; 1413: 1.1.1.4 ! root 1414: fprintf (file, "\tstq $31,-%d($30)\n", probed); 1.1 root 1415: 1416: while (probed + 8192 < frame_size) 1.1.1.4 ! root 1417: fprintf (file, "\tstq $31,-%d($30)\n", probed += 8192); 1.1 root 1418: 1.1.1.3 root 1419: /* We only have to do this probe if we aren't saving registers. */ 1420: if (sa_size == 0 && probed + 4096 < frame_size) 1.1.1.4 ! root 1421: fprintf (file, "\tstq $31,-%d($30)\n", frame_size); 1.1 root 1422: } 1423: 1424: if (frame_size != 0) 1425: fprintf (file, "\tlda $30,-%d($30)\n", frame_size); 1426: } 1427: else 1428: { 1429: /* Here we generate code to set R4 to SP + 4096 and set R5 to the 1430: number of 8192 byte blocks to probe. We then probe each block 1431: in the loop and then set SP to the proper location. If the 1.1.1.3 root 1432: amount remaining is > 4096, we have to do one more probe if we 1433: are not saving any registers. */ 1.1 root 1434: 1435: HOST_WIDE_INT blocks = (frame_size + 4096) / 8192; 1436: HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192; 1437: 1.1.1.3 root 1438: add_long_const (file, blocks, 31, 5, 5); 1.1 root 1439: 1.1.1.2 root 1440: fprintf (file, "\tlda $4,4096($30)\n"); 1.1 root 1441: 1.1.1.2 root 1442: assemble_name (file, alpha_function_name); 1443: fprintf (file, "..sc:\n"); 1.1 root 1444: 1.1.1.4 ! root 1445: fprintf (file, "\tstq $31,-8192($4)\n"); 1.1 root 1446: fprintf (file, "\tsubq $5,1,$5\n"); 1447: fprintf (file, "\tlda $4,-8192($4)\n"); 1.1.1.2 root 1448: 1.1.1.3 root 1449: fprintf (file, "\tbne $5,"); 1.1.1.2 root 1450: assemble_name (file, alpha_function_name); 1.1.1.3 root 1451: fprintf (file, "..sc\n"); 1.1.1.2 root 1452: 1.1.1.3 root 1453: if (leftover > 4096 && sa_size == 0) 1.1.1.4 ! root 1454: fprintf (file, "\tstq $31,-%d($4)\n", leftover); ! 1455: ! 1456: fprintf (file, "\tlda $30,-%d($4)\n", leftover); 1.1 root 1457: } 1458: 1459: /* Describe our frame. */ 1460: fprintf (file, "\t.frame $%d,%d,$26,%d\n", 1.1.1.3 root 1461: (frame_pointer_needed 1462: ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM), 1.1 root 1463: frame_size, current_function_pretend_args_size); 1464: 1.1.1.3 root 1465: /* Save register 26 if any other register needs to be saved. */ 1466: if (sa_size != 0) 1.1 root 1467: { 1468: reg_mask |= 1 << 26; 1.1.1.3 root 1469: fprintf (file, "\tstq $26,%d($30)\n", reg_offset); 1.1 root 1470: reg_offset += 8; 1.1.1.3 root 1471: int_reg_save_area_size += 8; 1.1 root 1472: } 1473: 1474: /* Now save any other used integer registers required to be saved. */ 1475: for (i = 0; i < 32; i++) 1476: if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26) 1477: { 1478: reg_mask |= 1 << i; 1.1.1.3 root 1479: fprintf (file, "\tstq $%d,%d($30)\n", i, reg_offset); 1.1 root 1480: reg_offset += 8; 1.1.1.3 root 1481: int_reg_save_area_size += 8; 1.1 root 1482: } 1483: 1484: /* Print the register mask and do floating-point saves. */ 1485: if (reg_mask) 1486: fprintf (file, "\t.mask 0x%x,%d\n", reg_mask, 1.1.1.2 root 1487: actual_start_reg_offset - frame_size); 1.1 root 1488: 1489: start_reg_offset = reg_offset; 1490: reg_mask = 0; 1491: 1492: for (i = 0; i < 32; i++) 1493: if (! fixed_regs[i + 32] && ! call_used_regs[i + 32] 1494: && regs_ever_live[i + 32]) 1495: { 1496: reg_mask |= 1 << i; 1.1.1.3 root 1497: fprintf (file, "\tstt $f%d,%d($30)\n", i, reg_offset); 1.1 root 1498: reg_offset += 8; 1499: } 1500: 1501: /* Print the floating-point mask, if we've saved any fp register. */ 1502: if (reg_mask) 1.1.1.3 root 1503: fprintf (file, "\t.fmask 0x%x,%d\n", reg_mask, 1504: actual_start_reg_offset - frame_size + int_reg_save_area_size); 1.1 root 1505: 1506: /* If we need a frame pointer, set it from the stack pointer. Note that 1507: this must always be the last instruction in the prologue. */ 1508: if (frame_pointer_needed) 1509: fprintf (file, "\tbis $30,$30,$15\n"); 1510: 1511: /* End the prologue and say if we used gp. */ 1512: fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp); 1513: } 1514: 1515: /* Write function epilogue. */ 1516: 1517: void 1518: output_epilog (file, size) 1519: FILE *file; 1520: int size; 1521: { 1522: rtx insn = get_last_insn (); 1.1.1.3 root 1523: HOST_WIDE_INT out_args_size 1524: = ALPHA_ROUND (current_function_outgoing_args_size); 1525: HOST_WIDE_INT sa_size = alpha_sa_size (); 1526: HOST_WIDE_INT frame_size 1527: = (out_args_size + sa_size 1528: + ALPHA_ROUND (size + current_function_pretend_args_size)); 1529: HOST_WIDE_INT reg_offset = out_args_size; 1.1.1.2 root 1530: HOST_WIDE_INT frame_size_from_reg_save = frame_size - reg_offset; 1.1.1.3 root 1531: int restore_fp 1532: = frame_pointer_needed && regs_ever_live[HARD_FRAME_POINTER_REGNUM]; 1.1 root 1533: int i; 1534: 1535: /* If the last insn was a BARRIER, we don't have to write anything except 1536: the .end pseudo-op. */ 1537: if (GET_CODE (insn) == NOTE) 1538: insn = prev_nonnote_insn (insn); 1539: if (insn == 0 || GET_CODE (insn) != BARRIER) 1540: { 1.1.1.4 ! root 1541: int fp_offset = 0; 1.1 root 1542: 1543: /* If we have a frame pointer, restore SP from it. */ 1544: if (frame_pointer_needed) 1545: fprintf (file, "\tbis $15,$15,$30\n"); 1546: 1547: /* Restore all the registers, starting with the return address 1548: register. */ 1.1.1.3 root 1549: if (sa_size != 0) 1.1 root 1550: { 1.1.1.3 root 1551: fprintf (file, "\tldq $26,%d($30)\n", reg_offset); 1.1 root 1552: reg_offset += 8; 1553: } 1554: 1555: /* Now restore any other used integer registers that that we saved, 1556: except for FP if it is being used as FP, since it must be 1557: restored last. */ 1558: 1559: for (i = 0; i < 32; i++) 1560: if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] 1561: && i != 26) 1562: { 1.1.1.3 root 1563: if (i == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) 1.1 root 1564: fp_offset = reg_offset; 1565: else 1.1.1.3 root 1566: fprintf (file, "\tldq $%d,%d($30)\n", i, reg_offset); 1.1 root 1567: reg_offset += 8; 1568: } 1569: 1570: for (i = 0; i < 32; i++) 1571: if (! fixed_regs[i + 32] && ! call_used_regs[i + 32] 1572: && regs_ever_live[i + 32]) 1573: { 1.1.1.3 root 1574: fprintf (file, "\tldt $f%d,%d($30)\n", i, reg_offset); 1.1 root 1575: reg_offset += 8; 1576: } 1577: 1.1.1.3 root 1578: /* If the stack size is large and we have a frame pointer, compute the 1579: size of the stack into a register because the old FP restore, stack 1580: pointer adjust, and return are required to be consecutive 1581: instructions. */ 1582: if (frame_size > 32767 && restore_fp) 1583: add_long_const (file, frame_size, 31, 1, 1); 1.1 root 1584: 1585: /* If we needed a frame pointer and we have to restore it, do it 1.1.1.2 root 1586: now. This must be done in one instruction immediately 1587: before the SP update. */ 1.1.1.4 ! root 1588: if (restore_fp && fp_offset) 1.1.1.3 root 1589: fprintf (file, "\tldq $15,%d($30)\n", fp_offset); 1.1 root 1590: 1.1.1.3 root 1591: /* Now update the stack pointer, if needed. Only one instruction must 1592: modify the stack pointer. It must be the last instruction in the 1593: sequence and must be an ADDQ or LDA instruction. If the frame 1594: pointer was loaded above, we may only put one instruction here. */ 1595: 1596: if (frame_size > 32768 && restore_fp) 1597: fprintf (file, "\taddq $1,$30,$30\n"); 1598: else 1599: add_long_const (file, frame_size, 30, 30, 1); 1.1 root 1600: 1601: /* Finally return to the caller. */ 1602: fprintf (file, "\tret $31,($26),1\n"); 1603: } 1604: 1605: /* End the function. */ 1.1.1.2 root 1606: fprintf (file, "\t.end "); 1607: assemble_name (file, alpha_function_name); 1608: fprintf (file, "\n"); 1609: inside_function = FALSE; 1.1.1.4 ! root 1610: ! 1611: /* Show that we know this function if it is called again. */ ! 1612: SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1; 1.1 root 1613: } 1.1.1.2 root 1614: 1615: /* Debugging support. */ 1616: 1617: #include "gstab.h" 1618: 1619: /* Count the number of sdb related labels are generated (to find block 1620: start and end boundaries). */ 1621: 1622: int sdb_label_count = 0; 1623: 1624: /* Next label # for each statement. */ 1625: 1626: static int sym_lineno = 0; 1627: 1628: /* Count the number of .file directives, so that .loc is up to date. */ 1629: 1630: static int num_source_filenames = 0; 1631: 1632: /* Name of the file containing the current function. */ 1633: 1634: static char *current_function_file = ""; 1635: 1636: /* Offsets to alpha virtual arg/local debugging pointers. */ 1637: 1638: long alpha_arg_offset; 1639: long alpha_auto_offset; 1640: 1641: /* Emit a new filename to a stream. */ 1642: 1643: void 1644: alpha_output_filename (stream, name) 1645: FILE *stream; 1646: char *name; 1647: { 1648: static int first_time = TRUE; 1649: char ltext_label_name[100]; 1650: 1651: if (first_time) 1652: { 1653: first_time = FALSE; 1654: ++num_source_filenames; 1655: current_function_file = name; 1656: fprintf (stream, "\t.file\t%d ", num_source_filenames); 1657: output_quoted_string (stream, name); 1658: fprintf (stream, "\n"); 1659: if (!TARGET_GAS && write_symbols == DBX_DEBUG) 1660: fprintf (stream, "\t#@stabs\n"); 1661: } 1662: 1663: else if (!TARGET_GAS && write_symbols == DBX_DEBUG) 1664: { 1665: ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0); 1666: fprintf (stream, "%s ", ASM_STABS_OP); 1667: output_quoted_string (stream, name); 1668: fprintf (stream, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]); 1669: } 1670: 1671: else if (name != current_function_file 1672: && strcmp (name, current_function_file) != 0) 1673: { 1674: if (inside_function && ! TARGET_GAS) 1675: fprintf (stream, "\t#.file\t%d ", num_source_filenames); 1676: else 1677: { 1678: ++num_source_filenames; 1679: current_function_file = name; 1680: fprintf (stream, "\t.file\t%d ", num_source_filenames); 1681: } 1682: 1683: output_quoted_string (stream, name); 1684: fprintf (stream, "\n"); 1685: } 1686: } 1687: 1688: /* Emit a linenumber to a stream. */ 1689: 1690: void 1691: alpha_output_lineno (stream, line) 1692: FILE *stream; 1693: int line; 1694: { 1695: if (! TARGET_GAS && write_symbols == DBX_DEBUG) 1696: { 1697: /* mips-tfile doesn't understand .stabd directives. */ 1698: ++sym_lineno; 1699: fprintf (stream, "$LM%d:\n\t%s %d,0,%d,$LM%d\n", 1700: sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno); 1701: } 1702: else 1703: fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line); 1704: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.