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