|
|
1.1 root 1: /* Subroutines for insn-output.c for HPPA. 1.1.1.4 ! root 2: Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 1.1 root 3: Contributed by Tim Moore ([email protected]), based on sparc.c 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: #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 "tree.h" 35: #include "c-tree.h" 36: #include "expr.h" 37: #include "obstack.h" 38: 39: /* Save the operands last given to a compare for use when we 40: generate a scc or bcc insn. */ 41: 42: rtx hppa_compare_op0, hppa_compare_op1; 43: enum cmp_type hppa_branch_type; 44: 1.1.1.4 ! root 45: /* Which cpu we are scheduling for. */ ! 46: enum processor_type pa_cpu; ! 47: ! 48: /* String to hold which cpu we are scheduling for. */ ! 49: char *pa_cpu_string; 1.1 root 50: 51: /* Set by the FUNCTION_PROFILER macro. */ 52: int hp_profile_labelno; 53: 1.1.1.2 root 54: /* Counts for the number of callee-saved general and floating point 55: registers which were saved by the current function's prologue. */ 56: static int gr_saved, fr_saved; 57: 1.1 root 58: static rtx find_addr_reg (); 59: 1.1.1.4 ! root 60: /* Keep track of the number of bytes we have output in the CODE subspaces ! 61: during this compilation so we'll know when to emit inline long-calls. */ ! 62: ! 63: unsigned int total_code_bytes; ! 64: ! 65: /* Variables to handle plabels that we discover are necessary at assembly ! 66: output time. They are output after the current function. */ ! 67: ! 68: struct defer_plab ! 69: { ! 70: rtx internal_label; ! 71: rtx symbol; ! 72: } *deferred_plabels = 0; ! 73: int n_deferred_plabels = 0; ! 74: ! 75: void ! 76: override_options () ! 77: { ! 78: /* Default to 700 scheduling which is reasonable for older 800 processors ! 79: correct for the 700s, and not too bad for the 7100s and 7100LCs. */ ! 80: if (pa_cpu_string == NULL ! 81: || ! strcmp (pa_cpu_string, "700")) ! 82: { ! 83: pa_cpu_string = "700"; ! 84: pa_cpu = PROCESSOR_700; ! 85: } ! 86: else if (! strcmp (pa_cpu_string, "7100")) ! 87: { ! 88: pa_cpu_string = "7100"; ! 89: pa_cpu = PROCESSOR_7100; ! 90: } ! 91: else if (! strcmp (pa_cpu_string, "7100LC")) ! 92: { ! 93: pa_cpu_string = "7100LC"; ! 94: pa_cpu = PROCESSOR_7100LC; ! 95: } ! 96: else ! 97: { ! 98: warning ("Unknown -mschedule= option (%s).\nValid options are 700, 7100 and 7100LC\n", pa_cpu_string); ! 99: } ! 100: } ! 101: ! 102: 1.1 root 103: /* Return non-zero only if OP is a register of mode MODE, 104: or CONST0_RTX. */ 105: int 106: reg_or_0_operand (op, mode) 107: rtx op; 108: enum machine_mode mode; 109: { 110: return (op == CONST0_RTX (mode) || register_operand (op, mode)); 111: } 112: 1.1.1.2 root 113: /* Return non-zero if OP is suitable for use in a call to a named 114: function. 115: 1.1.1.3 root 116: (???) For 2.5 try to eliminate either call_operand_address or 1.1.1.2 root 117: function_label_operand, they perform very similar functions. */ 1.1 root 118: int 119: call_operand_address (op, mode) 120: rtx op; 121: enum machine_mode mode; 122: { 1.1.1.4 ! root 123: return (CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME); 1.1 root 124: } 125: 1.1.1.3 root 126: /* Return 1 if X contains a symbolic expression. We know these 127: expressions will have one of a few well defined forms, so 1.1 root 128: we need only check those forms. */ 129: int 130: symbolic_expression_p (x) 131: register rtx x; 132: { 133: 1.1.1.3 root 134: /* Strip off any HIGH. */ 1.1 root 135: if (GET_CODE (x) == HIGH) 136: x = XEXP (x, 0); 137: 138: return (symbolic_operand (x, VOIDmode)); 139: } 140: 141: int 142: symbolic_operand (op, mode) 143: register rtx op; 144: enum machine_mode mode; 145: { 146: switch (GET_CODE (op)) 147: { 148: case SYMBOL_REF: 149: case LABEL_REF: 150: return 1; 151: case CONST: 152: op = XEXP (op, 0); 153: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 154: || GET_CODE (XEXP (op, 0)) == LABEL_REF) 155: && GET_CODE (XEXP (op, 1)) == CONST_INT); 156: default: 157: return 0; 158: } 159: } 160: 161: /* Return truth value of statement that OP is a symbolic memory 162: operand of mode MODE. */ 163: 164: int 165: symbolic_memory_operand (op, mode) 166: rtx op; 167: enum machine_mode mode; 168: { 169: if (GET_CODE (op) == SUBREG) 170: op = SUBREG_REG (op); 171: if (GET_CODE (op) != MEM) 172: return 0; 173: op = XEXP (op, 0); 174: return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST 175: || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); 176: } 177: 178: /* Return 1 if the operand is either a register or a memory operand that is 179: not symbolic. */ 180: 181: int 182: reg_or_nonsymb_mem_operand (op, mode) 183: register rtx op; 184: enum machine_mode mode; 185: { 186: if (register_operand (op, mode)) 187: return 1; 188: 189: if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode)) 190: return 1; 191: 192: return 0; 193: } 194: 1.1.1.3 root 195: /* Return 1 if the operand is either a register, zero, or a memory operand 1.1 root 196: that is not symbolic. */ 197: 198: int 199: reg_or_0_or_nonsymb_mem_operand (op, mode) 200: register rtx op; 201: enum machine_mode mode; 202: { 203: if (register_operand (op, mode)) 204: return 1; 205: 206: if (op == CONST0_RTX (mode)) 207: return 1; 208: 209: if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode)) 210: return 1; 211: 212: return 0; 213: } 214: 1.1.1.3 root 215: /* Accept any constant that can be moved in one instructions into a 1.1 root 216: general register. */ 1.1.1.3 root 217: int 1.1 root 218: cint_ok_for_move (intval) 1.1.1.3 root 219: HOST_WIDE_INT intval; 1.1 root 220: { 221: /* OK if ldo, ldil, or zdepi, can be used. */ 222: return (VAL_14_BITS_P (intval) || (intval & 0x7ff) == 0 223: || zdepi_cint_p (intval)); 224: } 225: 226: /* Accept anything that can be moved in one instruction into a general 227: register. */ 228: int 229: move_operand (op, mode) 230: rtx op; 231: enum machine_mode mode; 232: { 233: if (register_operand (op, mode)) 234: return 1; 235: 236: if (GET_CODE (op) == CONST_INT) 237: return cint_ok_for_move (INTVAL (op)); 238: 239: if (GET_MODE (op) != mode) 240: return 0; 241: if (GET_CODE (op) == SUBREG) 242: op = SUBREG_REG (op); 243: if (GET_CODE (op) != MEM) 244: return 0; 245: 246: op = XEXP (op, 0); 247: if (GET_CODE (op) == LO_SUM) 248: return (register_operand (XEXP (op, 0), Pmode) 249: && CONSTANT_P (XEXP (op, 1))); 250: return memory_address_p (mode, op); 251: } 252: 253: /* Accept REG and any CONST_INT that can be moved in one instruction into a 254: general register. */ 255: int 256: reg_or_cint_move_operand (op, mode) 257: rtx op; 258: enum machine_mode mode; 259: { 260: if (register_operand (op, mode)) 261: return 1; 262: 263: if (GET_CODE (op) == CONST_INT) 264: return cint_ok_for_move (INTVAL (op)); 265: 266: return 0; 267: } 268: 269: int 1.1.1.4 ! root 270: pic_label_operand (op, mode) 1.1 root 271: rtx op; 272: enum machine_mode mode; 273: { 1.1.1.4 ! root 274: if (!flag_pic) ! 275: return 0; ! 276: ! 277: switch (GET_CODE (op)) ! 278: { ! 279: case LABEL_REF: ! 280: return 1; ! 281: case CONST: ! 282: op = XEXP (op, 0); ! 283: return (GET_CODE (XEXP (op, 0)) == LABEL_REF ! 284: && GET_CODE (XEXP (op, 1)) == CONST_INT); ! 285: default: ! 286: return 0; ! 287: } 1.1 root 288: } 289: 290: int 291: fp_reg_operand (op, mode) 292: rtx op; 293: enum machine_mode mode; 294: { 295: return reg_renumber && FP_REG_P (op); 296: } 297: 298: 299: 300: /* Return truth value of whether OP can be used as an operand in a 301: three operand arithmetic insn that accepts registers of mode MODE 302: or 14-bit signed integers. */ 303: int 304: arith_operand (op, mode) 305: rtx op; 306: enum machine_mode mode; 307: { 308: return (register_operand (op, mode) 309: || (GET_CODE (op) == CONST_INT && INT_14_BITS (op))); 310: } 311: 312: /* Return truth value of whether OP can be used as an operand in a 313: three operand arithmetic insn that accepts registers of mode MODE 314: or 11-bit signed integers. */ 315: int 316: arith11_operand (op, mode) 317: rtx op; 318: enum machine_mode mode; 319: { 320: return (register_operand (op, mode) 321: || (GET_CODE (op) == CONST_INT && INT_11_BITS (op))); 322: } 323: 1.1.1.3 root 324: /* A constant integer suitable for use in a PRE_MODIFY memory 1.1 root 325: reference. */ 326: int 327: pre_cint_operand (op, mode) 328: rtx op; 329: enum machine_mode mode; 330: { 331: return (GET_CODE (op) == CONST_INT 332: && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10); 333: } 334: 1.1.1.3 root 335: /* A constant integer suitable for use in a POST_MODIFY memory 1.1 root 336: reference. */ 337: int 338: post_cint_operand (op, mode) 339: rtx op; 340: enum machine_mode mode; 341: { 342: return (GET_CODE (op) == CONST_INT 343: && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10); 344: } 345: 346: int 347: arith_double_operand (op, mode) 348: rtx op; 349: enum machine_mode mode; 350: { 351: return (register_operand (op, mode) 352: || (GET_CODE (op) == CONST_DOUBLE 353: && GET_MODE (op) == mode 354: && VAL_14_BITS_P (CONST_DOUBLE_LOW (op)) 355: && (CONST_DOUBLE_HIGH (op) >= 0 356: == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0)))); 357: } 358: 359: /* Return truth value of whether OP is a integer which fits the 360: range constraining immediate operands in three-address insns. */ 361: 362: int 363: int5_operand (op, mode) 364: rtx op; 365: enum machine_mode mode; 366: { 367: return (GET_CODE (op) == CONST_INT && INT_5_BITS (op)); 368: } 369: 370: int 371: uint5_operand (op, mode) 372: rtx op; 373: enum machine_mode mode; 374: { 375: return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op)); 376: } 377: 378: int 379: int11_operand (op, mode) 380: rtx op; 381: enum machine_mode mode; 382: { 1.1.1.3 root 383: return (GET_CODE (op) == CONST_INT && INT_11_BITS (op)); 384: } 385: 386: int 387: uint32_operand (op, mode) 388: rtx op; 389: enum machine_mode mode; 390: { 391: #if HOST_BITS_PER_WIDE_INT > 32 392: /* All allowed constants will fit a CONST_INT. */ 393: return (GET_CODE (op) == CONST_INT 394: && (INTVAL (op) >= 0 && INTVAL (op) < 0x100000000L)); 395: #else 396: return (GET_CODE (op) == CONST_INT 397: || (GET_CODE (op) == CONST_DOUBLE 398: && CONST_DOUBLE_HIGH (op) == 0)); 399: #endif 1.1 root 400: } 401: 402: int 403: arith5_operand (op, mode) 404: rtx op; 405: enum machine_mode mode; 406: { 407: return register_operand (op, mode) || int5_operand (op, mode); 408: } 409: 410: /* True iff zdepi can be used to generate this CONST_INT. */ 411: int 412: zdepi_cint_p (x) 1.1.1.3 root 413: unsigned HOST_WIDE_INT x; 1.1 root 414: { 1.1.1.4 ! root 415: unsigned HOST_WIDE_INT lsb_mask, t; 1.1 root 416: 417: /* This might not be obvious, but it's at least fast. 1.1.1.4 ! root 418: This function is critical; we don't have the time loops would take. */ 1.1 root 419: lsb_mask = x & -x; 420: t = ((x >> 4) + lsb_mask) & ~(lsb_mask - 1); 421: /* Return true iff t is a power of two. */ 422: return ((t & (t - 1)) == 0); 423: } 424: 1.1.1.3 root 425: /* True iff depi or extru can be used to compute (reg & mask). 426: Accept bit pattern like these: 427: 0....01....1 428: 1....10....0 429: 1..10..01..1 */ 1.1 root 430: int 431: and_mask_p (mask) 1.1.1.3 root 432: unsigned HOST_WIDE_INT mask; 1.1 root 433: { 434: mask = ~mask; 435: mask += mask & -mask; 436: return (mask & (mask - 1)) == 0; 437: } 438: 439: /* True iff depi or extru can be used to compute (reg & OP). */ 440: int 441: and_operand (op, mode) 442: rtx op; 443: enum machine_mode mode; 444: { 445: return (register_operand (op, mode) 446: || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op)))); 447: } 448: 449: /* True iff depi can be used to compute (reg | MASK). */ 450: int 451: ior_mask_p (mask) 1.1.1.3 root 452: unsigned HOST_WIDE_INT mask; 1.1 root 453: { 454: mask += mask & -mask; 455: return (mask & (mask - 1)) == 0; 456: } 457: 458: /* True iff depi can be used to compute (reg | OP). */ 459: int 460: ior_operand (op, mode) 461: rtx op; 462: enum machine_mode mode; 463: { 464: return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))); 465: } 466: 467: int 468: lhs_lshift_operand (op, mode) 469: rtx op; 470: enum machine_mode mode; 471: { 472: return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode); 473: } 474: 475: /* True iff OP is a CONST_INT of the forms 0...0xxxx or 0...01...1xxxx. 476: Such values can be the left hand side x in (x << r), using the zvdepi 477: instruction. */ 478: int 479: lhs_lshift_cint_operand (op, mode) 480: rtx op; 481: enum machine_mode mode; 482: { 1.1.1.4 ! root 483: unsigned HOST_WIDE_INT x; 1.1 root 484: if (GET_CODE (op) != CONST_INT) 485: return 0; 486: x = INTVAL (op) >> 4; 487: return (x & (x + 1)) == 0; 488: } 489: 490: int 491: arith32_operand (op, mode) 492: rtx op; 493: enum machine_mode mode; 494: { 495: return register_operand (op, mode) || GET_CODE (op) == CONST_INT; 496: } 497: 498: int 499: pc_or_label_operand (op, mode) 500: rtx op; 501: enum machine_mode mode; 502: { 503: return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF); 504: } 505: 506: /* Legitimize PIC addresses. If the address is already 507: position-independent, we return ORIG. Newly generated 508: position-independent addresses go to REG. If we need more 509: than one register, we lose. */ 510: 511: rtx 512: legitimize_pic_address (orig, mode, reg) 513: rtx orig, reg; 514: enum machine_mode mode; 515: { 516: rtx pic_ref = orig; 517: 1.1.1.4 ! root 518: /* Labels need special handling. */ ! 519: if (pic_label_operand (orig)) ! 520: { ! 521: emit_insn (gen_pic_load_label (reg, orig)); ! 522: current_function_uses_pic_offset_table = 1; ! 523: return reg; ! 524: } 1.1 root 525: if (GET_CODE (orig) == SYMBOL_REF) 526: { 527: if (reg == 0) 528: abort (); 529: 530: if (flag_pic == 2) 531: { 1.1.1.4 ! root 532: emit_insn (gen_pic2_highpart (reg, pic_offset_table_rtx, orig)); ! 533: pic_ref = gen_rtx (MEM, Pmode, ! 534: gen_rtx (LO_SUM, Pmode, reg, ! 535: gen_rtx (UNSPEC, SImode, gen_rtvec (1, orig), 0))); ! 536: } ! 537: else ! 538: pic_ref = gen_rtx (MEM, Pmode, ! 539: gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig)); 1.1 root 540: current_function_uses_pic_offset_table = 1; 541: RTX_UNCHANGING_P (pic_ref) = 1; 542: emit_move_insn (reg, pic_ref); 543: return reg; 544: } 545: else if (GET_CODE (orig) == CONST) 546: { 1.1.1.2 root 547: rtx base; 1.1 root 548: 549: if (GET_CODE (XEXP (orig, 0)) == PLUS 550: && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) 551: return orig; 552: 553: if (reg == 0) 554: abort (); 555: 556: if (GET_CODE (XEXP (orig, 0)) == PLUS) 557: { 558: base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); 559: orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, 560: base == reg ? 0 : reg); 561: } 562: else abort (); 563: if (GET_CODE (orig) == CONST_INT) 564: { 565: if (INT_14_BITS (orig)) 566: return plus_constant_for_output (base, INTVAL (orig)); 567: orig = force_reg (Pmode, orig); 568: } 569: pic_ref = gen_rtx (PLUS, Pmode, base, orig); 570: /* Likewise, should we set special REG_NOTEs here? */ 571: } 572: return pic_ref; 573: } 574: 575: /* Try machine-dependent ways of modifying an illegitimate address 576: to be legitimate. If we find one, return the new, valid address. 577: This macro is used in only one place: `memory_address' in explow.c. 578: 579: OLDX is the address as it was before break_out_memory_refs was called. 580: In some cases it is useful to look at this to decide what needs to be done. 581: 582: MODE and WIN are passed so that this macro can use 583: GO_IF_LEGITIMATE_ADDRESS. 584: 585: It is always safe for this macro to do nothing. It exists to recognize 1.1.1.3 root 586: opportunities to optimize the output. 1.1 root 587: 588: For the PA, transform: 589: 590: memory(X + <large int>) 591: 592: into: 593: 594: if (<large int> & mask) >= 16 595: Y = (<large int> & ~mask) + mask + 1 Round up. 596: else 597: Y = (<large int> & ~mask) Round down. 598: Z = X + Y 599: memory (Z + (<large int> - Y)); 600: 1.1.1.3 root 601: This is for CSE to find several similar references, and only use one Z. 1.1 root 602: 603: X can either be a SYMBOL_REF or REG, but because combine can not 604: perform a 4->2 combination we do nothing for SYMBOL_REF + D where 605: D will not fit in 14 bits. 606: 607: MODE_FLOAT references allow displacements which fit in 5 bits, so use 1.1.1.3 root 608: 0x1f as the mask. 1.1 root 609: 610: MODE_INT references allow displacements which fit in 14 bits, so use 1.1.1.3 root 611: 0x3fff as the mask. 1.1 root 612: 613: This relies on the fact that most mode MODE_FLOAT references will use FP 614: registers and most mode MODE_INT references will use integer registers. 615: (In the rare case of an FP register used in an integer MODE, we depend 616: on secondary reloads to clean things up.) 617: 618: 619: It is also beneficial to handle (plus (mult (X) (Y)) (Z)) in a special 620: manner if Y is 2, 4, or 8. (allows more shadd insns and shifted indexed 1.1.1.4 ! root 621: addressing modes to be used). 1.1 root 622: 623: Put X and Z into registers. Then put the entire expression into 624: a register. */ 625: 626: rtx 627: hppa_legitimize_address (x, oldx, mode) 628: rtx x, oldx; 629: enum machine_mode mode; 630: { 631: rtx orig = x; 632: 1.1.1.4 ! root 633: if (flag_pic) ! 634: return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode)); ! 635: 1.1 root 636: /* Strip off CONST. */ 637: if (GET_CODE (x) == CONST) 638: x = XEXP (x, 0); 639: 1.1.1.3 root 640: /* Note we must reject symbols which represent function addresses 641: since the assembler/linker can't handle arithmetic on plabels. */ 1.1 root 642: if (GET_CODE (x) == PLUS 643: && GET_CODE (XEXP (x, 1)) == CONST_INT 1.1.1.3 root 644: && ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF 645: && !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0))) 1.1 root 646: || GET_CODE (XEXP (x, 0)) == REG)) 647: { 648: rtx int_part, ptr_reg; 649: int newoffset; 650: int offset = INTVAL (XEXP (x, 1)); 651: int mask = GET_MODE_CLASS (mode) == MODE_FLOAT ? 0x1f : 0x3fff; 652: 1.1.1.3 root 653: /* Choose which way to round the offset. Round up if we 1.1 root 654: are >= halfway to the next boundary. */ 655: if ((offset & mask) >= ((mask + 1) / 2)) 656: newoffset = (offset & ~ mask) + mask + 1; 657: else 658: newoffset = (offset & ~ mask); 659: 660: /* If the newoffset will not fit in 14 bits (ldo), then 661: handling this would take 4 or 5 instructions (2 to load 662: the SYMBOL_REF + 1 or 2 to load the newoffset + 1 to 663: add the new offset and the SYMBOL_REF.) Combine can 664: not handle 4->2 or 5->2 combinations, so do not create 665: them. */ 666: if (! VAL_14_BITS_P (newoffset) 667: && GET_CODE (XEXP (x, 0)) == SYMBOL_REF) 668: { 669: rtx const_part = gen_rtx (CONST, VOIDmode, 670: gen_rtx (PLUS, Pmode, 671: XEXP (x, 0), 672: GEN_INT (newoffset))); 673: rtx tmp_reg 674: = force_reg (Pmode, 675: gen_rtx (HIGH, Pmode, const_part)); 676: ptr_reg 677: = force_reg (Pmode, 678: gen_rtx (LO_SUM, Pmode, 679: tmp_reg, const_part)); 680: } 681: else 682: { 683: if (! VAL_14_BITS_P (newoffset)) 684: int_part = force_reg (Pmode, GEN_INT (newoffset)); 685: else 686: int_part = GEN_INT (newoffset); 687: 688: ptr_reg = force_reg (Pmode, 689: gen_rtx (PLUS, Pmode, 690: force_reg (Pmode, XEXP (x, 0)), 691: int_part)); 692: } 693: return plus_constant (ptr_reg, offset - newoffset); 694: } 1.1.1.2 root 695: 696: /* Try to arrange things so that indexing modes can be used, but 1.1.1.3 root 697: only do so if indexing is safe. 1.1.1.2 root 698: 699: Indexing is safe when the second operand for the outer PLUS 1.1.1.3 root 700: is a REG, SUBREG, SYMBOL_REF or the like. 1.1.1.2 root 701: 1.1.1.3 root 702: For 2.5, indexing is also safe for (plus (symbol_ref) (const_int)) 1.1.1.2 root 703: if the integer is > 0. */ 1.1 root 704: if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT 705: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT 1.1.1.2 root 706: && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))) 707: && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o' 708: || GET_CODE (XEXP (x, 1)) == SUBREG) 709: && GET_CODE (XEXP (x, 1)) != CONST) 1.1 root 710: { 711: int val = INTVAL (XEXP (XEXP (x, 0), 1)); 712: rtx reg1, reg2; 713: reg1 = force_reg (Pmode, force_operand (XEXP (x, 1), 0)); 714: reg2 = force_reg (Pmode, 715: force_operand (XEXP (XEXP (x, 0), 0), 0)); 716: return force_reg (Pmode, 717: gen_rtx (PLUS, Pmode, 718: gen_rtx (MULT, Pmode, reg2, 719: GEN_INT (val)), 720: reg1)); 721: } 1.1.1.2 root 722: 1.1.1.3 root 723: /* Uh-oh. We might have an address for x[n-100000]. This needs 1.1.1.2 root 724: special handling. */ 725: 726: if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT 727: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT 728: && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))) 729: { 730: /* Ugly. We modify things here so that the address offset specified 731: by the index expression is computed first, then added to x to form 732: the entire address. 733: 734: For 2.5, it might be profitable to set things up so that we 735: compute the raw (unscaled) index first, then use scaled indexing 736: to access memory, or better yet have the MI parts of the compiler 737: handle this. */ 738: 739: rtx regx1, regy1, regy2, y; 740: 741: /* Strip off any CONST. */ 742: y = XEXP (x, 1); 743: if (GET_CODE (y) == CONST) 744: y = XEXP (y, 0); 745: 746: if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS) 747: { 748: regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0)); 749: regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0)); 750: regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0)); 751: regx1 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode, regx1, regy2)); 752: return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1)); 753: } 754: } 755: 1.1 root 756: return orig; 757: } 758: 759: /* For the HPPA, REG and REG+CONST is cost 0 760: and addresses involving symbolic constants are cost 2. 761: 762: PIC addresses are very expensive. 763: 764: It is no coincidence that this has the same structure 765: as GO_IF_LEGITIMATE_ADDRESS. */ 766: int 767: hppa_address_cost (X) 768: rtx X; 769: { 770: if (GET_CODE (X) == PLUS) 771: return 1; 772: else if (GET_CODE (X) == LO_SUM) 773: return 1; 774: else if (GET_CODE (X) == HIGH) 775: return 2; 776: return 4; 777: } 778: 779: /* Emit insns to move operands[1] into operands[0]. 780: 781: Return 1 if we have written out everything that needs to be done to 782: do the move. Otherwise, return 0 and the caller will emit the move 783: normally. */ 784: 785: int 786: emit_move_sequence (operands, mode, scratch_reg) 787: rtx *operands; 788: enum machine_mode mode; 789: rtx scratch_reg; 790: { 791: register rtx operand0 = operands[0]; 792: register rtx operand1 = operands[1]; 793: 794: /* Handle secondary reloads for loads/stores of FP registers from 1.1.1.3 root 795: REG+D addresses where D does not fit in 5 bits, including 796: (subreg (mem (addr)) cases. */ 1.1 root 797: if (fp_reg_operand (operand0, mode) 1.1.1.3 root 798: && ((GET_CODE (operand1) == MEM 799: && ! memory_address_p (DFmode, XEXP (operand1, 0))) 800: || ((GET_CODE (operand1) == SUBREG 801: && GET_CODE (XEXP (operand1, 0)) == MEM 802: && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0))))) 1.1 root 803: && scratch_reg) 804: { 1.1.1.3 root 805: if (GET_CODE (operand1) == SUBREG) 806: operand1 = XEXP (operand1, 0); 807: 808: scratch_reg = gen_rtx (REG, SImode, REGNO (scratch_reg)); 1.1.1.4 ! root 809: ! 810: /* D might not fit in 14 bits either; for such cases load D into ! 811: scratch reg. */ ! 812: if (!memory_address_p (SImode, XEXP (operand1, 0))) ! 813: { ! 814: emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1)); ! 815: emit_move_insn (scratch_reg, gen_rtx (GET_CODE (XEXP (operand1, 0)), ! 816: SImode, ! 817: XEXP (XEXP (operand1, 0), 0), ! 818: scratch_reg)); ! 819: } ! 820: else ! 821: emit_move_insn (scratch_reg, XEXP (operand1, 0)); 1.1 root 822: emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode, 823: scratch_reg))); 824: return 1; 825: } 826: else if (fp_reg_operand (operand1, mode) 1.1.1.3 root 827: && ((GET_CODE (operand0) == MEM 828: && ! memory_address_p (DFmode, XEXP (operand0, 0))) 829: || ((GET_CODE (operand0) == SUBREG) 830: && GET_CODE (XEXP (operand0, 0)) == MEM 831: && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0)))) 1.1 root 832: && scratch_reg) 833: { 1.1.1.3 root 834: if (GET_CODE (operand0) == SUBREG) 835: operand0 = XEXP (operand0, 0); 836: 837: scratch_reg = gen_rtx (REG, SImode, REGNO (scratch_reg)); 1.1.1.4 ! root 838: /* D might not fit in 14 bits either; for such cases load D into ! 839: scratch reg. */ ! 840: if (!memory_address_p (SImode, XEXP (operand0, 0))) ! 841: { ! 842: emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1)); ! 843: emit_move_insn (scratch_reg, gen_rtx (GET_CODE (XEXP (operand0, 0)), ! 844: SImode, ! 845: XEXP (XEXP (operand0, 0), 0), ! 846: scratch_reg)); ! 847: } ! 848: else ! 849: emit_move_insn (scratch_reg, XEXP (operand0, 0)); 1.1.1.3 root 850: emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg), 1.1 root 851: operand1)); 852: return 1; 853: } 854: /* Handle secondary reloads for loads of FP registers from constant 855: expressions by forcing the constant into memory. 856: 1.1.1.3 root 857: use scratch_reg to hold the address of the memory location. 1.1 root 858: 1.1.1.3 root 859: ??? The proper fix is to change PREFERRED_RELOAD_CLASS to return 860: NO_REGS when presented with a const_int and an register class 1.1 root 861: containing only FP registers. Doing so unfortunately creates 862: more problems than it solves. Fix this for 2.5. */ 863: else if (fp_reg_operand (operand0, mode) 864: && CONSTANT_P (operand1) 865: && scratch_reg) 866: { 867: rtx xoperands[2]; 868: 869: /* Force the constant into memory and put the address of the 870: memory location into scratch_reg. */ 871: xoperands[0] = scratch_reg; 872: xoperands[1] = XEXP (force_const_mem (mode, operand1), 0); 1.1.1.2 root 873: emit_move_sequence (xoperands, Pmode, 0); 1.1 root 874: 875: /* Now load the destination register. */ 876: emit_insn (gen_rtx (SET, mode, operand0, 877: gen_rtx (MEM, mode, scratch_reg))); 878: return 1; 879: } 880: /* Handle secondary reloads for SAR. These occur when trying to load 1.1.1.3 root 881: the SAR from memory a FP register, or with a constant. */ 1.1 root 882: else if (GET_CODE (operand0) == REG 883: && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS 884: && (GET_CODE (operand1) == MEM 1.1.1.3 root 885: || GET_CODE (operand1) == CONST_INT 1.1 root 886: || (GET_CODE (operand1) == REG 887: && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1))))) 888: && scratch_reg) 889: { 890: emit_move_insn (scratch_reg, operand1); 891: emit_move_insn (operand0, scratch_reg); 892: return 1; 893: } 894: /* Handle most common case: storing into a register. */ 895: else if (register_operand (operand0, mode)) 896: { 897: if (register_operand (operand1, mode) 898: || (GET_CODE (operand1) == CONST_INT && INT_14_BITS (operand1)) 899: || (operand1 == CONST0_RTX (mode)) 900: || (GET_CODE (operand1) == HIGH 1.1.1.3 root 901: && !symbolic_operand (XEXP (operand1, 0), VOIDmode)) 1.1 root 902: /* Only `general_operands' can come here, so MEM is ok. */ 903: || GET_CODE (operand1) == MEM) 904: { 905: /* Run this case quickly. */ 906: emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1)); 907: return 1; 908: } 909: } 910: else if (GET_CODE (operand0) == MEM) 911: { 912: if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode)) 913: { 914: /* Run this case quickly. */ 915: emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1)); 916: return 1; 917: } 1.1.1.2 root 918: if (! (reload_in_progress || reload_completed)) 1.1 root 919: { 920: operands[0] = validize_mem (operand0); 921: operands[1] = operand1 = force_reg (mode, operand1); 922: } 923: } 924: 925: /* Simplify the source if we need to. */ 1.1.1.2 root 926: if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) 1.1 root 927: || (GET_CODE (operand1) == HIGH 1.1.1.2 root 928: && symbolic_operand (XEXP (operand1, 0), mode))) 1.1 root 929: { 930: int ishighonly = 0; 931: 932: if (GET_CODE (operand1) == HIGH) 933: { 934: ishighonly = 1; 935: operand1 = XEXP (operand1, 0); 936: } 937: if (symbolic_operand (operand1, mode)) 938: { 1.1.1.4 ! root 939: rtx const_part = NULL; ! 940: ! 941: /* Argh. The assembler and linker can't handle arithmetic ! 942: involving plabels. We'll have to split up operand1 here ! 943: if it's a function label involved in an arithmetic ! 944: expression. Luckily, this only happens with addition ! 945: of constants to plabels, which simplifies the test. ! 946: ! 947: We add the constant back in just before returning to ! 948: our caller. */ ! 949: if (GET_CODE (operand1) == CONST ! 950: && GET_CODE (XEXP (operand1, 0)) == PLUS ! 951: && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode)) ! 952: { ! 953: /* Save away the constant part of the expression. */ ! 954: const_part = XEXP (XEXP (operand1, 0), 1); ! 955: if (GET_CODE (const_part) != CONST_INT) ! 956: abort (); ! 957: ! 958: /* Set operand1 to just the SYMBOL_REF. */ ! 959: operand1 = XEXP (XEXP (operand1, 0), 0); ! 960: } ! 961: 1.1 root 962: if (flag_pic) 963: { 1.1.1.2 root 964: rtx temp; 965: 966: if (reload_in_progress || reload_completed) 1.1.1.4 ! root 967: temp = scratch_reg ? scratch_reg : operand0; 1.1.1.2 root 968: else 969: temp = gen_reg_rtx (Pmode); 1.1.1.3 root 970: 1.1.1.4 ! root 971: /* If operand1 is a function label, then we've got to ! 972: force it to memory, then load op0 from memory. */ ! 973: if (function_label_operand (operand1, mode)) ! 974: { ! 975: operands[1] = force_const_mem (mode, operand1); ! 976: emit_move_sequence (operands, mode, temp); ! 977: } ! 978: /* Likewise for (const (plus (symbol) (const_int)) when generating ! 979: pic code during or after reload and const_int will not fit ! 980: in 14 bits. */ ! 981: else if (GET_CODE (operand1) == CONST ! 982: && GET_CODE (XEXP (operand1, 0)) == PLUS ! 983: && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT ! 984: && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1)) ! 985: && (reload_completed || reload_in_progress) ! 986: && flag_pic) ! 987: { ! 988: operands[1] = force_const_mem (mode, operand1); ! 989: operands[1] = legitimize_pic_address (XEXP (operands[1], 0), ! 990: mode, temp); ! 991: emit_move_sequence (operands, mode, temp); ! 992: } ! 993: else ! 994: { ! 995: operands[1] = legitimize_pic_address (operand1, mode, temp); ! 996: emit_insn (gen_rtx (SET, VOIDmode, operand0, operands[1])); ! 997: } 1.1 root 998: } 1.1.1.4 ! root 999: /* On the HPPA, references to data space are supposed to use dp, ! 1000: register 27, but showing it in the RTL inhibits various cse ! 1001: and loop optimizations. */ 1.1.1.3 root 1002: else 1.1 root 1003: { 1.1.1.4 ! root 1004: rtx temp, set; 1.1 root 1005: 1.1.1.3 root 1006: if (reload_in_progress || reload_completed) 1.1 root 1007: temp = scratch_reg ? scratch_reg : operand0; 1008: else 1009: temp = gen_reg_rtx (mode); 1010: 1011: if (ishighonly) 1012: set = gen_rtx (SET, mode, operand0, temp); 1013: else 1014: set = gen_rtx (SET, VOIDmode, 1015: operand0, 1016: gen_rtx (LO_SUM, mode, temp, operand1)); 1.1.1.3 root 1017: 1.1 root 1018: emit_insn (gen_rtx (SET, VOIDmode, 1019: temp, 1020: gen_rtx (HIGH, mode, operand1))); 1.1.1.3 root 1021: emit_insn (set); 1.1.1.2 root 1022: 1.1 root 1023: } 1.1.1.4 ! root 1024: ! 1025: /* Add back in the constant part if needed. */ ! 1026: if (const_part != NULL) ! 1027: expand_inc (operand0, const_part); 1.1 root 1028: return 1; 1029: } 1030: else if (GET_CODE (operand1) != CONST_INT 1.1.1.2 root 1031: || ! cint_ok_for_move (INTVAL (operand1))) 1.1 root 1032: { 1.1.1.2 root 1033: rtx temp; 1034: 1035: if (reload_in_progress || reload_completed) 1036: temp = operand0; 1037: else 1038: temp = gen_reg_rtx (mode); 1039: 1.1 root 1040: emit_insn (gen_rtx (SET, VOIDmode, temp, 1041: gen_rtx (HIGH, mode, operand1))); 1042: operands[1] = gen_rtx (LO_SUM, mode, temp, operand1); 1043: } 1044: } 1045: /* Now have insn-emit do whatever it normally does. */ 1046: return 0; 1047: } 1048: 1049: /* Does operand (which is a symbolic_operand) live in text space? If 1050: so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. */ 1051: 1052: int 1053: read_only_operand (operand) 1054: rtx operand; 1055: { 1056: if (GET_CODE (operand) == CONST) 1057: operand = XEXP (XEXP (operand, 0), 0); 1.1.1.4 ! root 1058: if (flag_pic) ! 1059: { ! 1060: if (GET_CODE (operand) == SYMBOL_REF) ! 1061: return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand); ! 1062: } ! 1063: else ! 1064: { ! 1065: if (GET_CODE (operand) == SYMBOL_REF) ! 1066: return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); ! 1067: } 1.1 root 1068: return 1; 1069: } 1.1.1.3 root 1070: 1.1 root 1071: 1072: /* Return the best assembler insn template 1.1.1.2 root 1073: for moving operands[1] into operands[0] as a fullword. */ 1.1 root 1074: char * 1075: singlemove_string (operands) 1076: rtx *operands; 1077: { 1.1.1.4 ! root 1078: HOST_WIDE_INT intval; ! 1079: 1.1 root 1080: if (GET_CODE (operands[0]) == MEM) 1081: return "stw %r1,%0"; 1.1.1.4 ! root 1082: if (GET_CODE (operands[1]) == MEM) 1.1 root 1083: return "ldw %1,%0"; 1.1.1.4 ! root 1084: if (GET_CODE (operands[1]) == CONST_DOUBLE) 1.1 root 1085: { 1.1.1.4 ! root 1086: long i; ! 1087: REAL_VALUE_TYPE d; 1.1 root 1088: 1.1.1.4 ! root 1089: if (GET_MODE (operands[1]) != SFmode) ! 1090: abort (); 1.1.1.2 root 1091: 1.1.1.4 ! root 1092: /* Translate the CONST_DOUBLE to a CONST_INT with the same target ! 1093: bit pattern. */ ! 1094: REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]); ! 1095: REAL_VALUE_TO_TARGET_SINGLE (d, i); ! 1096: ! 1097: operands[1] = GEN_INT (i); ! 1098: /* Fall through to CONST_INT case. */ ! 1099: } ! 1100: if (GET_CODE (operands[1]) == CONST_INT) ! 1101: { ! 1102: intval = INTVAL (operands[1]); ! 1103: ! 1104: if (VAL_14_BITS_P (intval)) ! 1105: return "ldi %1,%0"; ! 1106: else if ((intval & 0x7ff) == 0) ! 1107: return "ldil L'%1,%0"; ! 1108: else if (zdepi_cint_p (intval)) ! 1109: return "zdepi %Z1,%0"; 1.1 root 1110: else 1111: return "ldil L'%1,%0\n\tldo R'%1(%0),%0"; 1112: } 1113: return "copy %1,%0"; 1114: } 1115: 1116: 1117: /* Compute position (in OP[1]) and width (in OP[2]) 1118: useful for copying IMM to a register using the zdepi 1119: instructions. Store the immediate value to insert in OP[0]. */ 1120: void 1121: compute_zdepi_operands (imm, op) 1.1.1.3 root 1122: unsigned HOST_WIDE_INT imm; 1.1 root 1123: unsigned *op; 1124: { 1125: int lsb, len; 1126: 1127: /* Find the least significant set bit in IMM. */ 1128: for (lsb = 0; lsb < 32; lsb++) 1129: { 1130: if ((imm & 1) != 0) 1131: break; 1132: imm >>= 1; 1133: } 1134: 1135: /* Choose variants based on *sign* of the 5-bit field. */ 1136: if ((imm & 0x10) == 0) 1137: len = (lsb <= 28) ? 4 : 32 - lsb; 1138: else 1139: { 1140: /* Find the width of the bitstring in IMM. */ 1141: for (len = 5; len < 32; len++) 1142: { 1143: if ((imm & (1 << len)) == 0) 1144: break; 1145: } 1146: 1147: /* Sign extend IMM as a 5-bit value. */ 1148: imm = (imm & 0xf) - 0x10; 1149: } 1150: 1151: op[0] = imm; 1152: op[1] = 31 - lsb; 1153: op[2] = len; 1154: } 1155: 1156: /* Output assembler code to perform a doubleword move insn 1157: with operands OPERANDS. */ 1158: 1159: char * 1160: output_move_double (operands) 1161: rtx *operands; 1162: { 1163: enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1; 1164: rtx latehalf[2]; 1165: rtx addreg0 = 0, addreg1 = 0; 1166: 1167: /* First classify both operands. */ 1168: 1169: if (REG_P (operands[0])) 1170: optype0 = REGOP; 1171: else if (offsettable_memref_p (operands[0])) 1172: optype0 = OFFSOP; 1173: else if (GET_CODE (operands[0]) == MEM) 1174: optype0 = MEMOP; 1175: else 1176: optype0 = RNDOP; 1177: 1178: if (REG_P (operands[1])) 1179: optype1 = REGOP; 1180: else if (CONSTANT_P (operands[1])) 1181: optype1 = CNSTOP; 1182: else if (offsettable_memref_p (operands[1])) 1183: optype1 = OFFSOP; 1184: else if (GET_CODE (operands[1]) == MEM) 1185: optype1 = MEMOP; 1186: else 1187: optype1 = RNDOP; 1188: 1189: /* Check for the cases that the operand constraints are not 1190: supposed to allow to happen. Abort if we get one, 1191: because generating code for these cases is painful. */ 1192: 1193: if (optype0 != REGOP && optype1 != REGOP) 1194: abort (); 1195: 1196: /* Handle auto decrementing and incrementing loads and stores 1197: specifically, since the structure of the function doesn't work 1198: for them without major modification. Do it better when we learn 1199: this port about the general inc/dec addressing of PA. 1200: (This was written by tege. Chide him if it doesn't work.) */ 1201: 1202: if (optype0 == MEMOP) 1203: { 1204: /* We have to output the address syntax ourselves, since print_operand 1205: doesn't deal with the addresses we want to use. Fix this later. */ 1206: 1207: rtx addr = XEXP (operands[0], 0); 1208: if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC) 1209: { 1210: rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0); 1211: 1212: operands[0] = XEXP (addr, 0); 1213: if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG) 1214: abort (); 1215: 1216: if (!reg_overlap_mentioned_p (high_reg, addr)) 1217: { 1218: /* No overlap between high target register and address 1219: register. (We do this in a non-obvious way to 1220: save a register file writeback) */ 1221: if (GET_CODE (addr) == POST_INC) 1222: return "stws,ma %1,8(0,%0)\n\tstw %R1,-4(0,%0)"; 1223: return "stws,ma %1,-8(0,%0)\n\tstw %R1,12(0,%0)"; 1224: } 1225: else 1226: abort(); 1227: } 1228: else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) 1229: { 1230: rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0); 1231: 1232: operands[0] = XEXP (addr, 0); 1233: if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG) 1234: abort (); 1235: 1236: if (!reg_overlap_mentioned_p (high_reg, addr)) 1237: { 1238: /* No overlap between high target register and address 1239: register. (We do this in a non-obvious way to 1240: save a register file writeback) */ 1241: if (GET_CODE (addr) == PRE_INC) 1242: return "stws,mb %1,8(0,%0)\n\tstw %R1,4(0,%0)"; 1243: return "stws,mb %1,-8(0,%0)\n\tstw %R1,4(0,%0)"; 1244: } 1245: else 1246: abort(); 1247: } 1248: } 1249: if (optype1 == MEMOP) 1250: { 1251: /* We have to output the address syntax ourselves, since print_operand 1252: doesn't deal with the addresses we want to use. Fix this later. */ 1253: 1254: rtx addr = XEXP (operands[1], 0); 1255: if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC) 1256: { 1257: rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0); 1258: 1259: operands[1] = XEXP (addr, 0); 1260: if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG) 1261: abort (); 1262: 1263: if (!reg_overlap_mentioned_p (high_reg, addr)) 1264: { 1265: /* No overlap between high target register and address 1266: register. (We do this in a non-obvious way to 1267: save a register file writeback) */ 1268: if (GET_CODE (addr) == POST_INC) 1269: return "ldws,ma 8(0,%1),%0\n\tldw -4(0,%1),%R0"; 1270: return "ldws,ma -8(0,%1),%0\n\tldw 12(0,%1),%R0"; 1271: } 1272: else 1273: { 1274: /* This is an undefined situation. We should load into the 1275: address register *and* update that register. Probably 1276: we don't need to handle this at all. */ 1277: if (GET_CODE (addr) == POST_INC) 1278: return "ldw 4(0,%1),%R0\n\tldws,ma 8(0,%1),%0"; 1279: return "ldw 4(0,%1),%R0\n\tldws,ma -8(0,%1),%0"; 1280: } 1281: } 1282: else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) 1283: { 1284: rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0); 1285: 1286: operands[1] = XEXP (addr, 0); 1287: if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG) 1288: abort (); 1289: 1290: if (!reg_overlap_mentioned_p (high_reg, addr)) 1291: { 1292: /* No overlap between high target register and address 1293: register. (We do this in a non-obvious way to 1294: save a register file writeback) */ 1295: if (GET_CODE (addr) == PRE_INC) 1296: return "ldws,mb 8(0,%1),%0\n\tldw 4(0,%1),%R0"; 1297: return "ldws,mb -8(0,%1),%0\n\tldw 4(0,%1),%R0"; 1298: } 1299: else 1300: { 1301: /* This is an undefined situation. We should load into the 1302: address register *and* update that register. Probably 1303: we don't need to handle this at all. */ 1304: if (GET_CODE (addr) == PRE_INC) 1305: return "ldw 12(0,%1),%R0\n\tldws,mb 8(0,%1),%0"; 1306: return "ldw -4(0,%1),%R0\n\tldws,mb -8(0,%1),%0"; 1307: } 1308: } 1309: } 1310: 1311: /* If an operand is an unoffsettable memory ref, find a register 1312: we can increment temporarily to make it refer to the second word. */ 1313: 1314: if (optype0 == MEMOP) 1315: addreg0 = find_addr_reg (XEXP (operands[0], 0)); 1316: 1317: if (optype1 == MEMOP) 1318: addreg1 = find_addr_reg (XEXP (operands[1], 0)); 1319: 1320: /* Ok, we can do one word at a time. 1321: Normally we do the low-numbered word first. 1322: 1323: In either case, set up in LATEHALF the operands to use 1324: for the high-numbered word and in some cases alter the 1325: operands in OPERANDS to be suitable for the low-numbered word. */ 1326: 1327: if (optype0 == REGOP) 1328: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 1329: else if (optype0 == OFFSOP) 1330: latehalf[0] = adj_offsettable_operand (operands[0], 4); 1331: else 1332: latehalf[0] = operands[0]; 1333: 1334: if (optype1 == REGOP) 1335: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); 1336: else if (optype1 == OFFSOP) 1337: latehalf[1] = adj_offsettable_operand (operands[1], 4); 1338: else if (optype1 == CNSTOP) 1339: split_double (operands[1], &operands[1], &latehalf[1]); 1340: else 1341: latehalf[1] = operands[1]; 1342: 1343: /* If the first move would clobber the source of the second one, 1344: do them in the other order. 1345: 1346: RMS says "This happens only for registers; 1347: such overlap can't happen in memory unless the user explicitly 1348: sets it up, and that is an undefined circumstance." 1349: 1350: but it happens on the HP-PA when loading parameter registers, 1351: so I am going to define that circumstance, and make it work 1352: as expected. */ 1353: 1354: if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP) 1355: && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) 1356: { 1357: /* XXX THIS PROBABLY DOESN'T WORK. */ 1358: /* Do the late half first. */ 1359: if (addreg1) 1360: output_asm_insn ("ldo 4(%0),%0", &addreg1); 1361: output_asm_insn (singlemove_string (latehalf), latehalf); 1362: if (addreg1) 1363: output_asm_insn ("ldo -4(%0),%0", &addreg1); 1364: /* Then clobber. */ 1365: return singlemove_string (operands); 1366: } 1367: 1368: if (optype0 == REGOP && optype1 == REGOP 1369: && REGNO (operands[0]) == REGNO (operands[1]) + 1) 1370: { 1371: output_asm_insn (singlemove_string (latehalf), latehalf); 1372: return singlemove_string (operands); 1373: } 1374: 1375: /* Normal case: do the two words, low-numbered first. */ 1376: 1377: output_asm_insn (singlemove_string (operands), operands); 1378: 1379: /* Make any unoffsettable addresses point at high-numbered word. */ 1380: if (addreg0) 1381: output_asm_insn ("ldo 4(%0),%0", &addreg0); 1382: if (addreg1) 1383: output_asm_insn ("ldo 4(%0),%0", &addreg1); 1384: 1385: /* Do that word. */ 1386: output_asm_insn (singlemove_string (latehalf), latehalf); 1387: 1388: /* Undo the adds we just did. */ 1389: if (addreg0) 1390: output_asm_insn ("ldo -4(%0),%0", &addreg0); 1391: if (addreg1) 1392: output_asm_insn ("ldo -4(%0),%0", &addreg1); 1393: 1394: return ""; 1395: } 1396: 1397: char * 1398: output_fp_move_double (operands) 1399: rtx *operands; 1400: { 1401: if (FP_REG_P (operands[0])) 1402: { 1.1.1.3 root 1403: if (FP_REG_P (operands[1]) 1.1 root 1404: || operands[1] == CONST0_RTX (GET_MODE (operands[0]))) 1405: output_asm_insn ("fcpy,dbl %r1,%0", operands); 1.1.1.3 root 1406: else 1.1 root 1407: output_asm_insn ("fldds%F1 %1,%0", operands); 1408: } 1409: else if (FP_REG_P (operands[1])) 1410: { 1411: output_asm_insn ("fstds%F0 %1,%0", operands); 1412: } 1413: else if (operands[1] == CONST0_RTX (GET_MODE (operands[0]))) 1414: { 1415: if (GET_CODE (operands[0]) == REG) 1416: { 1417: rtx xoperands[2]; 1418: xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 1419: xoperands[0] = operands[0]; 1420: output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands); 1421: } 1.1.1.3 root 1422: /* This is a pain. You have to be prepared to deal with an 1.1.1.4 ! root 1423: arbitrary address here including pre/post increment/decrement. 1.1 root 1424: 1425: so avoid this in the MD. */ 1426: else 1427: abort (); 1428: } 1429: else abort (); 1430: return ""; 1431: } 1432: 1433: /* Return a REG that occurs in ADDR with coefficient 1. 1434: ADDR can be effectively incremented by incrementing REG. */ 1435: 1436: static rtx 1437: find_addr_reg (addr) 1438: rtx addr; 1439: { 1440: while (GET_CODE (addr) == PLUS) 1441: { 1442: if (GET_CODE (XEXP (addr, 0)) == REG) 1443: addr = XEXP (addr, 0); 1444: else if (GET_CODE (XEXP (addr, 1)) == REG) 1445: addr = XEXP (addr, 1); 1446: else if (CONSTANT_P (XEXP (addr, 0))) 1447: addr = XEXP (addr, 1); 1448: else if (CONSTANT_P (XEXP (addr, 1))) 1449: addr = XEXP (addr, 0); 1450: else 1451: abort (); 1452: } 1453: if (GET_CODE (addr) == REG) 1454: return addr; 1455: abort (); 1456: } 1457: 1458: /* Emit code to perform a block move. 1459: 1460: Restriction: If the length argument is non-constant, alignment 1461: must be 4. 1462: 1463: OPERANDS[0] is the destination pointer as a REG, clobbered. 1464: OPERANDS[1] is the source pointer as a REG, clobbered. 1465: if SIZE_IS_CONSTANT 1466: OPERANDS[2] is a register for temporary storage. 1467: OPERANDS[4] is the size as a CONST_INT 1468: else 1469: OPERANDS[2] is a REG which will contain the size, clobbered. 1470: OPERANDS[3] is a register for temporary storage. 1471: OPERANDS[5] is the alignment safe to use, as a CONST_INT. */ 1472: 1473: char * 1474: output_block_move (operands, size_is_constant) 1475: rtx *operands; 1476: int size_is_constant; 1477: { 1478: int align = INTVAL (operands[5]); 1479: unsigned long n_bytes; 1480: 1481: /* We can't move more than four bytes at a time because the PA 1482: has no longer integer move insns. (Could use fp mem ops?) */ 1483: if (align > 4) 1484: align = 4; 1485: 1486: if (size_is_constant) 1487: { 1488: unsigned long offset; 1489: rtx temp; 1490: 1491: n_bytes = INTVAL (operands[4]); 1492: if (n_bytes == 0) 1493: return ""; 1494: 1495: if (align >= 4) 1496: { 1497: /* Don't unroll too large blocks. */ 1.1.1.3 root 1498: if (n_bytes > 32) 1.1 root 1499: goto copy_with_loop; 1500: 1501: /* Read and store using two registers, and hide latency 1502: by deferring the stores until three instructions after 1503: the corresponding load. The last load insn will read 1504: the entire word were the last bytes are, possibly past 1505: the end of the source block, but since loads are aligned, 1506: this is harmless. */ 1507: 1508: output_asm_insn ("ldws,ma 4(0,%1),%2", operands); 1509: 1510: for (offset = 4; offset < n_bytes; offset += 4) 1511: { 1512: output_asm_insn ("ldws,ma 4(0,%1),%3", operands); 1513: output_asm_insn ("stws,ma %2,4(0,%0)", operands); 1514: 1515: temp = operands[2]; 1516: operands[2] = operands[3]; 1517: operands[3] = temp; 1518: } 1519: if (n_bytes % 4 == 0) 1520: /* Store the last word. */ 1521: output_asm_insn ("stw %2,0(0,%0)", operands); 1522: else 1523: { 1524: /* Store the last, partial word. */ 1.1.1.4 ! root 1525: operands[4] = GEN_INT (n_bytes % 4); 1.1 root 1526: output_asm_insn ("stbys,e %2,%4(0,%0)", operands); 1527: } 1528: return ""; 1529: } 1530: 1531: if (align >= 2 && n_bytes >= 2) 1532: { 1533: output_asm_insn ("ldhs,ma 2(0,%1),%2", operands); 1534: 1535: for (offset = 2; offset + 2 <= n_bytes; offset += 2) 1536: { 1537: output_asm_insn ("ldhs,ma 2(0,%1),%3", operands); 1538: output_asm_insn ("sths,ma %2,2(0,%0)", operands); 1539: 1540: temp = operands[2]; 1541: operands[2] = operands[3]; 1542: operands[3] = temp; 1543: } 1544: if (n_bytes % 2 != 0) 1545: output_asm_insn ("ldb 0(0,%1),%3", operands); 1546: 1547: output_asm_insn ("sths,ma %2,2(0,%0)", operands); 1548: 1549: if (n_bytes % 2 != 0) 1550: output_asm_insn ("stb %3,0(0,%0)", operands); 1551: 1552: return ""; 1553: } 1554: 1555: output_asm_insn ("ldbs,ma 1(0,%1),%2", operands); 1556: 1557: for (offset = 1; offset + 1 <= n_bytes; offset += 1) 1558: { 1559: output_asm_insn ("ldbs,ma 1(0,%1),%3", operands); 1560: output_asm_insn ("stbs,ma %2,1(0,%0)", operands); 1561: 1562: temp = operands[2]; 1563: operands[2] = operands[3]; 1564: operands[3] = temp; 1565: } 1566: output_asm_insn ("stb %2,0(0,%0)", operands); 1567: 1568: return ""; 1569: } 1570: 1571: if (align != 4) 1572: abort(); 1.1.1.3 root 1573: 1.1 root 1574: copy_with_loop: 1575: 1576: if (size_is_constant) 1577: { 1578: /* Size is compile-time determined, and also not 1579: very small (such small cases are handled above). */ 1.1.1.4 ! root 1580: operands[4] = GEN_INT (n_bytes - 4); 1.1 root 1581: output_asm_insn ("ldo %4(0),%2", operands); 1582: } 1583: else 1584: { 1585: /* Decrement counter by 4, and if it becomes negative, jump past the 1586: word copying loop. */ 1587: output_asm_insn ("addib,<,n -4,%2,.+16", operands); 1588: } 1589: 1590: /* Copying loop. Note that the first load is in the annulled delay slot 1591: of addib. Is it OK on PA to have a load in a delay slot, i.e. is a 1592: possible page fault stopped in time? */ 1593: output_asm_insn ("ldws,ma 4(0,%1),%3", operands); 1594: output_asm_insn ("addib,>= -4,%2,.-4", operands); 1595: output_asm_insn ("stws,ma %3,4(0,%0)", operands); 1596: 1597: /* The counter is negative, >= -4. The remaining number of bytes are 1598: determined by the two least significant bits. */ 1599: 1600: if (size_is_constant) 1601: { 1602: if (n_bytes % 4 != 0) 1603: { 1604: /* Read the entire word of the source block tail. */ 1605: output_asm_insn ("ldw 0(0,%1),%3", operands); 1.1.1.4 ! root 1606: operands[4] = GEN_INT (n_bytes % 4); 1.1 root 1607: output_asm_insn ("stbys,e %3,%4(0,%0)", operands); 1608: } 1609: } 1610: else 1611: { 1612: /* Add 4 to counter. If it becomes zero, we're done. */ 1613: output_asm_insn ("addib,=,n 4,%2,.+16", operands); 1614: 1615: /* Read the entire word of the source block tail. (Also this 1616: load is in an annulled delay slot.) */ 1617: output_asm_insn ("ldw 0(0,%1),%3", operands); 1618: 1619: /* Make %0 point at the first byte after the destination block. */ 1.1.1.3 root 1620: output_asm_insn ("addl %2,%0,%0", operands); 1.1 root 1621: /* Store the leftmost bytes, up to, but not including, the address 1622: in %0. */ 1623: output_asm_insn ("stbys,e %3,0(0,%0)", operands); 1624: } 1625: return ""; 1626: } 1627: 1628: /* Count the number of insns necessary to handle this block move. 1629: 1630: Basic structure is the same as emit_block_move, except that we 1631: count insns rather than emit them. */ 1632: 1633: int 1634: compute_movstrsi_length (insn) 1635: rtx insn; 1636: { 1637: rtx pat = PATTERN (insn); 1638: int size_is_constant; 1639: int align = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0)); 1640: unsigned long n_bytes; 1641: int insn_count = 0; 1642: 1643: if (GET_CODE (XEXP (XVECEXP (pat, 0, 5), 0)) == CONST_INT) 1644: { 1645: size_is_constant = 1; 1646: n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0)); 1647: } 1648: else 1649: { 1650: size_is_constant = 0; 1651: n_bytes = 0; 1652: } 1653: 1654: /* We can't move more than four bytes at a time because the PA 1655: has no longer integer move insns. (Could use fp mem ops?) */ 1656: if (align > 4) 1657: align = 4; 1658: 1659: if (size_is_constant) 1660: { 1661: unsigned long offset; 1662: 1663: if (n_bytes == 0) 1664: return 0; 1665: 1666: if (align >= 4) 1667: { 1668: /* Don't unroll too large blocks. */ 1.1.1.3 root 1669: if (n_bytes > 32) 1.1 root 1670: goto copy_with_loop; 1671: 1672: /* first load */ 1673: insn_count = 1; 1674: 1675: /* Count the unrolled insns. */ 1676: for (offset = 4; offset < n_bytes; offset += 4) 1677: insn_count += 2; 1678: 1679: /* Count last store or partial store. */ 1680: insn_count += 1; 1.1.1.2 root 1681: return insn_count * 4; 1.1 root 1682: } 1683: 1684: if (align >= 2 && n_bytes >= 2) 1685: { 1686: /* initial load. */ 1687: insn_count = 1; 1688: 1689: /* Unrolled loop. */ 1690: for (offset = 2; offset + 2 <= n_bytes; offset += 2) 1691: insn_count += 2; 1692: 1693: /* ??? odd load/store */ 1694: if (n_bytes % 2 != 0) 1695: insn_count += 2; 1696: 1697: /* ??? final store from loop. */ 1698: insn_count += 1; 1699: 1.1.1.2 root 1700: return insn_count * 4; 1.1 root 1701: } 1702: 1703: /* First load. */ 1704: insn_count = 1; 1705: 1706: /* The unrolled loop. */ 1707: for (offset = 1; offset + 1 <= n_bytes; offset += 1) 1708: insn_count += 2; 1709: 1710: /* Final store. */ 1711: insn_count += 1; 1712: 1.1.1.2 root 1713: return insn_count * 4; 1.1 root 1714: } 1715: 1716: if (align != 4) 1717: abort(); 1.1.1.3 root 1718: 1.1 root 1719: copy_with_loop: 1720: 1721: /* setup for constant and non-constant case. */ 1722: insn_count = 1; 1723: 1724: /* The copying loop. */ 1725: insn_count += 3; 1726: 1727: /* The counter is negative, >= -4. The remaining number of bytes are 1728: determined by the two least significant bits. */ 1729: 1730: if (size_is_constant) 1731: { 1732: if (n_bytes % 4 != 0) 1733: insn_count += 2; 1734: } 1735: else 1736: insn_count += 4; 1.1.1.2 root 1737: return insn_count * 4; 1.1 root 1738: } 1739: 1740: 1741: char * 1742: output_and (operands) 1743: rtx *operands; 1744: { 1745: if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) 1746: { 1.1.1.4 ! root 1747: unsigned HOST_WIDE_INT mask = INTVAL (operands[2]); 1.1 root 1748: int ls0, ls1, ms0, p, len; 1749: 1750: for (ls0 = 0; ls0 < 32; ls0++) 1751: if ((mask & (1 << ls0)) == 0) 1752: break; 1753: 1754: for (ls1 = ls0; ls1 < 32; ls1++) 1755: if ((mask & (1 << ls1)) != 0) 1756: break; 1757: 1758: for (ms0 = ls1; ms0 < 32; ms0++) 1759: if ((mask & (1 << ms0)) == 0) 1760: break; 1761: 1762: if (ms0 != 32) 1763: abort(); 1764: 1765: if (ls1 == 32) 1766: { 1767: len = ls0; 1768: 1769: if (len == 0) 1770: abort (); 1771: 1.1.1.4 ! root 1772: operands[2] = GEN_INT (len); 1.1 root 1773: return "extru %1,31,%2,%0"; 1774: } 1775: else 1776: { 1777: /* We could use this `depi' for the case above as well, but `depi' 1778: requires one more register file access than an `extru'. */ 1779: 1780: p = 31 - ls0; 1781: len = ls1 - ls0; 1782: 1.1.1.4 ! root 1783: operands[2] = GEN_INT (p); ! 1784: operands[3] = GEN_INT (len); 1.1 root 1785: return "depi 0,%2,%3,%0"; 1786: } 1787: } 1788: else 1789: return "and %1,%2,%0"; 1790: } 1791: 1792: char * 1793: output_ior (operands) 1794: rtx *operands; 1795: { 1.1.1.4 ! root 1796: unsigned HOST_WIDE_INT mask = INTVAL (operands[2]); 1.1.1.2 root 1797: int bs0, bs1, p, len; 1.1.1.3 root 1798: 1.1 root 1799: if (INTVAL (operands[2]) == 0) 1800: return "copy %1,%0"; 1801: 1802: for (bs0 = 0; bs0 < 32; bs0++) 1803: if ((mask & (1 << bs0)) != 0) 1804: break; 1805: 1806: for (bs1 = bs0; bs1 < 32; bs1++) 1807: if ((mask & (1 << bs1)) == 0) 1808: break; 1809: 1.1.1.4 ! root 1810: if (bs1 != 32 && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask) 1.1 root 1811: abort(); 1812: 1813: p = 31 - bs0; 1814: len = bs1 - bs0; 1815: 1.1.1.4 ! root 1816: operands[2] = GEN_INT (p); ! 1817: operands[3] = GEN_INT (len); 1.1 root 1818: return "depi -1,%2,%3,%0"; 1819: } 1820: 1821: /* Output an ascii string. */ 1.1.1.2 root 1822: void 1.1 root 1823: output_ascii (file, p, size) 1824: FILE *file; 1825: unsigned char *p; 1826: int size; 1827: { 1828: int i; 1829: int chars_output; 1830: unsigned char partial_output[16]; /* Max space 4 chars can occupy. */ 1831: 1832: /* The HP assembler can only take strings of 256 characters at one 1833: time. This is a limitation on input line length, *not* the 1834: length of the string. Sigh. Even worse, it seems that the 1835: restriction is in number of input characters (see \xnn & 1836: \whatever). So we have to do this very carefully. */ 1837: 1838: fprintf (file, "\t.STRING \""); 1839: 1840: chars_output = 0; 1841: for (i = 0; i < size; i += 4) 1842: { 1843: int co = 0; 1844: int io = 0; 1845: for (io = 0, co = 0; io < MIN (4, size - i); io++) 1846: { 1847: register unsigned int c = p[i + io]; 1848: 1849: if (c == '\"' || c == '\\') 1850: partial_output[co++] = '\\'; 1851: if (c >= ' ' && c < 0177) 1852: partial_output[co++] = c; 1853: else 1854: { 1855: unsigned int hexd; 1856: partial_output[co++] = '\\'; 1857: partial_output[co++] = 'x'; 1858: hexd = c / 16 - 0 + '0'; 1859: if (hexd > '9') 1860: hexd -= '9' - 'a' + 1; 1861: partial_output[co++] = hexd; 1862: hexd = c % 16 - 0 + '0'; 1863: if (hexd > '9') 1864: hexd -= '9' - 'a' + 1; 1865: partial_output[co++] = hexd; 1866: } 1867: } 1868: if (chars_output + co > 243) 1869: { 1870: fprintf (file, "\"\n\t.STRING \""); 1871: chars_output = 0; 1872: } 1873: fwrite (partial_output, 1, co, file); 1874: chars_output += co; 1875: co = 0; 1876: } 1877: fprintf (file, "\"\n"); 1878: } 1879: 1880: /* You may have trouble believing this, but this is the HP-PA stack 1881: layout. Wow. 1882: 1883: Offset Contents 1884: 1885: Variable arguments (optional; any number may be allocated) 1886: 1887: SP-(4*(N+9)) arg word N 1888: : : 1889: SP-56 arg word 5 1890: SP-52 arg word 4 1891: 1892: Fixed arguments (must be allocated; may remain unused) 1893: 1894: SP-48 arg word 3 1895: SP-44 arg word 2 1896: SP-40 arg word 1 1897: SP-36 arg word 0 1898: 1899: Frame Marker 1900: 1901: SP-32 External Data Pointer (DP) 1902: SP-28 External sr4 1903: SP-24 External/stub RP (RP') 1904: SP-20 Current RP 1905: SP-16 Static Link 1906: SP-12 Clean up 1907: SP-8 Calling Stub RP (RP'') 1908: SP-4 Previous SP 1909: 1910: Top of Frame 1911: 1912: SP-0 Stack Pointer (points to next available address) 1913: 1914: */ 1915: 1916: /* This function saves registers as follows. Registers marked with ' are 1917: this function's registers (as opposed to the previous function's). 1918: If a frame_pointer isn't needed, r4 is saved as a general register; 1919: the space for the frame pointer is still allocated, though, to keep 1920: things simple. 1921: 1922: 1923: Top of Frame 1924: 1925: SP (FP') Previous FP 1926: SP + 4 Alignment filler (sigh) 1927: SP + 8 Space for locals reserved here. 1928: . 1929: . 1930: . 1931: SP + n All call saved register used. 1932: . 1933: . 1934: . 1935: SP + o All call saved fp registers used. 1936: . 1937: . 1938: . 1939: SP + p (SP') points to next available address. 1.1.1.3 root 1940: 1.1 root 1941: */ 1942: 1943: /* Emit RTL to store REG at the memory location specified by BASE+DISP. 1944: Handle case where DISP > 8k by using the add_high_const pattern. 1945: 1946: Note in DISP > 8k case, we will leave the high part of the address 1947: in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ 1948: static void 1949: store_reg (reg, disp, base) 1950: int reg, disp, base; 1951: { 1952: if (VAL_14_BITS_P (disp)) 1953: { 1.1.1.3 root 1954: emit_move_insn (gen_rtx (MEM, SImode, 1955: gen_rtx (PLUS, SImode, 1.1 root 1956: gen_rtx (REG, SImode, base), 1957: GEN_INT (disp))), 1958: gen_rtx (REG, SImode, reg)); 1959: } 1960: else 1961: { 1.1.1.3 root 1962: emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1), 1963: gen_rtx (REG, SImode, base), 1.1 root 1964: GEN_INT (disp))); 1965: emit_move_insn (gen_rtx (MEM, SImode, 1.1.1.3 root 1966: gen_rtx (LO_SUM, SImode, 1.1 root 1967: gen_rtx (REG, SImode, 1), 1968: GEN_INT (disp))), 1969: gen_rtx (REG, SImode, reg)); 1970: } 1971: } 1972: 1973: /* Emit RTL to load REG from the memory location specified by BASE+DISP. 1974: Handle case where DISP > 8k by using the add_high_const pattern. 1975: 1976: Note in DISP > 8k case, we will leave the high part of the address 1977: in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ 1978: static void 1979: load_reg (reg, disp, base) 1980: int reg, disp, base; 1981: { 1982: if (VAL_14_BITS_P (disp)) 1983: { 1984: emit_move_insn (gen_rtx (REG, SImode, reg), 1.1.1.3 root 1985: gen_rtx (MEM, SImode, 1986: gen_rtx (PLUS, SImode, 1.1 root 1987: gen_rtx (REG, SImode, base), 1988: GEN_INT (disp)))); 1989: } 1990: else 1991: { 1.1.1.3 root 1992: emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1), 1.1 root 1993: gen_rtx (REG, SImode, base), 1994: GEN_INT (disp))); 1995: emit_move_insn (gen_rtx (REG, SImode, reg), 1996: gen_rtx (MEM, SImode, 1.1.1.3 root 1997: gen_rtx (LO_SUM, SImode, 1998: gen_rtx (REG, SImode, 1), 1.1 root 1999: GEN_INT (disp)))); 2000: } 2001: } 2002: 2003: /* Emit RTL to set REG to the value specified by BASE+DISP. 2004: Handle case where DISP > 8k by using the add_high_const pattern. 2005: 2006: Note in DISP > 8k case, we will leave the high part of the address 2007: in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ 2008: static void 2009: set_reg_plus_d(reg, base, disp) 2010: int reg, base, disp; 2011: { 2012: if (VAL_14_BITS_P (disp)) 2013: { 2014: emit_move_insn (gen_rtx (REG, SImode, reg), 1.1.1.3 root 2015: gen_rtx (PLUS, SImode, 1.1 root 2016: gen_rtx (REG, SImode, base), 2017: GEN_INT (disp))); 2018: } 2019: else 2020: { 1.1.1.3 root 2021: emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1), 1.1 root 2022: gen_rtx (REG, SImode, base), 2023: GEN_INT (disp))); 2024: emit_move_insn (gen_rtx (REG, SImode, reg), 1.1.1.3 root 2025: gen_rtx (LO_SUM, SImode, 1.1 root 2026: gen_rtx (REG, SImode, 1), 2027: GEN_INT (disp))); 2028: } 2029: } 2030: 2031: /* Global variables set by FUNCTION_PROLOGUE. */ 2032: /* Size of frame. Need to know this to emit return insns from 2033: leaf procedures. */ 2034: static int actual_fsize; 2035: static int local_fsize, save_fregs; 2036: 2037: int 2038: compute_frame_size (size, fregs_live) 2039: int size; 2040: int *fregs_live; 2041: { 2042: extern int current_function_outgoing_args_size; 2043: int i, fsize; 2044: 1.1.1.3 root 2045: /* 8 is space for frame pointer + filler. If any frame is allocated 1.1 root 2046: we need to add this in because of STARTING_FRAME_OFFSET. */ 2047: fsize = size + (size || frame_pointer_needed ? 8 : 0); 2048: 1.1.1.3 root 2049: for (i = 18; i >= 4; i--) 1.1 root 2050: { 1.1.1.3 root 2051: if (regs_ever_live[i]) 1.1 root 2052: fsize += 4; 2053: } 1.1.1.3 root 2054: /* If we don't have a frame pointer, the register normally used for that 2055: purpose is saved just like other registers, not in the "frame marker". */ 2056: if (! frame_pointer_needed) 1.1 root 2057: { 1.1.1.3 root 2058: if (regs_ever_live[FRAME_POINTER_REGNUM]) 2059: fsize += 4; 1.1 root 2060: } 2061: fsize = (fsize + 7) & ~7; 2062: 1.1.1.3 root 2063: for (i = 66; i >= 48; i -= 2) 2064: if (regs_ever_live[i] || regs_ever_live[i + 1]) 2065: { 2066: fsize += 8; 2067: if (fregs_live) 2068: *fregs_live = 1; 2069: } 2070: 1.1 root 2071: fsize += current_function_outgoing_args_size; 2072: if (! leaf_function_p () || fsize) 2073: fsize += 32; 1.1.1.2 root 2074: return (fsize + 63) & ~63; 1.1 root 2075: } 1.1.1.3 root 2076: 1.1 root 2077: rtx hp_profile_label_rtx; 2078: static char hp_profile_label_name[8]; 2079: void 2080: output_function_prologue (file, size) 2081: FILE *file; 2082: int size; 2083: { 1.1.1.3 root 2084: /* The function's label and associated .PROC must never be 2085: separated and must be output *after* any profiling declarations 2086: to avoid changing spaces/subspaces within a procedure. */ 2087: ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); 2088: fputs ("\t.PROC\n", file); 1.1 root 2089: 2090: /* hppa_expand_prologue does the dirty work now. We just need 2091: to output the assembler directives which denote the start 2092: of a function. */ 1.1.1.3 root 2093: fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize); 1.1 root 2094: if (regs_ever_live[2] || profile_flag) 1.1.1.2 root 2095: fprintf (file, ",CALLS,SAVE_RP"); 1.1 root 2096: else 1.1.1.2 root 2097: fprintf (file, ",NO_CALLS"); 2098: 2099: if (frame_pointer_needed) 2100: fprintf (file, ",SAVE_SP"); 2101: 2102: /* Pass on information about the number of callee register saves 2103: performed in the prologue. 2104: 2105: The compiler is supposed to pass the highest register number 1.1.1.3 root 2106: saved, the assembler then has to adjust that number before 1.1.1.2 root 2107: entering it into the unwind descriptor (to account for any 1.1.1.3 root 2108: caller saved registers with lower register numbers than the 1.1.1.2 root 2109: first callee saved register). */ 2110: if (gr_saved) 2111: fprintf (file, ",ENTRY_GR=%d", gr_saved + 2); 2112: 2113: if (fr_saved) 2114: fprintf (file, ",ENTRY_FR=%d", fr_saved + 11); 2115: 2116: fprintf (file, "\n\t.ENTRY\n"); 1.1 root 2117: 2118: /* Horrid hack. emit_function_prologue will modify this RTL in 2119: place to get the expected results. */ 2120: if (profile_flag) 1.1.1.3 root 2121: ASM_GENERATE_INTERNAL_LABEL (hp_profile_label_name, "LP", 2122: hp_profile_labelno); 1.1.1.4 ! root 2123: ! 2124: if (insn_addresses) ! 2125: { ! 2126: unsigned int old_total = total_code_bytes; ! 2127: ! 2128: total_code_bytes += insn_addresses[INSN_UID (get_last_insn())]; ! 2129: total_code_bytes += FUNCTION_BOUNDARY /BITS_PER_UNIT; ! 2130: ! 2131: /* Be prepared to handle overflows. */ ! 2132: total_code_bytes = old_total > total_code_bytes ? -1 : total_code_bytes; ! 2133: } ! 2134: else ! 2135: total_code_bytes = -1; 1.1 root 2136: } 2137: 1.1.1.2 root 2138: void 1.1 root 2139: hppa_expand_prologue() 2140: { 2141: extern char call_used_regs[]; 2142: int size = get_frame_size (); 2143: int merge_sp_adjust_with_store = 0; 2144: int i, offset; 2145: rtx tmpreg, size_rtx; 2146: 1.1.1.2 root 2147: gr_saved = 0; 2148: fr_saved = 0; 1.1 root 2149: save_fregs = 0; 2150: local_fsize = size + (size || frame_pointer_needed ? 8 : 0); 2151: actual_fsize = compute_frame_size (size, &save_fregs); 2152: 2153: /* Compute a few things we will use often. */ 2154: tmpreg = gen_rtx (REG, SImode, 1); 2155: size_rtx = GEN_INT (actual_fsize); 2156: 1.1.1.3 root 2157: /* Save RP first. The calling conventions manual states RP will 1.1 root 2158: always be stored into the caller's frame at sp-20. */ 2159: if (regs_ever_live[2] || profile_flag) 1.1.1.3 root 2160: store_reg (2, -20, STACK_POINTER_REGNUM); 2161: 1.1 root 2162: /* Allocate the local frame and set up the frame pointer if needed. */ 2163: if (actual_fsize) 2164: if (frame_pointer_needed) 2165: { 2166: /* Copy the old frame pointer temporarily into %r1. Set up the 2167: new stack pointer, then store away the saved old frame pointer 2168: into the stack at sp+actual_fsize and at the same time update 2169: the stack pointer by actual_fsize bytes. Two versions, first 2170: handles small (<8k) frames. The second handles large (>8k) 2171: frames. */ 2172: emit_move_insn (tmpreg, frame_pointer_rtx); 2173: emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); 2174: if (VAL_14_BITS_P (actual_fsize)) 2175: emit_insn (gen_post_stwm (stack_pointer_rtx, 2176: stack_pointer_rtx, 2177: size_rtx, tmpreg)); 2178: else 2179: { 1.1.1.3 root 2180: /* It is incorrect to store the saved frame pointer at *sp, 2181: then increment sp (writes beyond the current stack boundary). 2182: 2183: So instead use stwm to store at *sp and post-increment the 2184: stack pointer as an atomic operation. Then increment sp to 2185: finish allocating the new frame. */ 2186: emit_insn (gen_post_stwm (stack_pointer_rtx, 2187: stack_pointer_rtx, 2188: GEN_INT (64), tmpreg)); 1.1 root 2189: set_reg_plus_d (STACK_POINTER_REGNUM, 2190: STACK_POINTER_REGNUM, 1.1.1.3 root 2191: actual_fsize - 64); 1.1 root 2192: } 2193: } 2194: /* no frame pointer needed. */ 2195: else 2196: { 2197: /* In some cases we can perform the first callee register save 2198: and allocating the stack frame at the same time. If so, just 2199: make a note of it and defer allocating the frame until saving 2200: the callee registers. */ 1.1.1.3 root 2201: if (VAL_14_BITS_P (-actual_fsize) 2202: && local_fsize == 0 1.1 root 2203: && ! profile_flag 2204: && ! flag_pic) 2205: merge_sp_adjust_with_store = 1; 2206: /* Can not optimize. Adjust the stack frame by actual_fsize bytes. */ 2207: else if (actual_fsize != 0) 2208: set_reg_plus_d (STACK_POINTER_REGNUM, 2209: STACK_POINTER_REGNUM, 2210: actual_fsize); 2211: } 2212: /* The hppa calling conventions say that that %r19, the pic offset 2213: register, is saved at sp - 32 (in this function's frame) when 1.1.1.4 ! root 2214: generating PIC code. FIXME: What is the correct thing to do ! 2215: for functions which make no calls and allocate no frame? Do ! 2216: we need to allocate a frame, or can we just omit the save? For ! 2217: now we'll just omit the save. */ ! 2218: if (actual_fsize != 0 && flag_pic) 1.1.1.3 root 2219: store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM); 1.1 root 2220: 2221: /* Profiling code. 2222: 2223: Instead of taking one argument, the counter label, as most normal 2224: mcounts do, _mcount appears to behave differently on the HPPA. It 1.1.1.3 root 2225: takes the return address of the caller, the address of this routine, 2226: and the address of the label. Also, it isn't magic, so 1.1.1.4 ! root 2227: argument registers have to be preserved. */ 1.1 root 2228: if (profile_flag) 2229: { 2230: int pc_offset, i, arg_offset, basereg, offsetadj; 2231: 2232: pc_offset = 4 + (frame_pointer_needed 2233: ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20) 2234: : (VAL_14_BITS_P (actual_fsize) ? 4 : 8)); 2235: 2236: /* When the function has a frame pointer, use it as the base 2237: register for saving/restore registers. Else use the stack 2238: pointer. Adjust the offset according to the frame size if 2239: this function does not have a frame pointer. */ 2240: 2241: basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM 2242: : STACK_POINTER_REGNUM; 2243: offsetadj = frame_pointer_needed ? 0 : actual_fsize; 2244: 2245: /* Horrid hack. emit_function_prologue will modify this RTL in 2246: place to get the expected results. sprintf here is just to 2247: put something in the name. */ 2248: sprintf(hp_profile_label_name, "LP$%04d", -1); 2249: hp_profile_label_rtx = gen_rtx (SYMBOL_REF, SImode, 2250: hp_profile_label_name); 2251: if (current_function_returns_struct) 2252: store_reg (STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); 2253: 2254: for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) 2255: if (regs_ever_live [i]) 2256: { 2257: store_reg (i, arg_offset, basereg); 2258: /* Deal with arg_offset not fitting in 14 bits. */ 2259: pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8; 2260: } 2261: 2262: emit_move_insn (gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 2)); 2263: emit_move_insn (tmpreg, gen_rtx (HIGH, SImode, hp_profile_label_rtx)); 2264: emit_move_insn (gen_rtx (REG, SImode, 24), 2265: gen_rtx (LO_SUM, SImode, tmpreg, hp_profile_label_rtx)); 2266: /* %r25 is set from within the output pattern. */ 2267: emit_insn (gen_call_profiler (GEN_INT (- pc_offset - 20))); 2268: 2269: /* Restore argument registers. */ 2270: for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) 2271: if (regs_ever_live [i]) 2272: load_reg (i, arg_offset, basereg); 2273: 2274: if (current_function_returns_struct) 2275: load_reg (STRUCT_VALUE_REGNUM, -12 - offsetadj, basereg); 2276: 2277: } 2278: 1.1.1.3 root 2279: /* Normal register save. 1.1 root 2280: 2281: Do not save the frame pointer in the frame_pointer_needed case. It 2282: was done earlier. */ 2283: if (frame_pointer_needed) 2284: { 1.1.1.3 root 2285: for (i = 18, offset = local_fsize; i >= 4; i--) 2286: if (regs_ever_live[i] && ! call_used_regs[i]) 1.1 root 2287: { 1.1.1.3 root 2288: store_reg (i, offset, FRAME_POINTER_REGNUM); 1.1 root 2289: offset += 4; 1.1.1.2 root 2290: gr_saved++; 1.1 root 2291: } 1.1.1.2 root 2292: /* Account for %r4 which is saved in a special place. */ 2293: gr_saved++; 1.1 root 2294: } 2295: /* No frame pointer needed. */ 2296: else 2297: { 2298: for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--) 2299: if (regs_ever_live[i] && ! call_used_regs[i]) 2300: { 1.1.1.3 root 2301: /* If merge_sp_adjust_with_store is nonzero, then we can 1.1 root 2302: optimize the first GR save. */ 2303: if (merge_sp_adjust_with_store) 2304: { 2305: merge_sp_adjust_with_store = 0; 2306: emit_insn (gen_post_stwm (stack_pointer_rtx, 2307: stack_pointer_rtx, 2308: GEN_INT (-offset), 2309: gen_rtx (REG, SImode, i))); 2310: } 2311: else 2312: store_reg (i, offset, STACK_POINTER_REGNUM); 2313: offset += 4; 1.1.1.2 root 2314: gr_saved++; 1.1 root 2315: } 2316: 2317: /* If we wanted to merge the SP adjustment with a GR save, but we never 2318: did any GR saves, then just emit the adjustment here. */ 2319: if (merge_sp_adjust_with_store) 2320: set_reg_plus_d (STACK_POINTER_REGNUM, 2321: STACK_POINTER_REGNUM, 2322: actual_fsize); 2323: } 1.1.1.3 root 2324: 1.1 root 2325: /* Align pointer properly (doubleword boundary). */ 2326: offset = (offset + 7) & ~7; 2327: 2328: /* Floating point register store. */ 2329: if (save_fregs) 2330: { 2331: 2332: /* First get the frame or stack pointer to the start of the FP register 2333: save area. */ 2334: if (frame_pointer_needed) 2335: set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); 2336: else 2337: set_reg_plus_d (1, STACK_POINTER_REGNUM, offset); 2338: 2339: /* Now actually save the FP registers. */ 1.1.1.3 root 2340: for (i = 66; i >= 48; i -= 2) 2341: if (regs_ever_live[i] || regs_ever_live[i + 1]) 2342: { 2343: emit_move_insn (gen_rtx (MEM, DFmode, 2344: gen_rtx (POST_INC, DFmode, tmpreg)), 2345: gen_rtx (REG, DFmode, i)); 2346: fr_saved++; 2347: } 1.1 root 2348: } 1.1.1.4 ! root 2349: ! 2350: /* When generating PIC code it is necessary to save/restore the ! 2351: PIC register around each function call. We used to do this ! 2352: in the call patterns themselves, but that implementation ! 2353: made incorrect assumptions about using global variables to hold ! 2354: per-function rtl code generated in the backend. ! 2355: ! 2356: So instead, we copy the PIC register into a reserved callee saved ! 2357: register in the prologue. Then after each call we reload the PIC ! 2358: register from the callee saved register. We also reload the PIC ! 2359: register from the callee saved register in the epilogue ensure the ! 2360: PIC register is valid at function exit. ! 2361: ! 2362: This may (depending on the exact characteristics of the function) ! 2363: even be more efficient. ! 2364: ! 2365: Avoid this if the callee saved register wasn't used (these are ! 2366: leaf functions. */ ! 2367: if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM_SAVED]) ! 2368: emit_move_insn (gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED), ! 2369: gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM)); 1.1 root 2370: } 2371: 2372: 2373: void 2374: output_function_epilogue (file, size) 2375: FILE *file; 2376: int size; 2377: { 2378: rtx insn = get_last_insn (); 1.1.1.4 ! root 2379: int i; 1.1 root 2380: 2381: /* hppa_expand_epilogue does the dirty work now. We just need 2382: to output the assembler directives which denote the end 2383: of a function. 2384: 2385: To make debuggers happy, emit a nop if the epilogue was completely 2386: eliminated due to a volatile call as the last insn in the 1.1.1.3 root 2387: current function. That way the return address (in %r2) will 1.1 root 2388: always point to a valid instruction in the current function. */ 2389: 2390: /* Get the last real insn. */ 2391: if (GET_CODE (insn) == NOTE) 2392: insn = prev_real_insn (insn); 2393: 2394: /* If it is a sequence, then look inside. */ 2395: if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) 2396: insn = XVECEXP (PATTERN (insn), 0, 0); 2397: 1.1.1.3 root 2398: /* If insn is a CALL_INSN, then it must be a call to a volatile 1.1 root 2399: function (otherwise there would be epilogue insns). */ 2400: if (insn && GET_CODE (insn) == CALL_INSN) 2401: fprintf (file, "\tnop\n"); 1.1.1.3 root 2402: 1.1 root 2403: fprintf (file, "\t.EXIT\n\t.PROCEND\n"); 1.1.1.4 ! root 2404: ! 2405: /* If we have deferred plabels, then we need to switch into the data ! 2406: section and align it to a 4 byte boundary before we output the ! 2407: deferred plabels. */ ! 2408: if (n_deferred_plabels) ! 2409: { ! 2410: data_section (); ! 2411: ASM_OUTPUT_ALIGN (file, 2); ! 2412: } ! 2413: ! 2414: /* Now output the deferred plabels. */ ! 2415: for (i = 0; i < n_deferred_plabels; i++) ! 2416: { ! 2417: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label)); ! 2418: ASM_OUTPUT_INT (file, deferred_plabels[i].symbol); ! 2419: } ! 2420: n_deferred_plabels = 0; 1.1 root 2421: } 2422: 2423: void 2424: hppa_expand_epilogue () 2425: { 1.1.1.3 root 2426: rtx tmpreg; 1.1 root 2427: int offset,i; 2428: int merge_sp_adjust_with_load = 0; 2429: 2430: /* We will use this often. */ 2431: tmpreg = gen_rtx (REG, SImode, 1); 2432: 2433: /* Try to restore RP early to avoid load/use interlocks when 2434: RP gets used in the return (bv) instruction. This appears to still 2435: be necessary even when we schedule the prologue and epilogue. */ 2436: if (frame_pointer_needed 2437: && (regs_ever_live [2] || profile_flag)) 2438: load_reg (2, -20, FRAME_POINTER_REGNUM); 2439: 2440: /* No frame pointer, and stack is smaller than 8k. */ 2441: else if (! frame_pointer_needed 2442: && VAL_14_BITS_P (actual_fsize + 20) 2443: && (regs_ever_live[2] || profile_flag)) 2444: load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM); 2445: 2446: /* General register restores. */ 2447: if (frame_pointer_needed) 2448: { 1.1.1.3 root 2449: for (i = 18, offset = local_fsize; i >= 4; i--) 2450: if (regs_ever_live[i] && ! call_used_regs[i]) 1.1 root 2451: { 2452: load_reg (i, offset, FRAME_POINTER_REGNUM); 2453: offset += 4; 2454: } 2455: } 2456: else 2457: { 2458: for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--) 2459: if (regs_ever_live[i] && ! call_used_regs[i]) 2460: { 2461: /* Only for the first load. 2462: merge_sp_adjust_with_load holds the register load 2463: with which we will merge the sp adjustment. */ 2464: if (VAL_14_BITS_P (actual_fsize + 20) 2465: && local_fsize == 0 2466: && ! merge_sp_adjust_with_load) 2467: merge_sp_adjust_with_load = i; 2468: else 2469: load_reg (i, offset, STACK_POINTER_REGNUM); 2470: offset += 4; 2471: } 2472: } 2473: 2474: /* Align pointer properly (doubleword boundary). */ 2475: offset = (offset + 7) & ~7; 2476: 2477: /* FP register restores. */ 2478: if (save_fregs) 2479: { 2480: /* Adjust the register to index off of. */ 2481: if (frame_pointer_needed) 2482: set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); 2483: else 2484: set_reg_plus_d (1, STACK_POINTER_REGNUM, offset); 2485: 2486: /* Actually do the restores now. */ 1.1.1.3 root 2487: for (i = 66; i >= 48; i -= 2) 2488: if (regs_ever_live[i] || regs_ever_live[i + 1]) 2489: emit_move_insn (gen_rtx (REG, DFmode, i), 2490: gen_rtx (MEM, DFmode, 2491: gen_rtx (POST_INC, DFmode, tmpreg))); 1.1 root 2492: } 2493: 2494: /* No frame pointer, but we have a stack greater than 8k. We restore 2495: %r2 very late in this case. (All other cases are restored as early 2496: as possible.) */ 2497: if (! frame_pointer_needed 2498: && ! VAL_14_BITS_P (actual_fsize + 20) 2499: && (regs_ever_live[2] || profile_flag)) 2500: { 2501: set_reg_plus_d (STACK_POINTER_REGNUM, 2502: STACK_POINTER_REGNUM, 2503: - actual_fsize); 1.1.1.4 ! root 2504: ! 2505: /* This used to try and be clever by not depending on the value in ! 2506: %r30 and instead use the value held in %r1 (so that the 2nd insn ! 2507: which sets %r30 could be put in the delay slot of the return insn). ! 2508: ! 2509: That won't work since if the stack is exactly 8k set_reg_plus_d ! 2510: doesn't set %r1, just %r30. */ ! 2511: load_reg (2, - 20, STACK_POINTER_REGNUM); 1.1 root 2512: } 2513: 2514: /* Reset stack pointer (and possibly frame pointer). The stack */ 2515: /* pointer is initially set to fp + 64 to avoid a race condition. 2516: ??? What race condition?!? */ 2517: else if (frame_pointer_needed) 2518: { 2519: /* Emit a blockage insn here to keep these insns from being moved 2520: to the beginning of the prologue or into the main instruction 2521: stream, doing so avoids some very obscure problems. */ 2522: emit_insn (gen_blockage ()); 2523: set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64); 2524: emit_insn (gen_pre_ldwm (stack_pointer_rtx, stack_pointer_rtx, 2525: GEN_INT (-64), frame_pointer_rtx)); 2526: } 2527: /* If we were deferring a callee register restore, do it now. */ 2528: else if (! frame_pointer_needed && merge_sp_adjust_with_load) 2529: emit_insn (gen_pre_ldwm (stack_pointer_rtx, 2530: stack_pointer_rtx, 2531: GEN_INT (- actual_fsize), 1.1.1.3 root 2532: gen_rtx (REG, SImode, 1.1 root 2533: merge_sp_adjust_with_load))); 2534: else if (actual_fsize != 0) 2535: set_reg_plus_d (STACK_POINTER_REGNUM, 2536: STACK_POINTER_REGNUM, 2537: - actual_fsize); 2538: } 2539: 2540: /* This is only valid once reload has completed because it depends on 2541: knowing exactly how much (if any) frame there is and... 2542: 2543: It's only valid if there is no frame marker to de-allocate and... 2544: 2545: It's only valid if %r2 hasn't been saved into the caller's frame 2546: (we're not profiling and %r2 isn't live anywhere). */ 2547: int 2548: hppa_can_use_return_insn_p () 2549: { 2550: return (reload_completed 2551: && (compute_frame_size (get_frame_size (), 0) ? 0 : 1) 2552: && ! profile_flag 2553: && ! regs_ever_live[2] 2554: && ! frame_pointer_needed); 2555: } 2556: 2557: void 2558: emit_bcond_fp (code, operand0) 2559: enum rtx_code code; 2560: rtx operand0; 2561: { 2562: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, 2563: gen_rtx (IF_THEN_ELSE, VOIDmode, 1.1.1.3 root 2564: gen_rtx (code, VOIDmode, 1.1 root 2565: gen_rtx (REG, CCFPmode, 0), 2566: const0_rtx), 2567: gen_rtx (LABEL_REF, VOIDmode, operand0), 2568: pc_rtx))); 2569: 2570: } 2571: 2572: rtx 2573: gen_cmp_fp (code, operand0, operand1) 2574: enum rtx_code code; 2575: rtx operand0, operand1; 2576: { 2577: return gen_rtx (SET, VOIDmode, gen_rtx (REG, CCFPmode, 0), 2578: gen_rtx (code, CCFPmode, operand0, operand1)); 2579: } 2580: 2581: /* Adjust the cost of a scheduling dependency. Return the new cost of 2582: a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ 2583: 2584: int 2585: pa_adjust_cost (insn, link, dep_insn, cost) 2586: rtx insn; 2587: rtx link; 2588: rtx dep_insn; 2589: int cost; 2590: { 2591: if (! recog_memoized (insn)) 2592: return 0; 2593: 2594: if (REG_NOTE_KIND (link) == 0) 2595: { 2596: /* Data dependency; DEP_INSN writes a register that INSN reads some 2597: cycles later. */ 2598: 2599: if (get_attr_type (insn) == TYPE_FPSTORE) 2600: { 2601: rtx pat = PATTERN (insn); 2602: rtx dep_pat = PATTERN (dep_insn); 2603: if (GET_CODE (pat) == PARALLEL) 2604: { 2605: /* This happens for the fstXs,mb patterns. */ 2606: pat = XVECEXP (pat, 0, 0); 2607: } 2608: if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) 2609: /* If this happens, we have to extend this to schedule 2610: optimally. Return 0 for now. */ 2611: return 0; 2612: 2613: if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) 2614: { 2615: if (! recog_memoized (dep_insn)) 2616: return 0; 2617: /* DEP_INSN is writing its result to the register 2618: being stored in the fpstore INSN. */ 2619: switch (get_attr_type (dep_insn)) 2620: { 2621: case TYPE_FPLOAD: 1.1.1.4 ! root 2622: /* This cost 3 cycles, not 2 as the md says for the ! 2623: 700 and 7100. Note scaling of cost for 7100. */ ! 2624: return cost + (pa_cpu == PROCESSOR_700) ? 1 : 2; 1.1 root 2625: 2626: case TYPE_FPALU: 1.1.1.4 ! root 2627: case TYPE_FPMULSGL: ! 2628: case TYPE_FPMULDBL: 1.1 root 2629: case TYPE_FPDIVSGL: 2630: case TYPE_FPDIVDBL: 2631: case TYPE_FPSQRTSGL: 2632: case TYPE_FPSQRTDBL: 2633: /* In these important cases, we save one cycle compared to 2634: when flop instruction feed each other. */ 1.1.1.4 ! root 2635: return cost - (pa_cpu == PROCESSOR_700) ? 1 : 2; 1.1 root 2636: 2637: default: 2638: return cost; 2639: } 2640: } 2641: } 2642: 2643: /* For other data dependencies, the default cost specified in the 2644: md is correct. */ 2645: return cost; 2646: } 2647: else if (REG_NOTE_KIND (link) == REG_DEP_ANTI) 2648: { 2649: /* Anti dependency; DEP_INSN reads a register that INSN writes some 2650: cycles later. */ 2651: 2652: if (get_attr_type (insn) == TYPE_FPLOAD) 2653: { 2654: rtx pat = PATTERN (insn); 2655: rtx dep_pat = PATTERN (dep_insn); 2656: if (GET_CODE (pat) == PARALLEL) 2657: { 2658: /* This happens for the fldXs,mb patterns. */ 2659: pat = XVECEXP (pat, 0, 0); 2660: } 2661: if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) 2662: /* If this happens, we have to extend this to schedule 2663: optimally. Return 0 for now. */ 2664: return 0; 2665: 2666: if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat))) 2667: { 2668: if (! recog_memoized (dep_insn)) 2669: return 0; 2670: switch (get_attr_type (dep_insn)) 2671: { 2672: case TYPE_FPALU: 1.1.1.4 ! root 2673: case TYPE_FPMULSGL: ! 2674: case TYPE_FPMULDBL: 1.1 root 2675: case TYPE_FPDIVSGL: 2676: case TYPE_FPDIVDBL: 2677: case TYPE_FPSQRTSGL: 2678: case TYPE_FPSQRTDBL: 2679: /* A fpload can't be issued until one cycle before a 1.1.1.4 ! root 2680: preceding arithmetic operation has finished if 1.1 root 2681: the target of the fpload is any of the sources 2682: (or destination) of the arithmetic operation. */ 1.1.1.4 ! root 2683: return cost - (pa_cpu == PROCESSOR_700) ? 1 : 2; ! 2684: ! 2685: default: ! 2686: return 0; ! 2687: } ! 2688: } ! 2689: } ! 2690: else if (get_attr_type (insn) == TYPE_FPALU) ! 2691: { ! 2692: rtx pat = PATTERN (insn); ! 2693: rtx dep_pat = PATTERN (dep_insn); ! 2694: if (GET_CODE (pat) == PARALLEL) ! 2695: { ! 2696: /* This happens for the fldXs,mb patterns. */ ! 2697: pat = XVECEXP (pat, 0, 0); ! 2698: } ! 2699: if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) ! 2700: /* If this happens, we have to extend this to schedule ! 2701: optimally. Return 0 for now. */ ! 2702: return 0; ! 2703: ! 2704: if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat))) ! 2705: { ! 2706: if (! recog_memoized (dep_insn)) ! 2707: return 0; ! 2708: switch (get_attr_type (dep_insn)) ! 2709: { ! 2710: case TYPE_FPDIVSGL: ! 2711: case TYPE_FPDIVDBL: ! 2712: case TYPE_FPSQRTSGL: ! 2713: case TYPE_FPSQRTDBL: ! 2714: /* An ALU flop can't be issued until two cycles before a ! 2715: preceding divide or sqrt operation has finished if ! 2716: the target of the ALU flop is any of the sources ! 2717: (or destination) of the divide or sqrt operation. */ ! 2718: return cost - (pa_cpu == PROCESSOR_700) ? 2 : 4; 1.1 root 2719: 2720: default: 2721: return 0; 2722: } 2723: } 2724: } 2725: 2726: /* For other anti dependencies, the cost is 0. */ 2727: return 0; 2728: } 1.1.1.4 ! root 2729: else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT) ! 2730: { ! 2731: /* Output dependency; DEP_INSN writes a register that INSN writes some ! 2732: cycles later. */ ! 2733: if (get_attr_type (insn) == TYPE_FPLOAD) ! 2734: { ! 2735: rtx pat = PATTERN (insn); ! 2736: rtx dep_pat = PATTERN (dep_insn); ! 2737: if (GET_CODE (pat) == PARALLEL) ! 2738: { ! 2739: /* This happens for the fldXs,mb patterns. */ ! 2740: pat = XVECEXP (pat, 0, 0); ! 2741: } ! 2742: if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) ! 2743: /* If this happens, we have to extend this to schedule ! 2744: optimally. Return 0 for now. */ ! 2745: return 0; ! 2746: ! 2747: if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat))) ! 2748: { ! 2749: if (! recog_memoized (dep_insn)) ! 2750: return 0; ! 2751: switch (get_attr_type (dep_insn)) ! 2752: { ! 2753: case TYPE_FPALU: ! 2754: case TYPE_FPMULSGL: ! 2755: case TYPE_FPMULDBL: ! 2756: case TYPE_FPDIVSGL: ! 2757: case TYPE_FPDIVDBL: ! 2758: case TYPE_FPSQRTSGL: ! 2759: case TYPE_FPSQRTDBL: ! 2760: /* A fpload can't be issued until one cycle before a ! 2761: preceding arithmetic operation has finished if ! 2762: the target of the fpload is the destination of the ! 2763: arithmetic operation. */ ! 2764: return cost - (pa_cpu == PROCESSOR_700) ? 1 : 2; ! 2765: ! 2766: default: ! 2767: return 0; ! 2768: } ! 2769: } ! 2770: } ! 2771: else if (get_attr_type (insn) == TYPE_FPALU) ! 2772: { ! 2773: rtx pat = PATTERN (insn); ! 2774: rtx dep_pat = PATTERN (dep_insn); ! 2775: if (GET_CODE (pat) == PARALLEL) ! 2776: { ! 2777: /* This happens for the fldXs,mb patterns. */ ! 2778: pat = XVECEXP (pat, 0, 0); ! 2779: } ! 2780: if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) ! 2781: /* If this happens, we have to extend this to schedule ! 2782: optimally. Return 0 for now. */ ! 2783: return 0; ! 2784: ! 2785: if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat))) ! 2786: { ! 2787: if (! recog_memoized (dep_insn)) ! 2788: return 0; ! 2789: switch (get_attr_type (dep_insn)) ! 2790: { ! 2791: case TYPE_FPDIVSGL: ! 2792: case TYPE_FPDIVDBL: ! 2793: case TYPE_FPSQRTSGL: ! 2794: case TYPE_FPSQRTDBL: ! 2795: /* An ALU flop can't be issued until two cycles before a ! 2796: preceding divide or sqrt operation has finished if ! 2797: the target of the ALU flop is also the target of ! 2798: of the divide or sqrt operation. */ ! 2799: return cost - (pa_cpu == PROCESSOR_700) ? 2 : 4; ! 2800: ! 2801: default: ! 2802: return 0; ! 2803: } ! 2804: } ! 2805: } 1.1 root 2806: 1.1.1.4 ! root 2807: /* For other output dependencies, the cost is 0. */ ! 2808: return 0; ! 2809: } ! 2810: else ! 2811: abort (); 1.1 root 2812: } 2813: 2814: /* Return any length adjustment needed by INSN which already has its length 1.1.1.3 root 2815: computed as LENGTH. Return zero if no adjustment is necessary. 1.1 root 2816: 1.1.1.2 root 2817: For the PA: function calls, millicode calls, and backwards short 1.1.1.3 root 2818: conditional branches with unfilled delay slots need an adjustment by +1 1.1.1.2 root 2819: (to account for the NOP which will be inserted into the instruction stream). 1.1 root 2820: 2821: Also compute the length of an inline block move here as it is too 1.1.1.2 root 2822: complicated to express as a length attribute in pa.md. */ 1.1 root 2823: int 2824: pa_adjust_insn_length (insn, length) 2825: rtx insn; 2826: int length; 2827: { 2828: rtx pat = PATTERN (insn); 2829: 1.1.1.2 root 2830: /* Call insns which are *not* indirect and have unfilled delay slots. */ 1.1 root 2831: if (GET_CODE (insn) == CALL_INSN) 1.1.1.2 root 2832: { 2833: 2834: if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL 2835: && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF) 2836: return 4; 2837: else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET 2838: && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)) 2839: == SYMBOL_REF) 2840: return 4; 2841: else 2842: return 0; 2843: } 1.1.1.4 ! root 2844: /* Jumps inside switch tables which have unfilled delay slots ! 2845: also need adjustment. */ ! 2846: else if (GET_CODE (insn) == JUMP_INSN ! 2847: && simplejump_p (insn) ! 2848: && GET_MODE (PATTERN (insn)) == DImode) ! 2849: return 4; 1.1 root 2850: /* Millicode insn with an unfilled delay slot. */ 2851: else if (GET_CODE (insn) == INSN 2852: && GET_CODE (pat) != SEQUENCE 2853: && GET_CODE (pat) != USE 2854: && GET_CODE (pat) != CLOBBER 2855: && get_attr_type (insn) == TYPE_MILLI) 1.1.1.2 root 2856: return 4; 1.1 root 2857: /* Block move pattern. */ 2858: else if (GET_CODE (insn) == INSN 2859: && GET_CODE (pat) == PARALLEL 2860: && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM 2861: && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM 2862: && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode 2863: && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode) 1.1.1.2 root 2864: return compute_movstrsi_length (insn) - 4; 1.1 root 2865: /* Conditional branch with an unfilled delay slot. */ 1.1.1.2 root 2866: else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn)) 2867: { 2868: /* Adjust a short backwards conditional with an unfilled delay slot. */ 2869: if (GET_CODE (pat) == SET 2870: && length == 4 2871: && ! forward_branch_p (insn)) 2872: return 4; 2873: /* Adjust dbra insn with short backwards conditional branch with 1.1.1.3 root 2874: unfilled delay slot -- only for case where counter is in a 1.1.1.2 root 2875: general register register. */ 2876: else if (GET_CODE (pat) == PARALLEL 2877: && GET_CODE (XVECEXP (pat, 0, 1)) == SET 2878: && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG 1.1.1.3 root 2879: && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0)) 1.1.1.2 root 2880: && length == 4 2881: && ! forward_branch_p (insn)) 2882: return 4; 2883: else 2884: return 0; 2885: } 1.1 root 2886: else 2887: return 0; 2888: } 2889: 2890: /* Print operand X (an rtx) in assembler syntax to file FILE. 2891: CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. 2892: For `%' followed by punctuation, CODE is the punctuation and X is null. */ 2893: 2894: void 2895: print_operand (file, x, code) 2896: FILE *file; 2897: rtx x; 2898: int code; 2899: { 2900: switch (code) 2901: { 2902: case '#': 2903: /* Output a 'nop' if there's nothing for the delay slot. */ 2904: if (dbr_sequence_length () == 0) 2905: fputs ("\n\tnop", file); 2906: return; 2907: case '*': 2908: /* Output an nullification completer if there's nothing for the */ 1.1.1.3 root 2909: /* delay slot or nullification is requested. */ 1.1 root 2910: if (dbr_sequence_length () == 0 || 2911: (final_sequence && 2912: INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))) 2913: fputs (",n", file); 2914: return; 2915: case 'R': 2916: /* Print out the second register name of a register pair. 2917: I.e., R (6) => 7. */ 2918: fputs (reg_names[REGNO (x)+1], file); 2919: return; 2920: case 'r': 2921: /* A register or zero. */ 2922: if (x == const0_rtx 2923: || (x == CONST0_RTX (DFmode)) 2924: || (x == CONST0_RTX (SFmode))) 2925: { 2926: fputs ("0", file); 2927: return; 2928: } 2929: else 2930: break; 2931: case 'C': /* Plain (C)ondition */ 2932: case 'X': 2933: switch (GET_CODE (x)) 1.1.1.3 root 2934: { 1.1 root 2935: case EQ: 2936: fprintf (file, "="); break; 2937: case NE: 2938: fprintf (file, "<>"); break; 2939: case GT: 2940: fprintf (file, ">"); break; 2941: case GE: 2942: fprintf (file, ">="); break; 2943: case GEU: 2944: fprintf (file, ">>="); break; 2945: case GTU: 2946: fprintf (file, ">>"); break; 2947: case LT: 2948: fprintf (file, "<"); break; 2949: case LE: 2950: fprintf (file, "<="); break; 2951: case LEU: 2952: fprintf (file, "<<="); break; 2953: case LTU: 2954: fprintf (file, "<<"); break; 2955: default: 2956: abort (); 2957: } 2958: return; 2959: case 'N': /* Condition, (N)egated */ 2960: switch (GET_CODE (x)) 2961: { 2962: case EQ: 2963: fprintf (file, "<>"); break; 2964: case NE: 2965: fprintf (file, "="); break; 2966: case GT: 2967: fprintf (file, "<="); break; 2968: case GE: 2969: fprintf (file, "<"); break; 2970: case GEU: 2971: fprintf (file, "<<"); break; 2972: case GTU: 2973: fprintf (file, "<<="); break; 2974: case LT: 2975: fprintf (file, ">="); break; 2976: case LE: 2977: fprintf (file, ">"); break; 2978: case LEU: 2979: fprintf (file, ">>"); break; 2980: case LTU: 2981: fprintf (file, ">>="); break; 2982: default: 2983: abort (); 2984: } 2985: return; 2986: /* For floating point comparisons. Need special conditions to deal 2987: with NaNs properly. */ 2988: case 'Y': 2989: switch (GET_CODE (x)) 2990: { 2991: case EQ: 2992: fprintf (file, "!="); break; 2993: case NE: 2994: fprintf (file, "="); break; 2995: case GT: 2996: fprintf (file, "!>"); break; 2997: case GE: 2998: fprintf (file, "!>="); break; 2999: case LT: 3000: fprintf (file, "!<"); break; 3001: case LE: 3002: fprintf (file, "!<="); break; 3003: default: 3004: abort (); 3005: } 3006: return; 3007: case 'S': /* Condition, operands are (S)wapped. */ 3008: switch (GET_CODE (x)) 3009: { 3010: case EQ: 3011: fprintf (file, "="); break; 3012: case NE: 3013: fprintf (file, "<>"); break; 3014: case GT: 3015: fprintf (file, "<"); break; 3016: case GE: 3017: fprintf (file, "<="); break; 3018: case GEU: 3019: fprintf (file, "<<="); break; 3020: case GTU: 3021: fprintf (file, "<<"); break; 3022: case LT: 3023: fprintf (file, ">"); break; 3024: case LE: 3025: fprintf (file, ">="); break; 3026: case LEU: 3027: fprintf (file, ">>="); break; 3028: case LTU: 3029: fprintf (file, ">>"); break; 3030: default: 3031: abort (); 1.1.1.3 root 3032: } 1.1 root 3033: return; 3034: case 'B': /* Condition, (B)oth swapped and negate. */ 3035: switch (GET_CODE (x)) 3036: { 3037: case EQ: 3038: fprintf (file, "<>"); break; 3039: case NE: 3040: fprintf (file, "="); break; 3041: case GT: 3042: fprintf (file, ">="); break; 3043: case GE: 3044: fprintf (file, ">"); break; 3045: case GEU: 3046: fprintf (file, ">>"); break; 3047: case GTU: 3048: fprintf (file, ">>="); break; 3049: case LT: 3050: fprintf (file, "<="); break; 3051: case LE: 3052: fprintf (file, "<"); break; 3053: case LEU: 3054: fprintf (file, "<<"); break; 3055: case LTU: 3056: fprintf (file, "<<="); break; 3057: default: 3058: abort (); 1.1.1.3 root 3059: } 1.1 root 3060: return; 3061: case 'k': 3062: if (GET_CODE (x) == CONST_INT) 3063: { 3064: fprintf (file, "%d", ~INTVAL (x)); 3065: return; 3066: } 3067: abort(); 3068: case 'L': 3069: if (GET_CODE (x) == CONST_INT) 3070: { 3071: fprintf (file, "%d", 32 - (INTVAL (x) & 31)); 3072: return; 3073: } 3074: abort(); 3075: case 'O': 3076: if (GET_CODE (x) == CONST_INT && exact_log2 (INTVAL (x)) >= 0) 3077: { 3078: fprintf (file, "%d", exact_log2 (INTVAL (x))); 3079: return; 3080: } 3081: abort(); 3082: case 'P': 3083: if (GET_CODE (x) == CONST_INT) 3084: { 3085: fprintf (file, "%d", 31 - (INTVAL (x) & 31)); 3086: return; 3087: } 3088: abort(); 3089: case 'I': 3090: if (GET_CODE (x) == CONST_INT) 3091: fputs ("i", file); 3092: return; 3093: case 'M': 3094: switch (GET_CODE (XEXP (x, 0))) 3095: { 3096: case PRE_DEC: 3097: case PRE_INC: 3098: fprintf (file, "s,mb"); 3099: break; 3100: case POST_DEC: 3101: case POST_INC: 3102: fprintf (file, "s,ma"); 3103: break; 3104: default: 3105: break; 3106: } 3107: return; 3108: case 'F': 3109: switch (GET_CODE (XEXP (x, 0))) 3110: { 3111: case PRE_DEC: 3112: case PRE_INC: 3113: fprintf (file, ",mb"); 3114: break; 3115: case POST_DEC: 3116: case POST_INC: 3117: fprintf (file, ",ma"); 3118: break; 3119: default: 3120: break; 3121: } 3122: return; 3123: case 'G': 3124: output_global_address (file, x); 3125: return; 3126: case 0: /* Don't do anything special */ 3127: break; 3128: case 'Z': 3129: { 3130: unsigned op[3]; 3131: compute_zdepi_operands (INTVAL (x), op); 3132: fprintf (file, "%d,%d,%d", op[0], op[1], op[2]); 3133: return; 3134: } 3135: default: 3136: abort (); 3137: } 3138: if (GET_CODE (x) == REG) 1.1.1.3 root 3139: { 3140: if (FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4 && (REGNO (x) & 1) == 0) 3141: fprintf (file, "%sL", reg_names [REGNO (x)]); 3142: else 3143: fprintf (file, "%s", reg_names [REGNO (x)]); 3144: } 1.1 root 3145: else if (GET_CODE (x) == MEM) 3146: { 3147: int size = GET_MODE_SIZE (GET_MODE (x)); 3148: rtx base = XEXP (XEXP (x, 0), 0); 3149: switch (GET_CODE (XEXP (x, 0))) 3150: { 3151: case PRE_DEC: 3152: case POST_DEC: 3153: fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]); 3154: break; 3155: case PRE_INC: 3156: case POST_INC: 3157: fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]); 3158: break; 3159: default: 3160: output_address (XEXP (x, 0)); 3161: break; 3162: } 3163: } 1.1.1.4 ! root 3164: #if 0 ! 3165: /* The code here is completely wrong. It attempts to extract parts of ! 3166: a CONST_DOUBLE which is wrong since REAL_ARITHMETIC is defined, and it ! 3167: extracts the wrong indices (0 instead of 2 and 1 instead of 3) using ! 3168: the wrong macro (XINT instead of XWINT). ! 3169: Just disable it for now, since the code will never be used anyway! */ 1.1 root 3170: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) 3171: { 3172: union { double d; int i[2]; } u; 3173: union { float f; int i; } u1; 3174: u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1); 3175: u1.f = u.d; 3176: if (code == 'f') 3177: fprintf (file, "0r%.9g", u1.f); 3178: else 3179: fprintf (file, "0x%x", u1.i); 3180: } 1.1.1.3 root 3181: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode) 1.1 root 3182: { 3183: union { double d; int i[2]; } u; 3184: u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1); 3185: fprintf (file, "0r%.20g", u.d); 3186: } 1.1.1.4 ! root 3187: #endif 1.1 root 3188: else 3189: output_addr_const (file, x); 3190: } 3191: 3192: /* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */ 3193: 3194: void 3195: output_global_address (file, x) 3196: FILE *file; 3197: rtx x; 3198: { 3199: 3200: /* Imagine (high (const (plus ...))). */ 3201: if (GET_CODE (x) == HIGH) 3202: x = XEXP (x, 0); 3203: 3204: if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x)) 3205: assemble_name (file, XSTR (x, 0)); 1.1.1.4 ! root 3206: else if (GET_CODE (x) == SYMBOL_REF && !flag_pic) 1.1 root 3207: { 3208: assemble_name (file, XSTR (x, 0)); 3209: fprintf (file, "-$global$"); 3210: } 3211: else if (GET_CODE (x) == CONST) 3212: { 3213: char *sep = ""; 3214: int offset = 0; /* assembler wants -$global$ at end */ 3215: rtx base; 1.1.1.3 root 3216: 1.1 root 3217: if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF) 3218: { 3219: base = XEXP (XEXP (x, 0), 0); 3220: output_addr_const (file, base); 3221: } 3222: else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT) 3223: offset = INTVAL (XEXP (XEXP (x, 0), 0)); 3224: else abort (); 3225: 3226: if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF) 3227: { 3228: base = XEXP (XEXP (x, 0), 1); 3229: output_addr_const (file, base); 3230: } 3231: else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) 3232: offset = INTVAL (XEXP (XEXP (x, 0),1)); 3233: else abort (); 3234: 3235: if (GET_CODE (XEXP (x, 0)) == PLUS) 3236: { 3237: if (offset < 0) 3238: { 3239: offset = -offset; 3240: sep = "-"; 3241: } 3242: else 3243: sep = "+"; 3244: } 3245: else if (GET_CODE (XEXP (x, 0)) == MINUS 3246: && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)) 3247: sep = "-"; 3248: else abort (); 3249: 1.1.1.4 ! root 3250: if (!read_only_operand (base) && !flag_pic) 1.1 root 3251: fprintf (file, "-$global$"); 3252: fprintf (file, "%s", sep); 3253: if (offset) fprintf (file,"%d", offset); 3254: } 3255: else 3256: output_addr_const (file, x); 3257: } 3258: 3259: /* HP's millicode routines mean something special to the assembler. 3260: Keep track of which ones we have used. */ 3261: 3262: enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 }; 3263: static char imported[(int)end1000]; 3264: static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"}; 3265: static char import_string[] = ".IMPORT $$....,MILLICODE"; 3266: #define MILLI_START 10 3267: 1.1.1.2 root 3268: static void 1.1 root 3269: import_milli (code) 3270: enum millicodes code; 3271: { 3272: char str[sizeof (import_string)]; 1.1.1.3 root 3273: 1.1 root 3274: if (!imported[(int)code]) 3275: { 3276: imported[(int)code] = 1; 3277: strcpy (str, import_string); 3278: strncpy (str + MILLI_START, milli_names[(int)code], 4); 3279: output_asm_insn (str, 0); 3280: } 3281: } 3282: 1.1.1.3 root 3283: /* The register constraints have put the operands and return value in 1.1 root 3284: the proper registers. */ 3285: 3286: char * 1.1.1.2 root 3287: output_mul_insn (unsignedp, insn) 1.1 root 3288: int unsignedp; 1.1.1.2 root 3289: rtx insn; 1.1 root 3290: { 1.1.1.4 ! root 3291: import_milli (mulI); ! 3292: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$mulI"), ! 3293: gen_rtx (REG, SImode, 31)); 1.1 root 3294: } 3295: 3296: /* Emit the rtl for doing a division by a constant. */ 3297: 1.1.1.4 ! root 3298: /* Do magic division millicodes exist for this value? */ 1.1 root 3299: static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 3300: 1, 1}; 3301: 1.1.1.3 root 3302: /* We'll use an array to keep track of the magic millicodes and 1.1 root 3303: whether or not we've used them already. [n][0] is signed, [n][1] is 3304: unsigned. */ 3305: 3306: static int div_milli[16][2]; 3307: 3308: int 3309: div_operand (op, mode) 3310: rtx op; 3311: enum machine_mode mode; 3312: { 3313: return (mode == SImode 3314: && ((GET_CODE (op) == REG && REGNO (op) == 25) 3315: || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0 3316: && INTVAL (op) < 16 && magic_milli[INTVAL (op)]))); 3317: } 3318: 3319: int 3320: emit_hpdiv_const (operands, unsignedp) 3321: rtx *operands; 3322: int unsignedp; 3323: { 3324: if (GET_CODE (operands[2]) == CONST_INT 3325: && INTVAL (operands[2]) > 0 3326: && INTVAL (operands[2]) < 16 3327: && magic_milli[INTVAL (operands[2])]) 3328: { 3329: emit_move_insn ( gen_rtx (REG, SImode, 26), operands[1]); 3330: emit 3331: (gen_rtx 3332: (PARALLEL, VOIDmode, 3333: gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29), 3334: gen_rtx (unsignedp ? UDIV : DIV, SImode, 3335: gen_rtx (REG, SImode, 26), 3336: operands[2])), 3337: gen_rtx (CLOBBER, VOIDmode, operands[3]), 3338: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)), 3339: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)), 3340: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31))))); 3341: emit_move_insn (operands[0], gen_rtx (REG, SImode, 29)); 3342: return 1; 3343: } 3344: return 0; 3345: } 3346: 3347: char * 1.1.1.2 root 3348: output_div_insn (operands, unsignedp, insn) 1.1 root 3349: rtx *operands; 3350: int unsignedp; 1.1.1.2 root 3351: rtx insn; 1.1 root 3352: { 3353: int divisor; 1.1.1.3 root 3354: 3355: /* If the divisor is a constant, try to use one of the special 1.1 root 3356: opcodes .*/ 3357: if (GET_CODE (operands[0]) == CONST_INT) 3358: { 1.1.1.2 root 3359: static char buf[100]; 1.1 root 3360: divisor = INTVAL (operands[0]); 3361: if (!div_milli[divisor][unsignedp]) 3362: { 1.1.1.2 root 3363: div_milli[divisor][unsignedp] = 1; 1.1 root 3364: if (unsignedp) 3365: output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands); 3366: else 3367: output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands); 3368: } 3369: if (unsignedp) 1.1.1.2 root 3370: { 3371: sprintf (buf, "$$divU_%d", INTVAL (operands[0])); 3372: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, buf), 3373: gen_rtx (REG, SImode, 31)); 3374: } 3375: else 3376: { 3377: sprintf (buf, "$$divI_%d", INTVAL (operands[0])); 3378: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, buf), 3379: gen_rtx (REG, SImode, 31)); 3380: } 1.1 root 3381: } 3382: /* Divisor isn't a special constant. */ 3383: else 3384: { 3385: if (unsignedp) 3386: { 3387: import_milli (divU); 1.1.1.2 root 3388: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$divU"), 3389: gen_rtx (REG, SImode, 31)); 1.1 root 3390: } 3391: else 3392: { 3393: import_milli (divI); 1.1.1.2 root 3394: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$divI"), 3395: gen_rtx (REG, SImode, 31)); 1.1 root 3396: } 3397: } 3398: } 3399: 3400: /* Output a $$rem millicode to do mod. */ 3401: 3402: char * 1.1.1.2 root 3403: output_mod_insn (unsignedp, insn) 1.1 root 3404: int unsignedp; 1.1.1.2 root 3405: rtx insn; 1.1 root 3406: { 3407: if (unsignedp) 3408: { 3409: import_milli (remU); 1.1.1.2 root 3410: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$remU"), 3411: gen_rtx (REG, SImode, 31)); 1.1 root 3412: } 3413: else 3414: { 3415: import_milli (remI); 1.1.1.2 root 3416: return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$remI"), 3417: gen_rtx (REG, SImode, 31)); 1.1 root 3418: } 3419: } 3420: 3421: void 1.1.1.3 root 3422: output_arg_descriptor (call_insn) 3423: rtx call_insn; 1.1 root 3424: { 3425: char *arg_regs[4]; 3426: enum machine_mode arg_mode; 1.1.1.3 root 3427: rtx link; 1.1 root 3428: int i, output_flag = 0; 3429: int regno; 1.1.1.3 root 3430: 1.1 root 3431: for (i = 0; i < 4; i++) 3432: arg_regs[i] = 0; 3433: 1.1.1.3 root 3434: /* Specify explicitly that no argument relocations should take place 3435: if using the portable runtime calling conventions. */ 3436: if (TARGET_PORTABLE_RUNTIME) 1.1 root 3437: { 1.1.1.3 root 3438: fprintf (asm_out_file, 3439: "\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n"); 3440: return; 3441: } 1.1.1.2 root 3442: 1.1.1.3 root 3443: if (GET_CODE (call_insn) != CALL_INSN) 3444: abort (); 3445: for (link = CALL_INSN_FUNCTION_USAGE (call_insn); link; link = XEXP (link, 1)) 3446: { 3447: rtx use = XEXP (link, 0); 3448: 3449: if (! (GET_CODE (use) == USE 3450: && GET_CODE (XEXP (use, 0)) == REG 3451: && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0))))) 1.1.1.2 root 3452: continue; 3453: 1.1.1.3 root 3454: arg_mode = GET_MODE (XEXP (use, 0)); 3455: regno = REGNO (XEXP (use, 0)); 1.1 root 3456: if (regno >= 23 && regno <= 26) 3457: { 3458: arg_regs[26 - regno] = "GR"; 3459: if (arg_mode == DImode) 3460: arg_regs[25 - regno] = "GR"; 3461: } 1.1.1.3 root 3462: else if (regno >= 32 && regno <= 39) 1.1 root 3463: { 3464: if (arg_mode == SFmode) 1.1.1.3 root 3465: arg_regs[(regno - 32) / 2] = "FR"; 1.1 root 3466: else 3467: { 1.1.1.2 root 3468: #ifndef HP_FP_ARG_DESCRIPTOR_REVERSED 1.1.1.3 root 3469: arg_regs[(regno - 34) / 2] = "FR"; 3470: arg_regs[(regno - 34) / 2 + 1] = "FU"; 1.1 root 3471: #else 1.1.1.3 root 3472: arg_regs[(regno - 34) / 2] = "FU"; 3473: arg_regs[(regno - 34) / 2 + 1] = "FR"; 1.1 root 3474: #endif 3475: } 3476: } 3477: } 3478: fputs ("\t.CALL ", asm_out_file); 3479: for (i = 0; i < 4; i++) 3480: { 3481: if (arg_regs[i]) 3482: { 3483: if (output_flag++) 3484: fputc (',', asm_out_file); 3485: fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]); 3486: } 3487: } 3488: fputc ('\n', asm_out_file); 3489: } 3490: 3491: /* Memory loads/stores to/from the shift need to go through 3492: the general registers. */ 3493: 3494: enum reg_class 3495: secondary_reload_class (class, mode, in) 3496: enum reg_class class; 3497: enum machine_mode mode; 3498: rtx in; 3499: { 3500: int regno = true_regnum (in); 3501: 1.1.1.4 ! root 3502: /* Trying to load a constant into a FP register during PIC code ! 3503: generation will require %r1 as a scratch register. */ ! 3504: if (flag_pic == 2 ! 3505: && GET_MODE_CLASS (mode) == MODE_INT ! 3506: && FP_REG_CLASS_P (class) ! 3507: && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE)) ! 3508: return R1_REGS; ! 3509: 1.1.1.3 root 3510: if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1) 3511: && GET_MODE_CLASS (mode) == MODE_INT 3512: && FP_REG_CLASS_P (class)) 1.1 root 3513: || (class == SHIFT_REGS && (regno <= 0 || regno >= 32))) 3514: return GENERAL_REGS; 3515: 3516: if (GET_CODE (in) == HIGH) 3517: in = XEXP (in, 0); 3518: 1.1.1.4 ! root 3519: if (!flag_pic ! 3520: && symbolic_operand (in, VOIDmode) ! 3521: && read_only_operand (in)) ! 3522: return NO_REGS; ! 3523: 1.1.1.2 root 3524: if (class != R1_REGS && symbolic_operand (in, VOIDmode)) 1.1 root 3525: return R1_REGS; 3526: 1.1.1.3 root 3527: if (GET_CODE (in) == SUBREG) 3528: in = SUBREG_REG (in); 3529: 3530: if (FP_REG_CLASS_P (class) 3531: && GET_CODE (in) == MEM 3532: && !memory_address_p (DFmode, XEXP (in, 0)) 3533: && memory_address_p (SImode, XEXP (in, 0))) 3534: return GENERAL_REGS; 3535: 1.1 root 3536: return NO_REGS; 3537: } 3538: 3539: enum direction 3540: function_arg_padding (mode, type) 3541: enum machine_mode mode; 3542: tree type; 3543: { 3544: int size; 3545: 3546: if (mode == BLKmode) 3547: { 3548: if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) 3549: size = int_size_in_bytes (type) * BITS_PER_UNIT; 3550: else 3551: return upward; /* Don't know if this is right, but */ 3552: /* same as old definition. */ 3553: } 3554: else 3555: size = GET_MODE_BITSIZE (mode); 3556: if (size < PARM_BOUNDARY) 3557: return downward; 3558: else if (size % PARM_BOUNDARY) 3559: return upward; 3560: else 3561: return none; 3562: } 3563: 3564: 3565: /* Do what is necessary for `va_start'. The argument is ignored; 3566: We look at the current function to determine if stdargs or varargs 3567: is used and fill in an initial va_list. A pointer to this constructor 3568: is returned. */ 3569: 3570: struct rtx_def * 3571: hppa_builtin_saveregs (arglist) 3572: tree arglist; 3573: { 1.1.1.2 root 3574: rtx offset; 1.1 root 3575: tree fntype = TREE_TYPE (current_function_decl); 3576: int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0 3577: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 3578: != void_type_node))) 3579: ? UNITS_PER_WORD : 0); 3580: 3581: if (argadj) 3582: offset = plus_constant (current_function_arg_offset_rtx, argadj); 3583: else 3584: offset = current_function_arg_offset_rtx; 3585: 3586: /* Store general registers on the stack. */ 3587: move_block_from_reg (23, 3588: gen_rtx (MEM, BLKmode, 3589: plus_constant 3590: (current_function_internal_arg_pointer, -16)), 1.1.1.3 root 3591: 4, 4 * UNITS_PER_WORD); 1.1 root 3592: return copy_to_reg (expand_binop (Pmode, add_optab, 3593: current_function_internal_arg_pointer, 3594: offset, 0, 0, OPTAB_LIB_WIDEN)); 3595: } 3596: 1.1.1.3 root 3597: /* This routine handles all the normal conditional branch sequences we 3598: might need to generate. It handles compare immediate vs compare 3599: register, nullification of delay slots, varying length branches, 1.1 root 3600: negated branches, and all combinations of the above. It returns the 1.1.1.3 root 3601: output appropriate to emit the branch corresponding to all given 1.1 root 3602: parameters. */ 3603: 3604: char * 3605: output_cbranch (operands, nullify, length, negated, insn) 3606: rtx *operands; 3607: int nullify, length, negated; 3608: rtx insn; 1.1.1.2 root 3609: { 1.1 root 3610: static char buf[100]; 3611: int useskip = 0; 3612: 1.1.1.2 root 3613: /* A conditional branch to the following instruction (eg the delay slot) is 3614: asking for a disaster. This can happen when not optimizing. 3615: 3616: In such cases it is safe to emit nothing. */ 3617: 1.1.1.4 ! root 3618: if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) 1.1.1.2 root 3619: return ""; 1.1.1.3 root 3620: 1.1.1.2 root 3621: /* If this is a long branch with its delay slot unfilled, set `nullify' 3622: as it can nullify the delay slot and save a nop. */ 3623: if (length == 8 && dbr_sequence_length () == 0) 3624: nullify = 1; 3625: 3626: /* If this is a short forward conditional branch which did not get 3627: its delay slot filled, the delay slot can still be nullified. */ 3628: if (! nullify && length == 4 && dbr_sequence_length () == 0) 3629: nullify = forward_branch_p (insn); 3630: 1.1.1.3 root 3631: /* A forward branch over a single nullified insn can be done with a 1.1 root 3632: comclr instruction. This avoids a single cycle penalty due to 3633: mis-predicted branch if we fall through (branch not taken). */ 1.1.1.2 root 3634: if (length == 4 3635: && next_real_insn (insn) != 0 3636: && get_attr_length (next_real_insn (insn)) == 4 3637: && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn)) 1.1 root 3638: && nullify) 3639: useskip = 1; 3640: 3641: switch (length) 3642: { 1.1.1.2 root 3643: /* All short conditional branches except backwards with an unfilled 3644: delay slot. */ 3645: case 4: 1.1 root 3646: if (useskip) 3647: strcpy (buf, "com%I2clr,"); 3648: else 3649: strcpy (buf, "com%I2b,"); 3650: if (negated) 3651: strcat (buf, "%B3"); 3652: else 3653: strcat (buf, "%S3"); 3654: if (useskip) 3655: strcat (buf, " %2,%1,0"); 3656: else if (nullify) 3657: strcat (buf, ",n %2,%1,%0"); 1.1.1.3 root 3658: else 1.1.1.2 root 3659: strcat (buf, " %2,%1,%0"); 1.1 root 3660: break; 3661: 1.1.1.3 root 3662: /* All long conditionals. Note an short backward branch with an 1.1.1.2 root 3663: unfilled delay slot is treated just like a long backward branch 3664: with an unfilled delay slot. */ 3665: case 8: 3666: /* Handle weird backwards branch with a filled delay slot 3667: with is nullified. */ 3668: if (dbr_sequence_length () != 0 3669: && ! forward_branch_p (insn) 3670: && nullify) 3671: { 3672: strcpy (buf, "com%I2b,"); 3673: if (negated) 3674: strcat (buf, "%S3"); 3675: else 3676: strcat (buf, "%B3"); 3677: strcat (buf, ",n %2,%1,.+12\n\tbl %0,0"); 3678: } 1.1.1.4 ! root 3679: /* Handle short backwards branch with an unfilled delay slot. ! 3680: Using a comb;nop rather than comiclr;bl saves 1 cycle for both ! 3681: taken and untaken branches. */ ! 3682: else if (dbr_sequence_length () == 0 ! 3683: && ! forward_branch_p (insn) ! 3684: && insn_addresses ! 3685: && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] ! 3686: - insn_addresses[INSN_UID (insn)])) ! 3687: { ! 3688: strcpy (buf, "com%I2b,"); ! 3689: if (negated) ! 3690: strcat (buf, "%B3 %2,%1,%0%#"); ! 3691: else ! 3692: strcat (buf, "%S3 %2,%1,%0%#"); ! 3693: } 1.1 root 3694: else 1.1.1.2 root 3695: { 3696: strcpy (buf, "com%I2clr,"); 3697: if (negated) 3698: strcat (buf, "%S3"); 3699: else 3700: strcat (buf, "%B3"); 3701: if (nullify) 3702: strcat (buf, " %2,%1,0\n\tbl,n %0,0"); 3703: else 3704: strcat (buf, " %2,%1,0\n\tbl %0,0"); 3705: } 1.1 root 3706: break; 3707: 3708: default: 3709: abort(); 1.1.1.2 root 3710: } 1.1 root 3711: return buf; 3712: } 3713: 1.1.1.3 root 3714: /* This routine handles all the branch-on-bit conditional branch sequences we 1.1 root 3715: might need to generate. It handles nullification of delay slots, 3716: varying length branches, negated branches and all combinations of the 3717: above. it returns the appropriate output template to emit the branch. */ 3718: 3719: char * 3720: output_bb (operands, nullify, length, negated, insn, which) 3721: rtx *operands; 3722: int nullify, length, negated; 3723: rtx insn; 3724: int which; 1.1.1.2 root 3725: { 1.1 root 3726: static char buf[100]; 3727: int useskip = 0; 3728: 1.1.1.2 root 3729: /* A conditional branch to the following instruction (eg the delay slot) is 3730: asking for a disaster. I do not think this can happen as this pattern 1.1.1.3 root 3731: is only used when optimizing; jump optimization should eliminate the 1.1.1.2 root 3732: jump. But be prepared just in case. */ 1.1.1.3 root 3733: 1.1.1.4 ! root 3734: if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) 1.1.1.2 root 3735: return ""; 1.1.1.3 root 3736: 1.1.1.2 root 3737: /* If this is a long branch with its delay slot unfilled, set `nullify' 3738: as it can nullify the delay slot and save a nop. */ 3739: if (length == 8 && dbr_sequence_length () == 0) 3740: nullify = 1; 3741: 3742: /* If this is a short forward conditional branch which did not get 3743: its delay slot filled, the delay slot can still be nullified. */ 3744: if (! nullify && length == 4 && dbr_sequence_length () == 0) 3745: nullify = forward_branch_p (insn); 3746: 1.1.1.3 root 3747: /* A forward branch over a single nullified insn can be done with a 1.1 root 3748: extrs instruction. This avoids a single cycle penalty due to 3749: mis-predicted branch if we fall through (branch not taken). */ 3750: 1.1.1.2 root 3751: if (length == 4 3752: && next_real_insn (insn) != 0 3753: && get_attr_length (next_real_insn (insn)) == 4 3754: && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn)) 1.1 root 3755: && nullify) 3756: useskip = 1; 3757: 3758: switch (length) 3759: { 3760: 1.1.1.2 root 3761: /* All short conditional branches except backwards with an unfilled 3762: delay slot. */ 3763: case 4: 1.1 root 3764: if (useskip) 3765: strcpy (buf, "extrs,"); 1.1.1.3 root 3766: else 1.1 root 3767: strcpy (buf, "bb,"); 3768: if ((which == 0 && negated) 3769: || (which == 1 && ! negated)) 3770: strcat (buf, ">="); 3771: else 3772: strcat (buf, "<"); 3773: if (useskip) 3774: strcat (buf, " %0,%1,1,0"); 3775: else if (nullify && negated) 3776: strcat (buf, ",n %0,%1,%3"); 3777: else if (nullify && ! negated) 3778: strcat (buf, ",n %0,%1,%2"); 3779: else if (! nullify && negated) 1.1.1.2 root 3780: strcat (buf, "%0,%1,%3"); 1.1 root 3781: else if (! nullify && ! negated) 1.1.1.2 root 3782: strcat (buf, " %0,%1,%2"); 1.1 root 3783: break; 3784: 1.1.1.3 root 3785: /* All long conditionals. Note an short backward branch with an 1.1.1.2 root 3786: unfilled delay slot is treated just like a long backward branch 3787: with an unfilled delay slot. */ 3788: case 8: 3789: /* Handle weird backwards branch with a filled delay slot 3790: with is nullified. */ 3791: if (dbr_sequence_length () != 0 3792: && ! forward_branch_p (insn) 3793: && nullify) 3794: { 3795: strcpy (buf, "bb,"); 3796: if ((which == 0 && negated) 3797: || (which == 1 && ! negated)) 3798: strcat (buf, "<"); 3799: else 3800: strcat (buf, ">="); 3801: if (negated) 1.1.1.4 ! root 3802: strcat (buf, ",n %0,%1,.+12\n\tbl %3,0"); 1.1.1.2 root 3803: else 1.1.1.4 ! root 3804: strcat (buf, ",n %0,%1,.+12\n\tbl %2,0"); ! 3805: } ! 3806: /* Handle short backwards branch with an unfilled delay slot. ! 3807: Using a bb;nop rather than extrs;bl saves 1 cycle for both ! 3808: taken and untaken branches. */ ! 3809: else if (dbr_sequence_length () == 0 ! 3810: && ! forward_branch_p (insn) ! 3811: && insn_addresses ! 3812: && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] ! 3813: - insn_addresses[INSN_UID (insn)])) ! 3814: { ! 3815: strcpy (buf, "bb,"); ! 3816: if ((which == 0 && negated) ! 3817: || (which == 1 && ! negated)) ! 3818: strcat (buf, ">="); ! 3819: else ! 3820: strcat (buf, "<"); ! 3821: if (negated) ! 3822: strcat (buf, " %0,%1,%3%#"); ! 3823: else ! 3824: strcat (buf, " %0,%1,%2%#"); 1.1.1.2 root 3825: } 1.1 root 3826: else 1.1.1.2 root 3827: { 3828: strcpy (buf, "extrs,"); 3829: if ((which == 0 && negated) 3830: || (which == 1 && ! negated)) 3831: strcat (buf, "<"); 3832: else 3833: strcat (buf, ">="); 3834: if (nullify && negated) 3835: strcat (buf, " %0,%1,1,0\n\tbl,n %3,0"); 3836: else if (nullify && ! negated) 3837: strcat (buf, " %0,%1,1,0\n\tbl,n %2,0"); 3838: else if (negated) 3839: strcat (buf, " %0,%1,1,0\n\tbl %3,0"); 1.1.1.3 root 3840: else 1.1.1.2 root 3841: strcat (buf, " %0,%1,1,0\n\tbl %2,0"); 3842: } 1.1 root 3843: break; 3844: 3845: default: 3846: abort(); 1.1.1.2 root 3847: } 1.1 root 3848: return buf; 3849: } 3850: 1.1.1.2 root 3851: /* Return the output template for emitting a dbra type insn. 3852: 3853: Note it may perform some output operations on its own before 3854: returning the final output string. */ 3855: char * 3856: output_dbra (operands, insn, which_alternative) 3857: rtx *operands; 3858: rtx insn; 3859: int which_alternative; 3860: { 3861: 3862: /* A conditional branch to the following instruction (eg the delay slot) is 3863: asking for a disaster. Be prepared! */ 3864: 1.1.1.4 ! root 3865: if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) 1.1.1.2 root 3866: { 3867: if (which_alternative == 0) 3868: return "ldo %1(%0),%0"; 3869: else if (which_alternative == 1) 3870: { 3871: output_asm_insn ("fstws %0,-16(0,%%r30)",operands); 3872: output_asm_insn ("ldw -16(0,%%r30),%4",operands); 3873: output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands); 3874: return "fldws -16(0,%%r30),%0"; 3875: } 3876: else 3877: { 3878: output_asm_insn ("ldw %0,%4", operands); 3879: return "ldo %1(%4),%4\n\tstw %4,%0"; 3880: } 3881: } 3882: 3883: if (which_alternative == 0) 3884: { 3885: int nullify = INSN_ANNULLED_BRANCH_P (insn); 3886: int length = get_attr_length (insn); 3887: 3888: /* If this is a long branch with its delay slot unfilled, set `nullify' 3889: as it can nullify the delay slot and save a nop. */ 3890: if (length == 8 && dbr_sequence_length () == 0) 3891: nullify = 1; 3892: 3893: /* If this is a short forward conditional branch which did not get 3894: its delay slot filled, the delay slot can still be nullified. */ 3895: if (! nullify && length == 4 && dbr_sequence_length () == 0) 3896: nullify = forward_branch_p (insn); 3897: 3898: /* Handle short versions first. */ 3899: if (length == 4 && nullify) 3900: return "addib,%C2,n %1,%0,%3"; 3901: else if (length == 4 && ! nullify) 3902: return "addib,%C2 %1,%0,%3"; 3903: else if (length == 8) 3904: { 1.1.1.3 root 3905: /* Handle weird backwards branch with a fulled delay slot 1.1.1.2 root 3906: which is nullified. */ 3907: if (dbr_sequence_length () != 0 3908: && ! forward_branch_p (insn) 3909: && nullify) 3910: return "addib,%N2,n %1,%0,.+12\n\tbl %3,0"; 1.1.1.4 ! root 3911: /* Handle short backwards branch with an unfilled delay slot. ! 3912: Using a addb;nop rather than addi;bl saves 1 cycle for both ! 3913: taken and untaken branches. */ ! 3914: else if (dbr_sequence_length () == 0 ! 3915: && ! forward_branch_p (insn) ! 3916: && insn_addresses ! 3917: && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] ! 3918: - insn_addresses[INSN_UID (insn)])) ! 3919: return "addib,%C2 %1,%0,%3%#"; 1.1.1.3 root 3920: 3921: /* Handle normal cases. */ 1.1.1.2 root 3922: if (nullify) 3923: return "addi,%N2 %1,%0,%0\n\tbl,n %3,0"; 3924: else 3925: return "addi,%N2 %1,%0,%0\n\tbl %3,0"; 3926: } 3927: else 3928: abort(); 3929: } 3930: /* Deal with gross reload from FP register case. */ 3931: else if (which_alternative == 1) 3932: { 3933: /* Move loop counter from FP register to MEM then into a GR, 3934: increment the GR, store the GR into MEM, and finally reload 1.1.1.3 root 3935: the FP register from MEM from within the branch's delay slot. */ 1.1.1.2 root 3936: output_asm_insn ("fstws %0,-16(0,%%r30)\n\tldw -16(0,%%r30),%4",operands); 3937: output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands); 3938: if (get_attr_length (insn) == 24) 3939: return "comb,%S2 0,%4,%3\n\tfldws -16(0,%%r30),%0"; 3940: else 3941: return "comclr,%B2 0,%4,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0"; 3942: } 3943: /* Deal with gross reload from memory case. */ 3944: else 3945: { 3946: /* Reload loop counter from memory, the store back to memory 3947: happens in the branch's delay slot. */ 3948: output_asm_insn ("ldw %0,%4", operands); 3949: if (get_attr_length (insn) == 12) 3950: return "addib,%C2 %1,%4,%3\n\tstw %4,%0"; 3951: else 3952: return "addi,%N2 %1,%4,%4\n\tbl %3,0\n\tstw %4,%0"; 3953: } 3954: } 3955: 3956: /* Return the output template for emitting a dbra type insn. 3957: 3958: Note it may perform some output operations on its own before 3959: returning the final output string. */ 3960: char * 3961: output_movb (operands, insn, which_alternative, reverse_comparison) 3962: rtx *operands; 3963: rtx insn; 3964: int which_alternative; 3965: int reverse_comparison; 3966: { 3967: 3968: /* A conditional branch to the following instruction (eg the delay slot) is 3969: asking for a disaster. Be prepared! */ 3970: 1.1.1.4 ! root 3971: if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) 1.1.1.2 root 3972: { 3973: if (which_alternative == 0) 3974: return "copy %1,%0"; 3975: else if (which_alternative == 1) 3976: { 3977: output_asm_insn ("stw %1,-16(0,%%r30)",operands); 3978: return "fldws -16(0,%%r30),%0"; 3979: } 3980: else 3981: return "stw %1,%0"; 3982: } 3983: 3984: /* Support the second variant. */ 3985: if (reverse_comparison) 3986: PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2]))); 3987: 3988: if (which_alternative == 0) 3989: { 3990: int nullify = INSN_ANNULLED_BRANCH_P (insn); 3991: int length = get_attr_length (insn); 3992: 3993: /* If this is a long branch with its delay slot unfilled, set `nullify' 3994: as it can nullify the delay slot and save a nop. */ 3995: if (length == 8 && dbr_sequence_length () == 0) 3996: nullify = 1; 3997: 3998: /* If this is a short forward conditional branch which did not get 3999: its delay slot filled, the delay slot can still be nullified. */ 4000: if (! nullify && length == 4 && dbr_sequence_length () == 0) 4001: nullify = forward_branch_p (insn); 4002: 4003: /* Handle short versions first. */ 4004: if (length == 4 && nullify) 4005: return "movb,%C2,n %1,%0,%3"; 4006: else if (length == 4 && ! nullify) 4007: return "movb,%C2 %1,%0,%3"; 4008: else if (length == 8) 4009: { 1.1.1.3 root 4010: /* Handle weird backwards branch with a filled delay slot 1.1.1.2 root 4011: which is nullified. */ 4012: if (dbr_sequence_length () != 0 4013: && ! forward_branch_p (insn) 4014: && nullify) 1.1.1.4 ! root 4015: return "movb,%N2,n %1,%0,.+12\n\tbl %3,0"; 1.1.1.3 root 4016: 1.1.1.4 ! root 4017: /* Handle short backwards branch with an unfilled delay slot. ! 4018: Using a movb;nop rather than or;bl saves 1 cycle for both ! 4019: taken and untaken branches. */ ! 4020: else if (dbr_sequence_length () == 0 ! 4021: && ! forward_branch_p (insn) ! 4022: && insn_addresses ! 4023: && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] ! 4024: - insn_addresses[INSN_UID (insn)])) ! 4025: return "movb,%C2 %1,%0,%3%#"; 1.1.1.3 root 4026: /* Handle normal cases. */ 1.1.1.2 root 4027: if (nullify) 4028: return "or,%N2 %1,%%r0,%0\n\tbl,n %3,0"; 4029: else 4030: return "or,%N2 %1,%%r0,%0\n\tbl %3,0"; 4031: } 4032: else 4033: abort(); 4034: } 4035: /* Deal with gross reload from FP register case. */ 4036: else if (which_alternative == 1) 4037: { 4038: /* Move loop counter from FP register to MEM then into a GR, 4039: increment the GR, store the GR into MEM, and finally reload 1.1.1.3 root 4040: the FP register from MEM from within the branch's delay slot. */ 1.1.1.2 root 4041: output_asm_insn ("stw %1,-16(0,%%r30)",operands); 4042: if (get_attr_length (insn) == 12) 4043: return "comb,%S2 0,%1,%3\n\tfldws -16(0,%%r30),%0"; 4044: else 4045: return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0"; 4046: } 4047: /* Deal with gross reload from memory case. */ 4048: else 4049: { 4050: /* Reload loop counter from memory, the store back to memory 4051: happens in the branch's delay slot. */ 4052: if (get_attr_length (insn) == 8) 4053: return "comb,%S2 0,%1,%3\n\tstw %1,%0"; 4054: else 4055: return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tstw %1,%0"; 4056: } 4057: } 4058: 4059: 4060: /* INSN is either a function call or a millicode call. It may have an 1.1.1.3 root 4061: unconditional jump in its delay slot. 1.1.1.2 root 4062: 4063: CALL_DEST is the routine we are calling. 4064: 4065: RETURN_POINTER is the register which will hold the return address. 1.1.1.3 root 4066: %r2 for most calls, %r31 for millicode calls. 4067: 1.1.1.4 ! root 4068: When TARGET_MILLICODE_LONG_CALLS is true, then we have to assume ! 4069: that two instruction sequences must be used to reach the millicode ! 4070: routines (including dyncall!). */ 1.1.1.3 root 4071: 1.1.1.2 root 4072: char * 4073: output_call (insn, call_dest, return_pointer) 4074: rtx insn; 4075: rtx call_dest; 4076: rtx return_pointer; 4077: 4078: { 4079: int distance; 4080: rtx xoperands[4]; 4081: rtx seq_insn; 4082: 1.1.1.4 ! root 4083: /* Handle long millicode calls for mod, div, and mul. */ ! 4084: if (TARGET_PORTABLE_RUNTIME ! 4085: || (TARGET_MILLICODE_LONG_CALLS && REGNO (return_pointer) == 31)) ! 4086: { ! 4087: xoperands[0] = call_dest; ! 4088: xoperands[1] = return_pointer; ! 4089: output_asm_insn ("ldil L%%%0,%%r29", xoperands); ! 4090: output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands); ! 4091: output_asm_insn ("blr 0,%r1\n\tbv,n 0(%%r29)\n\tnop", xoperands); ! 4092: return ""; ! 4093: } ! 4094: ! 4095: /* Handle common case -- empty delay slot or no jump in the delay slot, ! 4096: and we're sure that the branch will reach the beginning of the $CODE$ ! 4097: subspace. */ ! 4098: if ((dbr_sequence_length () == 0 ! 4099: && get_attr_length (insn) == 8) 1.1.1.3 root 4100: || (dbr_sequence_length () != 0 1.1.1.4 ! root 4101: && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN ! 4102: && get_attr_length (insn) == 4)) 1.1.1.2 root 4103: { 4104: xoperands[0] = call_dest; 4105: xoperands[1] = return_pointer; 1.1.1.4 ! root 4106: output_asm_insn ("bl %0,%r1%#", xoperands); ! 4107: return ""; ! 4108: } ! 4109: ! 4110: /* This call may not reach the beginning of the $CODE$ subspace. */ ! 4111: if (get_attr_length (insn) > 8) ! 4112: { ! 4113: int delay_insn_deleted = 0; ! 4114: rtx xoperands[2]; ! 4115: rtx link; ! 4116: ! 4117: /* We need to emit an inline long-call branch. Furthermore, ! 4118: because we're changing a named function call into an indirect ! 4119: function call well after the parameters have been set up, we ! 4120: need to make sure any FP args appear in both the integer ! 4121: and FP registers. Also, we need move any delay slot insn ! 4122: out of the delay slot -- Yuk! */ ! 4123: if (dbr_sequence_length () != 0 ! 4124: && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN) ! 4125: { ! 4126: /* A non-jump insn in the delay slot. By definition we can ! 4127: emit this insn before the call (and in fact before argument ! 4128: relocating. */ ! 4129: final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0); ! 4130: ! 4131: /* Now delete the delay insn. */ ! 4132: PUT_CODE (NEXT_INSN (insn), NOTE); ! 4133: NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; ! 4134: NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; ! 4135: delay_insn_deleted = 1; ! 4136: } ! 4137: ! 4138: /* Now copy any FP arguments into integer registers. */ ! 4139: for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) ! 4140: { ! 4141: int arg_mode, regno; ! 4142: rtx use = XEXP (link, 0); ! 4143: if (! (GET_CODE (use) == USE ! 4144: && GET_CODE (XEXP (use, 0)) == REG ! 4145: && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0))))) ! 4146: continue; ! 4147: ! 4148: arg_mode = GET_MODE (XEXP (use, 0)); ! 4149: regno = REGNO (XEXP (use, 0)); ! 4150: /* Is it a floating point register? */ ! 4151: if (regno >= 32 && regno <= 39) ! 4152: { ! 4153: /* Copy from the FP register into an integer register ! 4154: (via memory). */ ! 4155: if (arg_mode == SFmode) ! 4156: { ! 4157: xoperands[0] = XEXP (use, 0); ! 4158: xoperands[1] = gen_rtx (REG, SImode, 26 - (regno - 32) / 2); ! 4159: output_asm_insn ("fstws %0,-16(%%sr0,%%r30)", xoperands); ! 4160: output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands); ! 4161: } ! 4162: else ! 4163: { ! 4164: xoperands[0] = XEXP (use, 0); ! 4165: xoperands[1] = gen_rtx (REG, DImode, 25 - (regno - 34) / 2); ! 4166: output_asm_insn ("fstds %0,-16(%%sr0,%%r30)", xoperands); ! 4167: output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands); ! 4168: output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands); ! 4169: } ! 4170: ! 4171: } ! 4172: } ! 4173: ! 4174: if (flag_pic) 1.1.1.3 root 4175: { 1.1.1.4 ! root 4176: /* We have to load the address of the function using a procedure ! 4177: label (plabel). The LP and RP relocs don't work reliably for PIC, ! 4178: so we make a plain 32 bit plabel in the data segment instead. We ! 4179: have to defer outputting it of course... Not pretty. */ ! 4180: ! 4181: xoperands[0] = gen_label_rtx (); ! 4182: output_asm_insn ("addil LT%%%0,%%r19\n\tldw RT%%%0(%%r1),%%r22", ! 4183: xoperands); ! 4184: output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands); ! 4185: ! 4186: if (deferred_plabels == 0) ! 4187: deferred_plabels = (struct defer_plab *) ! 4188: xmalloc (1 * sizeof (struct defer_plab)); ! 4189: else ! 4190: deferred_plabels = (struct defer_plab *) ! 4191: xrealloc (deferred_plabels, ! 4192: (n_deferred_plabels + 1) * sizeof (struct defer_plab)); ! 4193: deferred_plabels[n_deferred_plabels].internal_label = xoperands[0]; ! 4194: deferred_plabels[n_deferred_plabels].symbol = call_dest; ! 4195: n_deferred_plabels++; ! 4196: } ! 4197: else ! 4198: { ! 4199: /* Now emit the inline long-call. */ ! 4200: xoperands[0] = call_dest; ! 4201: output_asm_insn ("ldil LP%%%0,%%r22\n\tldo RP%%%0(%%r22),%%r22", ! 4202: xoperands); ! 4203: } ! 4204: ! 4205: /* If TARGET_MILLICODE_LONG_CALLS, then we must use a long-call sequence ! 4206: to call dyncall! */ ! 4207: if (TARGET_MILLICODE_LONG_CALLS) ! 4208: { ! 4209: output_asm_insn ("ldil L%%$$dyncall,%%r31", xoperands); ! 4210: output_asm_insn ("ldo R%%$$dyncall(%%r31),%%r31", xoperands); ! 4211: output_asm_insn ("blr 0,%%r2\n\tbv,n 0(%%r31)\n\tnop", xoperands); 1.1.1.3 root 4212: } 4213: else 1.1.1.4 ! root 4214: output_asm_insn ("bl $$dyncall,%%r31\n\tcopy %%r31,%%r2", xoperands); ! 4215: ! 4216: /* If we had a jump in the call's delay slot, output it now. */ ! 4217: if (dbr_sequence_length () != 0 ! 4218: && !delay_insn_deleted) ! 4219: { ! 4220: xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1); ! 4221: output_asm_insn ("b,n %0", xoperands); ! 4222: ! 4223: /* Now delete the delay insn. */ ! 4224: PUT_CODE (NEXT_INSN (insn), NOTE); ! 4225: NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; ! 4226: NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; ! 4227: } 1.1.1.2 root 4228: return ""; 4229: } 1.1.1.3 root 4230: 1.1.1.2 root 4231: /* This call has an unconditional jump in its delay slot. */ 4232: 4233: /* Use the containing sequence insn's address. */ 4234: seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); 4235: 1.1.1.3 root 4236: distance = insn_addresses[INSN_UID (JUMP_LABEL (NEXT_INSN (insn)))] 1.1.1.2 root 4237: - insn_addresses[INSN_UID (seq_insn)] - 8; 4238: 4239: /* If the branch was too far away, emit a normal call followed 4240: by a nop, followed by the unconditional branch. 4241: 1.1.1.3 root 4242: If the branch is close, then adjust %r2 from within the 1.1.1.2 root 4243: call's delay slot. */ 4244: 4245: xoperands[0] = call_dest; 4246: xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1); 4247: xoperands[2] = return_pointer; 4248: if (! VAL_14_BITS_P (distance)) 4249: output_asm_insn ("bl %0,%r2\n\tnop\n\tbl,n %1,%%r0", xoperands); 4250: else 4251: { 4252: xoperands[3] = gen_label_rtx (); 1.1.1.3 root 4253: output_asm_insn ("\n\tbl %0,%r2\n\tldo %1-%3(%r2),%r2", xoperands); 4254: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", 1.1.1.2 root 4255: CODE_LABEL_NUMBER (xoperands[3])); 4256: } 4257: 4258: /* Delete the jump. */ 4259: PUT_CODE (NEXT_INSN (insn), NOTE); 4260: NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; 4261: NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; 4262: return ""; 4263: } 4264: 1.1.1.4 ! root 4265: extern struct obstack permanent_obstack; 1.1 root 4266: extern struct obstack *saveable_obstack; 4267: 4268: /* In HPUX 8.0's shared library scheme, special relocations are needed 1.1.1.3 root 4269: for function labels if they might be passed to a function 1.1 root 4270: in a shared library (because shared libraries don't live in code 1.1.1.4 ! root 4271: space), and special magic is needed to construct their address. ! 4272: ! 4273: For reasons too disgusting to describe storage for the new name ! 4274: is allocated either on the saveable_obstack (released at function ! 4275: exit) or on the permanent_obstack for things that can never change ! 4276: (libcall names for example). */ 1.1 root 4277: 4278: void 1.1.1.4 ! root 4279: hppa_encode_label (sym, permanent) 1.1 root 4280: rtx sym; 1.1.1.4 ! root 4281: int permanent; 1.1 root 4282: { 4283: char *str = XSTR (sym, 0); 4284: int len = strlen (str); 1.1.1.4 ! root 4285: char *newstr; ! 4286: ! 4287: newstr = obstack_alloc ((permanent ? &permanent_obstack : saveable_obstack), ! 4288: len + 2); 1.1 root 4289: 4290: if (str[0] == '*') 4291: *newstr++ = *str++; 4292: strcpy (newstr + 1, str); 4293: *newstr = '@'; 4294: XSTR (sym,0) = newstr; 4295: } 1.1.1.3 root 4296: 1.1 root 4297: int 1.1.1.3 root 4298: function_label_operand (op, mode) 1.1 root 4299: rtx op; 4300: enum machine_mode mode; 4301: { 4302: return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0)); 4303: } 4304: 1.1.1.3 root 4305: /* Returns 1 if OP is a function label involved in a simple addition 4306: with a constant. Used to keep certain patterns from matching 4307: during instruction combination. */ 4308: int 4309: is_function_label_plus_const (op) 4310: rtx op; 4311: { 4312: /* Strip off any CONST. */ 4313: if (GET_CODE (op) == CONST) 4314: op = XEXP (op, 0); 4315: 4316: return (GET_CODE (op) == PLUS 4317: && function_label_operand (XEXP (op, 0), Pmode) 4318: && GET_CODE (XEXP (op, 1)) == CONST_INT); 4319: } 4320: 1.1 root 4321: /* Returns 1 if the 6 operands specified in OPERANDS are suitable for 4322: use in fmpyadd instructions. */ 4323: int 1.1.1.3 root 4324: fmpyaddoperands (operands) 1.1 root 4325: rtx *operands; 4326: { 4327: enum machine_mode mode = GET_MODE (operands[0]); 4328: 4329: /* All modes must be the same. */ 4330: if (! (mode == GET_MODE (operands[1]) 4331: && mode == GET_MODE (operands[2]) 4332: && mode == GET_MODE (operands[3]) 4333: && mode == GET_MODE (operands[4]) 4334: && mode == GET_MODE (operands[5]))) 4335: return 0; 4336: 4337: /* Both DFmode and SFmode should work. But using SFmode makes the 4338: assembler complain. Just turn it off for now. */ 4339: if (mode != DFmode) 4340: return 0; 4341: 4342: /* Only 2 real operands to the addition. One of the input operands must 4343: be the same as the output operand. */ 4344: if (! rtx_equal_p (operands[3], operands[4]) 4345: && ! rtx_equal_p (operands[3], operands[5])) 4346: return 0; 4347: 4348: /* Inout operand of add can not conflict with any operands from multiply. */ 4349: if (rtx_equal_p (operands[3], operands[0]) 4350: || rtx_equal_p (operands[3], operands[1]) 4351: || rtx_equal_p (operands[3], operands[2])) 4352: return 0; 4353: 4354: /* multiply can not feed into addition operands. */ 4355: if (rtx_equal_p (operands[4], operands[0]) 4356: || rtx_equal_p (operands[5], operands[0])) 4357: return 0; 4358: 4359: /* Passed. Operands are suitable for fmpyadd. */ 4360: return 1; 4361: } 4362: 4363: /* Returns 1 if the 6 operands specified in OPERANDS are suitable for 4364: use in fmpysub instructions. */ 4365: int 1.1.1.3 root 4366: fmpysuboperands (operands) 1.1 root 4367: rtx *operands; 4368: { 4369: enum machine_mode mode = GET_MODE (operands[0]); 4370: 4371: /* All modes must be the same. */ 4372: if (! (mode == GET_MODE (operands[1]) 4373: && mode == GET_MODE (operands[2]) 4374: && mode == GET_MODE (operands[3]) 4375: && mode == GET_MODE (operands[4]) 4376: && mode == GET_MODE (operands[5]))) 4377: return 0; 4378: 4379: /* Both DFmode and SFmode should work. But using SFmode makes the 4380: assembler complain. Just turn it off for now. */ 4381: if (mode != DFmode) 4382: return 0; 4383: 4384: /* Only 2 real operands to the subtraction. Subtraction is not a commutative 4385: operation, so operands[4] must be the same as operand[3]. */ 4386: if (! rtx_equal_p (operands[3], operands[4])) 4387: return 0; 4388: 4389: /* multiply can not feed into subtraction. */ 4390: if (rtx_equal_p (operands[5], operands[0])) 4391: return 0; 4392: 4393: /* Inout operand of sub can not conflict with any operands from multiply. */ 4394: if (rtx_equal_p (operands[3], operands[0]) 4395: || rtx_equal_p (operands[3], operands[1]) 4396: || rtx_equal_p (operands[3], operands[2])) 4397: return 0; 4398: 4399: /* Passed. Operands are suitable for fmpysub. */ 4400: return 1; 4401: } 4402: 4403: int 4404: plus_xor_ior_operator (op, mode) 4405: rtx op; 4406: enum machine_mode mode; 4407: { 4408: return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR 4409: || GET_CODE (op) == IOR); 4410: } 4411: 4412: /* Return 1 if the given constant is 2, 4, or 8. These are the valid 4413: constants for shadd instructions. */ 4414: int 4415: shadd_constant_p (val) 4416: int val; 4417: { 4418: if (val == 2 || val == 4 || val == 8) 4419: return 1; 4420: else 4421: return 0; 4422: } 4423: 4424: /* Return 1 if OP is a CONST_INT with the value 2, 4, or 8. These are 4425: the valid constant for shadd instructions. */ 4426: int 4427: shadd_operand (op, mode) 4428: rtx op; 4429: enum machine_mode mode; 4430: { 4431: return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op))); 4432: } 1.1.1.2 root 4433: 1.1.1.3 root 4434: /* Return 1 if this operand is anything other than a hard register. */ 4435: 4436: int 4437: non_hard_reg_operand (op, mode) 4438: rtx op; 4439: enum machine_mode mode; 4440: { 4441: return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER); 4442: } 4443: 1.1.1.2 root 4444: /* Return 1 if INSN branches forward. Should be using insn_addresses 4445: to avoid walking through all the insns... */ 4446: int 4447: forward_branch_p (insn) 4448: rtx insn; 4449: { 4450: rtx label = JUMP_LABEL (insn); 4451: 4452: while (insn) 4453: { 4454: if (insn == label) 4455: break; 4456: else 4457: insn = NEXT_INSN (insn); 4458: } 4459: 4460: return (insn == label); 4461: } 4462: 4463: /* Return 1 if OP is an equality comparison, else return 0. */ 4464: int 4465: eq_neq_comparison_operator (op, mode) 4466: rtx op; 4467: enum machine_mode mode; 4468: { 4469: return (GET_CODE (op) == EQ || GET_CODE (op) == NE); 4470: } 4471: 4472: /* Return 1 if OP is an operator suitable for use in a movb instruction. */ 4473: int 4474: movb_comparison_operator (op, mode) 4475: rtx op; 4476: enum machine_mode mode; 4477: { 4478: return (GET_CODE (op) == EQ || GET_CODE (op) == NE 4479: || GET_CODE (op) == LT || GET_CODE (op) == GE); 4480: } 4481: 4482: /* Return 1 if INSN is in the delay slot of a call instruction. */ 4483: int 4484: jump_in_call_delay (insn) 4485: rtx insn; 4486: { 4487: 4488: if (GET_CODE (insn) != JUMP_INSN) 4489: return 0; 4490: 4491: if (PREV_INSN (insn) 4492: && PREV_INSN (PREV_INSN (insn)) 4493: && GET_CODE (next_active_insn (PREV_INSN (PREV_INSN (insn)))) == INSN) 4494: { 4495: rtx test_insn = next_active_insn (PREV_INSN (PREV_INSN (insn))); 4496: 4497: return (GET_CODE (PATTERN (test_insn)) == SEQUENCE 4498: && XVECEXP (PATTERN (test_insn), 0, 1) == insn); 4499: 4500: } 4501: else 4502: return 0; 4503: } 1.1.1.4 ! root 4504: ! 4505: ! 4506: /* We use this hook to perform a PA specific optimization which is difficult ! 4507: to do in earlier passes. ! 4508: ! 4509: We want the delay slots of branches within jump tables to be filled. ! 4510: None of the compiler passes at the moment even has the notion that a ! 4511: PA jump table doesn't contain addresses, but instead contains actual ! 4512: instructions! ! 4513: ! 4514: Because we actually jump into the table, the addresses of each entry ! 4515: must stay constant in relation to the beginning of the table (which ! 4516: itself must stay constant relative to the instruction to jump into ! 4517: it). I don't believe we can guarantee earlier passes of the compiler ! 4518: will adhere to those rules. ! 4519: ! 4520: So, late in the compilation process we find all the jump tables, and ! 4521: expand them into real code -- eg each entry in the jump table vector ! 4522: will get an appropriate label followed by a jump to the final target. ! 4523: ! 4524: Reorg and the final jump pass can then optimize these branches and ! 4525: fill their delay slots. We end up with smaller, more efficient code. ! 4526: ! 4527: The jump instructions within the table are special; we must be able ! 4528: to identify them during assembly output (if the jumps don't get filled ! 4529: we need to emit a nop rather than nullifying the delay slot)). We ! 4530: identify jumps in switch tables by marking the SET with DImode. */ ! 4531: ! 4532: pa_reorg (insns) ! 4533: rtx insns; ! 4534: { ! 4535: rtx insn; ! 4536: ! 4537: /* This is fairly cheap, so always run it if optimizing. */ ! 4538: if (optimize > 0) ! 4539: { ! 4540: /* Find and explode all ADDR_VEC insns. */ ! 4541: insns = get_insns (); ! 4542: for (insn = insns; insn; insn = NEXT_INSN (insn)) ! 4543: { ! 4544: rtx pattern, tmp, location; ! 4545: unsigned int length, i; ! 4546: ! 4547: /* Find an ADDR_VEC insn to explode. */ ! 4548: if (GET_CODE (insn) != JUMP_INSN ! 4549: || GET_CODE (PATTERN (insn)) != ADDR_VEC) ! 4550: continue; ! 4551: ! 4552: pattern = PATTERN (insn); ! 4553: location = PREV_INSN (insn); ! 4554: length = XVECLEN (pattern, 0); ! 4555: for (i = 0; i < length; i++) ! 4556: { ! 4557: /* Emit the jump itself. */ ! 4558: tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 0, i), 0)); ! 4559: tmp = emit_jump_insn_after (tmp, location); ! 4560: JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0); ! 4561: LABEL_NUSES (JUMP_LABEL (tmp))++; ! 4562: ! 4563: /* Emit a BARRIER after the jump. */ ! 4564: location = NEXT_INSN (location); ! 4565: emit_barrier_after (location); ! 4566: ! 4567: /* Put a CODE_LABEL before each so jump.c does not optimize ! 4568: the jumps away. */ ! 4569: location = NEXT_INSN (location); ! 4570: tmp = gen_label_rtx (); ! 4571: LABEL_NUSES (tmp) = 1; ! 4572: emit_label_after (tmp, location); ! 4573: location = NEXT_INSN (location); ! 4574: } ! 4575: /* Delete the ADDR_VEC. */ ! 4576: delete_insn (insn); ! 4577: } ! 4578: } ! 4579: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.