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