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