|
|
1.1 ! root 1: /* Subroutines used for code generation on intel 80960. ! 2: Copyright (C) 1992 Free Software Foundation, Inc. ! 3: Contributed by Steven McGeady, Intel Corp. ! 4: Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson ! 5: Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. ! 6: ! 7: This file is part of GNU CC. ! 8: ! 9: GNU CC is free software; you can redistribute it and/or modify ! 10: it under the terms of the GNU General Public License as published by ! 11: the Free Software Foundation; either version 2, or (at your option) ! 12: any later version. ! 13: ! 14: GNU CC is distributed in the hope that it will be useful, ! 15: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 17: GNU General Public License for more details. ! 18: ! 19: You should have received a copy of the GNU General Public License ! 20: along with GNU CC; see the file COPYING. If not, write to ! 21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 22: ! 23: #include <stdio.h> ! 24: ! 25: #include "config.h" ! 26: #include "rtl.h" ! 27: #include "regs.h" ! 28: #include "hard-reg-set.h" ! 29: #include "real.h" ! 30: #include "insn-config.h" ! 31: #include "conditions.h" ! 32: #include "insn-flags.h" ! 33: #include "output.h" ! 34: #include "insn-attr.h" ! 35: #include "flags.h" ! 36: #include "tree.h" ! 37: #include "insn-codes.h" ! 38: #include "assert.h" ! 39: #include "expr.h" ! 40: #include "function.h" ! 41: #include "recog.h" ! 42: #include <math.h> ! 43: ! 44: /* Save the operands last given to a compare for use when we ! 45: generate a scc or bcc insn. */ ! 46: ! 47: rtx i960_compare_op0, i960_compare_op1; ! 48: ! 49: /* Used to implement #pragma align/noalign. Initialized by OVERRIDE_OPTIONS ! 50: macro in i960.h. */ ! 51: ! 52: static int i960_maxbitalignment; ! 53: static int i960_last_maxbitalignment; ! 54: ! 55: /* Used to implement switching between MEM and ALU insn types, for better ! 56: C series performance. */ ! 57: ! 58: enum insn_types i960_last_insn_type; ! 59: ! 60: /* The leaf-procedure return register. Set only if this is a leaf routine. */ ! 61: ! 62: static int i960_leaf_ret_reg; ! 63: ! 64: /* True if replacing tail calls with jumps is OK. */ ! 65: ! 66: static int tail_call_ok; ! 67: ! 68: /* A string containing a list of insns to emit in the epilogue so as to ! 69: restore all registers saved by the prologue. Created by the prologue ! 70: code as it saves registers away. */ ! 71: ! 72: char epilogue_string[1000]; ! 73: ! 74: /* A unique number (per function) for return labels. */ ! 75: ! 76: static int ret_label = 0; ! 77: ! 78: #if 0 ! 79: /* Handle pragmas for compatibility with Intel's compilers. */ ! 80: ! 81: /* ??? This is incomplete, since it does not handle all pragmas that the ! 82: intel compilers understand. Also, it needs to be rewritten to accept ! 83: a stream instead of a string for GCC 2. */ ! 84: ! 85: void ! 86: process_pragma(str) ! 87: char *str; ! 88: { ! 89: int align; ! 90: int i; ! 91: ! 92: if ((i = sscanf (str, " align %d", &align)) == 1) ! 93: switch (align) ! 94: { ! 95: case 0: /* Return to last alignment. */ ! 96: align = i960_last_maxbitalignment / 8; ! 97: ! 98: case 16: /* Byte alignments. */ ! 99: case 8: ! 100: case 4: ! 101: case 2: ! 102: case 1: ! 103: i960_last_maxbitalignment = i960_maxbitalignment; ! 104: i960_maxbitalignment = align * 8; ! 105: break; ! 106: ! 107: default: /* Unknown, silently ignore. */ ! 108: break; ! 109: } ! 110: ! 111: /* NOTE: ic960 R3.0 pragma align definition: ! 112: ! 113: #pragma align [(size)] | (identifier=size[,...]) ! 114: #pragma noalign [(identifier)[,...]] ! 115: ! 116: (all parens are optional) ! 117: ! 118: - size is [1,2,4,8,16] ! 119: - noalign means size==1 ! 120: - applies only to component elements of a struct (and union?) ! 121: - identifier applies to structure tag (only) ! 122: - missing identifier means next struct ! 123: ! 124: - alignment rules for bitfields need more investigation */ ! 125: ! 126: /* Should be pragma 'far' or equivalent for callx/balx here. */ ! 127: } ! 128: #endif ! 129: ! 130: /* Initialize variables before compiling any files. */ ! 131: ! 132: void ! 133: i960_initialize () ! 134: { ! 135: if (TARGET_IC_COMPAT2_0) ! 136: { ! 137: i960_maxbitalignment = 8; ! 138: i960_last_maxbitalignment = 128; ! 139: } ! 140: else ! 141: { ! 142: i960_maxbitalignment = 128; ! 143: i960_last_maxbitalignment = 8; ! 144: } ! 145: } ! 146: ! 147: /* Return true if OP can be used as the source of an fp move insn. */ ! 148: ! 149: int ! 150: fpmove_src_operand (op, mode) ! 151: rtx op; ! 152: enum machine_mode mode; ! 153: { ! 154: return (GET_CODE (op) == CONST_DOUBLE || general_operand (op, mode)); ! 155: } ! 156: ! 157: #if 0 ! 158: /* Return true if OP is a register or zero. */ ! 159: ! 160: int ! 161: reg_or_zero_operand (op, mode) ! 162: rtx op; ! 163: enum machine_mode mode; ! 164: { ! 165: return register_operand (op, mode) || op == const0_rtx; ! 166: } ! 167: #endif ! 168: ! 169: /* Return truth value of whether OP can be used as an operands in a three ! 170: address arithmetic insn (such as add %o1,7,%l2) of mode MODE. */ ! 171: ! 172: int ! 173: arith_operand (op, mode) ! 174: rtx op; ! 175: enum machine_mode mode; ! 176: { ! 177: return (register_operand (op, mode) || literal (op, mode)); ! 178: } ! 179: ! 180: /* Return true if OP is a register or a valid floating point literal. */ ! 181: ! 182: int ! 183: fp_arith_operand (op, mode) ! 184: rtx op; ! 185: enum machine_mode mode; ! 186: { ! 187: return (register_operand (op, mode) || fp_literal (op, mode)); ! 188: } ! 189: ! 190: /* Return true is OP is a register or a valid signed integer literal. */ ! 191: ! 192: int ! 193: signed_arith_operand (op, mode) ! 194: rtx op; ! 195: enum machine_mode mode; ! 196: { ! 197: return (register_operand (op, mode) || signed_literal (op, mode)); ! 198: } ! 199: ! 200: /* Return truth value of whether OP is a integer which fits the ! 201: range constraining immediate operands in three-address insns. */ ! 202: ! 203: int ! 204: literal (op, mode) ! 205: rtx op; ! 206: enum machine_mode mode; ! 207: { ! 208: return ((GET_CODE (op) == CONST_INT) && INTVAL(op) >= 0 && INTVAL(op) < 32); ! 209: } ! 210: ! 211: /* Return true if OP is a float constant of 1. */ ! 212: ! 213: int ! 214: fp_literal_one (op, mode) ! 215: rtx op; ! 216: enum machine_mode mode; ! 217: { ! 218: return (TARGET_NUMERICS && (mode == VOIDmode || mode == GET_MODE (op)) ! 219: && (op == CONST1_RTX (mode))); ! 220: } ! 221: ! 222: /* Return true if OP is a float constant of 0. */ ! 223: ! 224: int ! 225: fp_literal_zero (op, mode) ! 226: rtx op; ! 227: enum machine_mode mode; ! 228: { ! 229: return (TARGET_NUMERICS && (mode == VOIDmode || mode == GET_MODE (op)) ! 230: && (op == CONST0_RTX (mode))); ! 231: } ! 232: ! 233: /* Return true if OP is a valid floating point literal. */ ! 234: ! 235: int ! 236: fp_literal(op, mode) ! 237: rtx op; ! 238: enum machine_mode mode; ! 239: { ! 240: return fp_literal_zero (op, mode) || fp_literal_one (op, mode); ! 241: } ! 242: ! 243: /* Return true if OP is a valid signed immediate constant. */ ! 244: ! 245: int ! 246: signed_literal(op, mode) ! 247: rtx op; ! 248: enum machine_mode mode; ! 249: { ! 250: return ((GET_CODE (op) == CONST_INT) && INTVAL(op) > -32 && INTVAL(op) < 32); ! 251: } ! 252: ! 253: /* Return truth value of statement that OP is a symbolic memory ! 254: operand of mode MODE. */ ! 255: ! 256: int ! 257: symbolic_memory_operand (op, mode) ! 258: rtx op; ! 259: enum machine_mode mode; ! 260: { ! 261: if (GET_CODE (op) == SUBREG) ! 262: op = SUBREG_REG (op); ! 263: if (GET_CODE (op) != MEM) ! 264: return 0; ! 265: op = XEXP (op, 0); ! 266: return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST ! 267: || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); ! 268: } ! 269: ! 270: /* Return truth value of whether OP is EQ or NE. */ ! 271: ! 272: int ! 273: eq_or_neq (op, mode) ! 274: rtx op; ! 275: enum machine_mode mode; ! 276: { ! 277: return (GET_CODE (op) == EQ || GET_CODE (op) == NE); ! 278: } ! 279: ! 280: /* OP is an integer register or a constant. */ ! 281: ! 282: int ! 283: arith32_operand (op, mode) ! 284: rtx op; ! 285: enum machine_mode mode; ! 286: { ! 287: if (register_operand (op, mode)) ! 288: return 1; ! 289: return (CONSTANT_P (op)); ! 290: } ! 291: ! 292: /* Return true if OP is an integer constant which is a power of 2. */ ! 293: ! 294: int ! 295: power2_operand (op,mode) ! 296: rtx op; ! 297: enum machine_mode mode; ! 298: { ! 299: if (GET_CODE (op) != CONST_INT) ! 300: return 0; ! 301: ! 302: return exact_log2 (INTVAL (op)) >= 0; ! 303: } ! 304: ! 305: /* Return true if OP is an integer constant which is the complement of a ! 306: power of 2. */ ! 307: ! 308: int ! 309: cmplpower2_operand (op, mode) ! 310: rtx op; ! 311: enum machine_mode mode; ! 312: { ! 313: if (GET_CODE (op) != CONST_INT) ! 314: return 0; ! 315: ! 316: return exact_log2 (~ INTVAL (op)) >= 0; ! 317: } ! 318: ! 319: /* If VAL has only one bit set, return the index of that bit. Otherwise ! 320: return -1. */ ! 321: ! 322: int ! 323: bitpos (val) ! 324: unsigned int val; ! 325: { ! 326: register int i; ! 327: ! 328: for (i = 0; val != 0; i++, val >>= 1) ! 329: { ! 330: if (val & 1) ! 331: { ! 332: if (val != 1) ! 333: return -1; ! 334: return i; ! 335: } ! 336: } ! 337: return -1; ! 338: } ! 339: ! 340: /* Return non-zero if OP is a mask, i.e. all one bits are consecutive. ! 341: The return value indicates how many consecutive non-zero bits exist ! 342: if this is a mask. This is the same as the next function, except that ! 343: it does not indicate what the start and stop bit positions are. */ ! 344: ! 345: int ! 346: is_mask (val) ! 347: unsigned int val; ! 348: { ! 349: register int start, end, i; ! 350: ! 351: start = -1; ! 352: for (i = 0; val != 0; val >>= 1, i++) ! 353: { ! 354: if (val & 1) ! 355: { ! 356: if (start < 0) ! 357: start = i; ! 358: ! 359: end = i; ! 360: continue; ! 361: } ! 362: /* Still looking for the first bit. */ ! 363: if (start < 0) ! 364: continue; ! 365: ! 366: /* We've seen the start of a bit sequence, and now a zero. There ! 367: must be more one bits, otherwise we would have exited the loop. ! 368: Therefore, it is not a mask. */ ! 369: if (val) ! 370: return 0; ! 371: } ! 372: ! 373: /* The bit string has ones from START to END bit positions only. */ ! 374: return end - start + 1; ! 375: } ! 376: ! 377: /* If VAL is a mask, then return nonzero, with S set to the starting bit ! 378: position and E set to the ending bit position of the mask. The return ! 379: value indicates how many consecutive bits exist in the mask. This is ! 380: the same as the previous function, except that it also indicates the ! 381: start and end bit positions of the mask. */ ! 382: ! 383: int ! 384: bitstr (val, s, e) ! 385: unsigned int val; ! 386: int *s, *e; ! 387: { ! 388: register int start, end, i; ! 389: ! 390: start = -1; ! 391: end = -1; ! 392: for (i = 0; val != 0; val >>= 1, i++) ! 393: { ! 394: if (val & 1) ! 395: { ! 396: if (start < 0) ! 397: start = i; ! 398: ! 399: end = i; ! 400: continue; ! 401: } ! 402: ! 403: /* Still looking for the first bit. */ ! 404: if (start < 0) ! 405: continue; ! 406: ! 407: /* We've seen the start of a bit sequence, and now a zero. There ! 408: must be more one bits, otherwise we would have exited the loop. ! 409: Therefor, it is not a mask. */ ! 410: if (val) ! 411: { ! 412: start = -1; ! 413: end = -1; ! 414: break; ! 415: } ! 416: } ! 417: ! 418: /* The bit string has ones from START to END bit positions only. */ ! 419: *s = start; ! 420: *e = end; ! 421: return ((start < 0) ? 0 : end - start + 1); ! 422: } ! 423: ! 424: /* Return the machine mode to use for a comparison. */ ! 425: ! 426: enum machine_mode ! 427: select_cc_mode (op, x) ! 428: RTX_CODE op; ! 429: rtx x; ! 430: { ! 431: if (op == GTU || op == LTU || op == GEU || op == LEU) ! 432: return CC_UNSmode; ! 433: return CCmode; ! 434: } ! 435: ! 436: /* X and Y are two things to compare using CODE. Emit the compare insn and ! 437: return the rtx for register 36 in the proper mode. */ ! 438: ! 439: rtx ! 440: gen_compare_reg (code, x, y) ! 441: enum rtx_code code; ! 442: rtx x, y; ! 443: { ! 444: rtx cc_reg; ! 445: enum machine_mode ccmode = SELECT_CC_MODE (code, x, y); ! 446: enum machine_mode mode ! 447: = GET_MODE (x) == VOIDmode ? GET_MODE (y) : GET_MODE (x); ! 448: ! 449: if (mode == SImode) ! 450: { ! 451: if (! arith_operand (x, mode)) ! 452: x = force_reg (SImode, x); ! 453: if (! arith_operand (y, mode)) ! 454: y = force_reg (SImode, y); ! 455: } ! 456: ! 457: cc_reg = gen_rtx (REG, ccmode, 36); ! 458: emit_insn (gen_rtx (SET, VOIDmode, cc_reg, ! 459: gen_rtx (COMPARE, ccmode, x, y))); ! 460: ! 461: return cc_reg; ! 462: } ! 463: ! 464: /* For the i960, REG is cost 1, REG+immed CONST is cost 2, REG+REG is cost 2, ! 465: REG+nonimmed CONST is cost 4. REG+SYMBOL_REF, SYMBOL_REF, and similar ! 466: are 4. Indexed addresses are cost 6. */ ! 467: ! 468: /* ??? Try using just RTX_COST, i.e. not defining ADDRESS_COST. */ ! 469: ! 470: int ! 471: i960_address_cost (x) ! 472: rtx x; ! 473: { ! 474: #if 0 ! 475: /* Handled before calling here. */ ! 476: if (GET_CODE (x) == REG) ! 477: return 1; ! 478: #endif ! 479: if (GET_CODE (x) == PLUS) ! 480: { ! 481: rtx base = XEXP (x, 0); ! 482: rtx offset = XEXP (x, 1); ! 483: ! 484: if (GET_CODE (base) == SUBREG) ! 485: base = SUBREG_REG (base); ! 486: if (GET_CODE (offset) == SUBREG) ! 487: offset = SUBREG_REG (offset); ! 488: ! 489: if (GET_CODE (base) == REG) ! 490: { ! 491: if (GET_CODE (offset) == REG) ! 492: return 2; ! 493: if (GET_CODE (offset) == CONST_INT) ! 494: { ! 495: if ((unsigned)INTVAL (offset) < 2047) ! 496: return 2; ! 497: return 4; ! 498: } ! 499: if (CONSTANT_P (offset)) ! 500: return 4; ! 501: } ! 502: if (GET_CODE (base) == PLUS || GET_CODE (base) == MULT) ! 503: return 6; ! 504: ! 505: /* This is an invalid address. The return value doesn't matter, but ! 506: for convenience we make this more expensive than anything else. */ ! 507: return 12; ! 508: } ! 509: if (GET_CODE (x) == MULT) ! 510: return 6; ! 511: ! 512: /* Symbol_refs and other unrecognized addresses are cost 4. */ ! 513: return 4; ! 514: } ! 515: ! 516: /* Emit insns to move operands[1] into operands[0]. ! 517: ! 518: Return 1 if we have written out everything that needs to be done to ! 519: do the move. Otherwise, return 0 and the caller will emit the move ! 520: normally. */ ! 521: ! 522: int ! 523: emit_move_sequence (operands, mode) ! 524: rtx *operands; ! 525: enum machine_mode mode; ! 526: { ! 527: register rtx operand0 = operands[0]; ! 528: register rtx operand1 = operands[1]; ! 529: ! 530: /* We can only store registers to memory. */ ! 531: ! 532: if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG) ! 533: operands[1] = force_reg (mode, operand1); ! 534: ! 535: return 0; ! 536: } ! 537: ! 538: /* Emit insns to load a constant. Uses several strategies to try to use ! 539: as few insns as possible. */ ! 540: ! 541: char * ! 542: i960_output_ldconst (dst, src) ! 543: register rtx dst, src; ! 544: { ! 545: register int rsrc1; ! 546: register unsigned rsrc2; ! 547: enum machine_mode mode = GET_MODE (dst); ! 548: rtx operands[4]; ! 549: union { long l[2]; double d; } x; ! 550: ! 551: operands[0] = operands[2] = dst; ! 552: operands[1] = operands[3] = src; ! 553: ! 554: /* Anything that isn't a compile time constant, such as a SYMBOL_REF, ! 555: must be a ldconst insn. */ ! 556: ! 557: if (GET_CODE (src) != CONST_INT && GET_CODE (src) != CONST_DOUBLE) ! 558: { ! 559: output_asm_insn ("ldconst %1,%0", operands); ! 560: return ""; ! 561: } ! 562: else if (mode == DFmode) ! 563: { ! 564: rtx first, second; ! 565: ! 566: if (fp_literal_zero (src, VOIDmode)) ! 567: { ! 568: if (FP_REG_P (dst)) ! 569: return "movrl %1,%0"; ! 570: else ! 571: return "movl 0,%0"; ! 572: } ! 573: ! 574: #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! 575: split_double (src, &first, &second); ! 576: ! 577: output_asm_insn ("# ldconst %1,%0",operands); ! 578: ! 579: operands[0] = gen_rtx (REG, SImode, REGNO (dst)); ! 580: operands[1] = first; ! 581: output_asm_insn (i960_output_ldconst (operands[0], operands[1]), ! 582: operands); ! 583: operands[0] = gen_rtx (REG, SImode, REGNO (dst) + 1); ! 584: operands[1] = second; ! 585: output_asm_insn (i960_output_ldconst (operands[0], operands[1]), ! 586: operands); ! 587: return ""; ! 588: #else ! 589: if (fp_literal_one (src, VOIDmode)) ! 590: return "movrl 0f1.0,%0"; ! 591: fatal ("inline double constants not supported on this host"); ! 592: #endif ! 593: } ! 594: else if (mode == TImode) ! 595: { ! 596: /* ??? This is currently not handled at all. */ ! 597: abort (); ! 598: ! 599: /* Note: lowest order word goes in lowest numbered reg. */ ! 600: rsrc1 = INTVAL (src); ! 601: if (rsrc1 >= 0 && rsrc1 < 32) ! 602: return "movq %1,%0"; ! 603: else ! 604: output_asm_insn ("movq\t0,%0\t# ldconstq %1,%0",operands); ! 605: /* Go pick up the low-order word. */ ! 606: } ! 607: else if (mode == DImode) ! 608: { ! 609: rtx upperhalf, lowerhalf, xoperands[2]; ! 610: char *string; ! 611: ! 612: if (GET_CODE (src) == CONST_DOUBLE) ! 613: { ! 614: upperhalf = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (src)); ! 615: lowerhalf = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (src)); ! 616: } ! 617: else if (GET_CODE (src) == CONST_INT) ! 618: { ! 619: lowerhalf = src; ! 620: upperhalf = INTVAL (src) < 0 ? constm1_rtx : const0_rtx; ! 621: } ! 622: else ! 623: abort (); ! 624: ! 625: /* Note: lowest order word goes in lowest numbered reg. */ ! 626: /* Numbers from 0 to 31 can be handled with a single insn. */ ! 627: rsrc1 = INTVAL (lowerhalf); ! 628: if (upperhalf == const0_rtx && rsrc1 >= 0 && rsrc1 < 32) ! 629: return "movl %1,%0"; ! 630: ! 631: /* Output the upper half with a recursive call. */ ! 632: xoperands[0] = gen_rtx (REG, SImode, REGNO (dst) + 1); ! 633: xoperands[1] = upperhalf; ! 634: output_asm_insn (i960_output_ldconst (xoperands[0], xoperands[1]), ! 635: xoperands); ! 636: /* The lower word is emitted as normally. */ ! 637: } ! 638: else if (mode == SFmode) ! 639: { ! 640: #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! 641: REAL_VALUE_TYPE d; ! 642: long value; ! 643: ! 644: REAL_VALUE_FROM_CONST_DOUBLE (d, src); ! 645: REAL_VALUE_TO_TARGET_SINGLE (d, value); ! 646: ! 647: output_asm_insn ("# ldconst %1,%0",operands); ! 648: operands[0] = gen_rtx (REG, SImode, REGNO (dst)); ! 649: operands[1] = gen_rtx (CONST_INT, VOIDmode, value); ! 650: output_asm_insn (i960_output_ldconst (operands[0], operands[1]), ! 651: operands); ! 652: #else ! 653: if (fp_literal_zero (src, VOIDmode)) ! 654: return "movr 0f0.0,%0"; ! 655: if (fp_literal_one (src, VOIDmode)) ! 656: return "movr 0f1.0,%0"; ! 657: fatal ("inline float constants not supported on this host"); ! 658: #endif ! 659: return ""; ! 660: } ! 661: else ! 662: { ! 663: rsrc1 = INTVAL (src); ! 664: if (mode == QImode) ! 665: { ! 666: if (rsrc1 > 0xff) ! 667: rsrc1 &= 0xff; ! 668: } ! 669: else if (mode == HImode) ! 670: { ! 671: if (rsrc1 > 0xffff) ! 672: rsrc1 &= 0xffff; ! 673: } ! 674: } ! 675: ! 676: if (rsrc1 >= 0) ! 677: { ! 678: /* ldconst 0..31,X -> mov 0..31,X */ ! 679: if (rsrc1 < 32) ! 680: { ! 681: if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) ! 682: return "lda %1,%0"; ! 683: return "mov %1,%0"; ! 684: } ! 685: ! 686: /* ldconst 32..63,X -> add 31,nn,X */ ! 687: if (rsrc1 < 63) ! 688: { ! 689: if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) ! 690: return "lda %1,%0"; ! 691: operands[1] = gen_rtx (CONST_INT, VOIDmode, rsrc1 - 31); ! 692: output_asm_insn ("addo\t31,%1,%0\t# ldconst %3,%0", operands); ! 693: return ""; ! 694: } ! 695: } ! 696: else if (rsrc1 < 0) ! 697: { ! 698: /* ldconst -1..-31 -> sub 0,0..31,X */ ! 699: if (rsrc1 >= -31) ! 700: { ! 701: /* return 'sub -(%1),0,%0' */ ! 702: operands[1] = gen_rtx (CONST_INT, VOIDmode, - rsrc1); ! 703: output_asm_insn ("subo\t%1,0,%0\t# ldconst %3,%0", operands); ! 704: return ""; ! 705: } ! 706: ! 707: /* ldconst -32 -> not 31,X */ ! 708: if (rsrc1 == -32) ! 709: { ! 710: operands[1] = gen_rtx (CONST_INT, VOIDmode, ~rsrc1); ! 711: output_asm_insn ("not\t%1,%0 # ldconst %3,%0", operands); ! 712: return ""; ! 713: } ! 714: } ! 715: ! 716: /* If const is a single bit. */ ! 717: if (bitpos (rsrc1) >= 0) ! 718: { ! 719: operands[1] = gen_rtx (CONST_INT, VOIDmode, bitpos (rsrc1)); ! 720: output_asm_insn ("setbit\t%1,0,%0\t# ldconst %3,%0", operands); ! 721: return ""; ! 722: } ! 723: ! 724: /* If const is a bit string of less than 6 bits (1..31 shifted). */ ! 725: if (is_mask (rsrc1)) ! 726: { ! 727: int s, e; ! 728: ! 729: if (bitstr (rsrc1, &s, &e) < 6) ! 730: { ! 731: rsrc2 = ((unsigned int) rsrc1) >> s; ! 732: operands[1] = gen_rtx (CONST_INT, VOIDmode, rsrc2); ! 733: operands[2] = gen_rtx (CONST_INT, VOIDmode, s); ! 734: output_asm_insn ("shlo\t%2,%1,%0\t# ldconst %3,%0", operands); ! 735: return ""; ! 736: } ! 737: } ! 738: ! 739: /* Unimplemented cases: ! 740: const is in range 0..31 but rotated around end of word: ! 741: ror 31,3,g0 -> ldconst 0xe0000003,g0 ! 742: ! 743: and any 2 instruction cases that might be worthwhile */ ! 744: ! 745: output_asm_insn ("ldconst %1,%0", operands); ! 746: return ""; ! 747: } ! 748: ! 749: /* Determine if there is an opportunity for a bypass optimization. ! 750: Bypass succeeds on the 960K* if the destination of the previous ! 751: instruction is the second operand of the current instruction. ! 752: Bypass always succeeds on the C*. ! 753: ! 754: Return 1 if the pattern should interchange the operands. ! 755: ! 756: CMPBR_FLAG is true if this is for a compare-and-branch insn. ! 757: OP1 and OP2 are the two source operands of a 3 operand insn. */ ! 758: ! 759: int ! 760: i960_bypass (insn, op1, op2, cmpbr_flag) ! 761: register rtx insn, op1, op2; ! 762: int cmpbr_flag; ! 763: { ! 764: register rtx prev_insn, prev_dest; ! 765: ! 766: if (TARGET_C_SERIES) ! 767: return 0; ! 768: ! 769: /* Can't do this if op1 isn't a register. */ ! 770: if (! REG_P (op1)) ! 771: return 0; ! 772: ! 773: /* Can't do this for a compare-and-branch if both ops aren't regs. */ ! 774: if (cmpbr_flag && ! REG_P (op2)) ! 775: return 0; ! 776: ! 777: prev_insn = prev_real_insn (insn); ! 778: ! 779: if (prev_insn && GET_CODE (prev_insn) == INSN ! 780: && GET_CODE (PATTERN (prev_insn)) == SET) ! 781: { ! 782: prev_dest = SET_DEST (PATTERN (prev_insn)); ! 783: if ((GET_CODE (prev_dest) == REG && REGNO (prev_dest) == REGNO (op1)) ! 784: || (GET_CODE (prev_dest) == SUBREG ! 785: && GET_CODE (SUBREG_REG (prev_dest)) == REG ! 786: && REGNO (SUBREG_REG (prev_dest)) == REGNO (op1))) ! 787: return 1; ! 788: } ! 789: return 0; ! 790: } ! 791: ! 792: /* Output the code which declares the function name. This also handles ! 793: leaf routines, which have special requirements, and initializes some ! 794: global variables. */ ! 795: ! 796: void ! 797: i960_function_name_declare (file, name, fndecl) ! 798: FILE *file; ! 799: char *name; ! 800: tree fndecl; ! 801: { ! 802: register int i, j; ! 803: int leaf_proc_ok; ! 804: rtx insn; ! 805: ! 806: /* Increment global return label. */ ! 807: ! 808: ret_label++; ! 809: ! 810: /* Compute whether tail calls and leaf routine optimizations can be performed ! 811: for this function. */ ! 812: ! 813: if (TARGET_TAILCALL) ! 814: tail_call_ok = 1; ! 815: else ! 816: tail_call_ok = 0; ! 817: ! 818: if (TARGET_LEAFPROC) ! 819: leaf_proc_ok = 1; ! 820: else ! 821: leaf_proc_ok = 0; ! 822: ! 823: /* Even if nobody uses extra parms, can't have leafroc or tail calls if ! 824: argblock, because argblock uses g14 implicitly. */ ! 825: ! 826: if (current_function_args_size != 0) ! 827: { ! 828: tail_call_ok = 0; ! 829: leaf_proc_ok = 0; ! 830: } ! 831: ! 832: /* See if caller passes in an address to return value. */ ! 833: ! 834: if (aggregate_value_p (DECL_RESULT (fndecl))) ! 835: { ! 836: tail_call_ok = 0; ! 837: leaf_proc_ok = 0; ! 838: } ! 839: ! 840: /* Can not use tail calls or make this a leaf routine if there is a non ! 841: zero frame size. */ ! 842: ! 843: if (get_frame_size () != 0) ! 844: leaf_proc_ok = 0; ! 845: ! 846: /* I don't understand this condition, and do not think that it is correct. ! 847: Apparently this is just checking whether the frame pointer is used, and ! 848: we can't trust regs_ever_live[fp] since it is (almost?) always set. */ ! 849: ! 850: if (tail_call_ok) ! 851: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 852: if (GET_CODE (insn) == INSN ! 853: && reg_mentioned_p (frame_pointer_rtx, insn)) ! 854: { ! 855: tail_call_ok = 0; ! 856: break; ! 857: } ! 858: ! 859: /* Check for CALL insns. Can not be a leaf routine if there are any. */ ! 860: ! 861: if (leaf_proc_ok) ! 862: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 863: if (GET_CODE (insn) == CALL_INSN) ! 864: { ! 865: leaf_proc_ok = 0; ! 866: break; ! 867: } ! 868: ! 869: /* Can not be a leaf routine if any non-call clobbered registers are ! 870: used in this function. */ ! 871: ! 872: if (leaf_proc_ok) ! 873: for (i = 0, j = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 874: if (regs_ever_live[i] ! 875: && ((! call_used_regs[i]) || (i > 7 && i < 12))) ! 876: { ! 877: /* Global registers. */ ! 878: if (i < 16 && i > 7 && i != 13) ! 879: leaf_proc_ok = 0; ! 880: /* Local registers. */ ! 881: else if (i < 32) ! 882: leaf_proc_ok = 0; ! 883: } ! 884: ! 885: /* Now choose a leaf return register, if we can find one, and if it is ! 886: OK for this to be a leaf routine. */ ! 887: ! 888: i960_leaf_ret_reg = -1; ! 889: ! 890: if (optimize && leaf_proc_ok) ! 891: { ! 892: for (i960_leaf_ret_reg = -1, i = 0; i < 8; i++) ! 893: if (regs_ever_live[i] == 0) ! 894: { ! 895: i960_leaf_ret_reg = i; ! 896: regs_ever_live[i] = 1; ! 897: break; ! 898: } ! 899: } ! 900: ! 901: /* Do this after choosing the leaf return register, so it will be listed ! 902: if one was chosen. */ ! 903: ! 904: fprintf (file, "\t# Function '%s'\n", name); ! 905: fprintf (file, "\t# Registers used: "); ! 906: ! 907: for (i = 0, j = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 908: { ! 909: if (regs_ever_live[i]) ! 910: { ! 911: fprintf (file, "%s%s ", reg_names[i], call_used_regs[i] ? "" : "*"); ! 912: ! 913: if (i > 15 && j == 0) ! 914: { ! 915: fprintf (file,"\n\t#\t\t "); ! 916: j++; ! 917: } ! 918: } ! 919: } ! 920: ! 921: fprintf (file, "\n"); ! 922: ! 923: if (i960_leaf_ret_reg >= 0) ! 924: { ! 925: /* Make it a leaf procedure. */ ! 926: ! 927: if (TREE_PUBLIC (fndecl)) ! 928: fprintf (file,"\t.globl %s.lf\n", name); ! 929: ! 930: fprintf (file, "\t.leafproc\t_%s,%s.lf\n", name, name); ! 931: fprintf (file, "_%s:\n", name); ! 932: fprintf (file, "\tlda LR%d,g14\n", ret_label); ! 933: fprintf (file, "%s.lf:\n", name); ! 934: fprintf (file, "\tmov g14,g%d\n", i960_leaf_ret_reg); ! 935: ! 936: if (TARGET_C_SERIES) ! 937: { ! 938: fprintf (file, "\tlda 0,g14\n"); ! 939: i960_last_insn_type = I_TYPE_MEM; ! 940: } ! 941: else ! 942: { ! 943: fprintf (file, "\tmov 0,g14\n"); ! 944: i960_last_insn_type = I_TYPE_REG; ! 945: } ! 946: } ! 947: else ! 948: { ! 949: ASM_OUTPUT_LABEL (file, name); ! 950: i960_last_insn_type = I_TYPE_CTRL; ! 951: } ! 952: } ! 953: ! 954: /* Compute and return the frame size. */ ! 955: ! 956: int ! 957: compute_frame_size (size) ! 958: int size; ! 959: { ! 960: int actual_fsize; ! 961: int outgoing_args_size ! 962: = current_function_outgoing_args_size + current_function_pretend_args_size; ! 963: ! 964: /* The STARTING_FRAME_OFFSET is totally hidden to us as far ! 965: as size is concerned. */ ! 966: actual_fsize = (size + 15) & -16; ! 967: actual_fsize += (outgoing_args_size + 15) & -16; ! 968: ! 969: return actual_fsize; ! 970: } ! 971: ! 972: /* Output code for the function prologue. */ ! 973: ! 974: void ! 975: i960_function_prologue (file, size) ! 976: FILE *file; ! 977: unsigned int size; ! 978: { ! 979: register int i, j, nr; ! 980: int n_iregs = 0; ! 981: int rsize = 0; ! 982: int actual_fsize, offset; ! 983: char tmpstr[1000]; ! 984: /* -1 if reg must be saved on proc entry, 0 if available, 1 if saved ! 985: somewhere. */ ! 986: int regs[FIRST_PSEUDO_REGISTER]; ! 987: ! 988: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 989: if (regs_ever_live[i] ! 990: && ((! call_used_regs[i]) || (i > 7 && i < 12))) ! 991: { ! 992: regs[i] = -1; ! 993: /* Count global registers that need saving. */ ! 994: if (i < 16) ! 995: n_iregs++; ! 996: } ! 997: else ! 998: regs[i] = 0; ! 999: ! 1000: epilogue_string[0] = '\0'; ! 1001: ! 1002: if (profile_flag || profile_block_flag) ! 1003: { ! 1004: /* When profiling, we may use registers 20 to 27 to save arguments, so ! 1005: they can't be used here for saving globals. J is the number of ! 1006: argument registers the mcount call will save. */ ! 1007: for (j = 7; j >= 0 && ! regs_ever_live[j]; j--) ! 1008: ; ! 1009: ! 1010: for (i = 20; i <= j + 20; i++) ! 1011: regs[i] = -1; ! 1012: } ! 1013: ! 1014: /* First look for local registers to save globals in. */ ! 1015: for (i = 0; i < 16; i++) ! 1016: { ! 1017: if (regs[i] == 0) ! 1018: continue; ! 1019: ! 1020: /* Start at r4, not r3. */ ! 1021: for (j = 20; j < 32; j++) ! 1022: { ! 1023: if (regs[j] != 0) ! 1024: continue; ! 1025: ! 1026: regs[i] = 1; ! 1027: regs[j] = -1; ! 1028: regs_ever_live[j] = 1; ! 1029: nr = 1; ! 1030: if (i <= 14 && i % 2 == 0 && j <= 30 && j % 2 == 0 ! 1031: && regs[i+1] != 0 && regs[j+1] == 0) ! 1032: { ! 1033: nr = 2; ! 1034: regs[i+1] = 1; ! 1035: regs[j+1] = -1; ! 1036: regs_ever_live[j+1] = 1; ! 1037: } ! 1038: if (nr == 2 && i <= 12 && i % 4 == 0 && j <= 28 && j % 4 == 0 ! 1039: && regs[i+2] != 0 && regs[j+2] == 0) ! 1040: { ! 1041: nr = 3; ! 1042: regs[i+2] = 1; ! 1043: regs[j+2] = -1; ! 1044: regs_ever_live[j+2] = 1; ! 1045: } ! 1046: if (nr == 3 && regs[i+3] != 0 && regs[j+3] == 0) ! 1047: { ! 1048: nr = 4; ! 1049: regs[i+3] = 1; ! 1050: regs[j+3] = -1; ! 1051: regs_ever_live[j+3] = 1; ! 1052: } ! 1053: ! 1054: fprintf (file, "\tmov%s %s,%s\n", ! 1055: ((nr == 4) ? "q" : ! 1056: (nr == 3) ? "t" : ! 1057: (nr == 2) ? "l" : ""), ! 1058: reg_names[i], reg_names[j]); ! 1059: sprintf (tmpstr, "\tmov%s %s,%s\n", ! 1060: ((nr == 4) ? "q" : ! 1061: (nr == 3) ? "t" : ! 1062: (nr == 2) ? "l" : ""), ! 1063: reg_names[j], reg_names[i]); ! 1064: strcat (epilogue_string, tmpstr); ! 1065: ! 1066: n_iregs -= nr; ! 1067: i += nr-1; ! 1068: break; ! 1069: } ! 1070: } ! 1071: ! 1072: /* N_iregs is now the number of global registers that haven't been saved ! 1073: yet. */ ! 1074: ! 1075: rsize = (n_iregs * 4); ! 1076: actual_fsize = compute_frame_size (size) + rsize; ! 1077: #if 0 ! 1078: /* ??? The 1.2.1 compiler does this also. This is meant to round the frame ! 1079: size up to the nearest multiple of 16. I don't know whether this is ! 1080: necessary, or even desirable. ! 1081: ! 1082: The frame pointer must be aligned, but the call instruction takes care of ! 1083: that. If we leave the stack pointer unaligned, we may save a little on ! 1084: dynamic stack allocation. And we don't lose, at least according to the ! 1085: i960CA manual. */ ! 1086: actual_fsize = (actual_fsize + 15) & ~0xF; ! 1087: #endif ! 1088: ! 1089: /* Allocate space for register save and locals. */ ! 1090: if (actual_fsize > 0) ! 1091: { ! 1092: if (actual_fsize < 32) ! 1093: fprintf (file, "\taddo %d,sp,sp\n", actual_fsize); ! 1094: else ! 1095: fprintf (file, "\tlda\t%d(sp),sp\n", actual_fsize); ! 1096: } ! 1097: ! 1098: /* Take hardware register save area created by the call instruction ! 1099: into account. */ ! 1100: offset = compute_frame_size (size) + 64; ! 1101: /* Save registers on stack if needed. */ ! 1102: for (i = 0, j = n_iregs; j > 0 && i < 16; i++) ! 1103: { ! 1104: if (regs[i] != -1) ! 1105: continue; ! 1106: ! 1107: nr = 1; ! 1108: ! 1109: if (i <= 14 && i % 2 == 0 && regs[i+1] == -1 && offset % 2 == 0) ! 1110: nr = 2; ! 1111: ! 1112: if (nr == 2 && i <= 12 && i % 4 == 0 && regs[i+2] == -1 ! 1113: && offset % 4 == 0) ! 1114: nr = 3; ! 1115: ! 1116: if (nr == 3 && regs[i+3] == -1) ! 1117: nr = 4; ! 1118: ! 1119: fprintf (file,"\tst%s %s,%d(fp)\n", ! 1120: ((nr == 4) ? "q" : ! 1121: (nr == 3) ? "t" : ! 1122: (nr == 2) ? "l" : ""), ! 1123: reg_names[i], offset); ! 1124: sprintf (tmpstr,"\tld%s %d(fp),%s\n", ! 1125: ((nr == 4) ? "q" : ! 1126: (nr == 3) ? "t" : ! 1127: (nr == 2) ? "l" : ""), ! 1128: offset, reg_names[i]); ! 1129: strcat (epilogue_string, tmpstr); ! 1130: i += nr-1; ! 1131: j -= nr; ! 1132: offset += nr * 4; ! 1133: } ! 1134: ! 1135: if (actual_fsize == 0 && size == 0 && rsize == 0) ! 1136: return; ! 1137: ! 1138: fprintf (file, "\t#Prologue stats:\n"); ! 1139: fprintf (file, "\t# Total Frame Size: %d bytes\n", actual_fsize); ! 1140: ! 1141: if (size) ! 1142: fprintf (file, "\t# Local Variable Size: %d bytes\n", size); ! 1143: if (rsize) ! 1144: fprintf (file, "\t# Register Save Size: %d regs, %d bytes\n", ! 1145: n_iregs, rsize); ! 1146: fprintf (file, "\t#End Prologue#\n"); ! 1147: } ! 1148: ! 1149: /* Output code for the function profiler. */ ! 1150: ! 1151: void ! 1152: output_function_profiler (file, labelno) ! 1153: FILE *file; ! 1154: int labelno; ! 1155: { ! 1156: /* The last used parameter register. */ ! 1157: int last_parm_reg; ! 1158: int i, j, increment; ! 1159: ! 1160: /* Figure out the last used parameter register. The proper thing to do ! 1161: is to walk incoming args of the function. A function might have live ! 1162: parameter registers even if it has no incoming args. Note that we ! 1163: don't have to save parameter registers g8 to g11 because they are ! 1164: call preserved. */ ! 1165: ! 1166: /* See also output_function_prologue, which tries to use local registers ! 1167: for preserved call-saved global registers. */ ! 1168: ! 1169: for (last_parm_reg = 7; ! 1170: last_parm_reg >= 0 && ! regs_ever_live[last_parm_reg]; ! 1171: last_parm_reg--) ! 1172: ; ! 1173: ! 1174: /* Save parameter registers in regs r4 (20) to r11 (27). */ ! 1175: ! 1176: for (i = 0, j = 4; i <= last_parm_reg; i += increment, j += increment) ! 1177: { ! 1178: if (i % 4 == 0 && (last_parm_reg - i) >= 3) ! 1179: increment = 4; ! 1180: else if (i % 4 == 0 && (last_parm_reg - i) >= 2) ! 1181: increment = 3; ! 1182: else if (i % 2 == 0 && (last_parm_reg - i) >= 1) ! 1183: increment = 2; ! 1184: else ! 1185: increment = 1; ! 1186: ! 1187: fprintf (file, "\tmov%s g%d,r%d\n", ! 1188: (increment == 4 ? "q" : increment == 3 ? "t" ! 1189: : increment == 2 ? "l": ""), i, j); ! 1190: } ! 1191: ! 1192: /* If this function uses the arg pointer, then save it in r3 and then ! 1193: set it to zero. */ ! 1194: ! 1195: if (current_function_args_size != 0) ! 1196: fprintf (file, "\tmov g14,r3\n\tmov 0,g14\n"); ! 1197: ! 1198: /* Load location address into g0 and call mcount. */ ! 1199: ! 1200: fprintf (file, "\tlda\tLP%d,g0\n\tcallx\tmcount\n", labelno); ! 1201: ! 1202: /* If this function uses the arg pointer, restore it. */ ! 1203: ! 1204: if (current_function_args_size != 0) ! 1205: fprintf (file, "\tmov r3,g14\n"); ! 1206: ! 1207: /* Restore parameter registers. */ ! 1208: ! 1209: for (i = 0, j = 4; i <= last_parm_reg; i += increment, j += increment) ! 1210: { ! 1211: if (i % 4 == 0 && (last_parm_reg - i) >= 3) ! 1212: increment = 4; ! 1213: else if (i % 4 == 0 && (last_parm_reg - i) >= 2) ! 1214: increment = 3; ! 1215: else if (i % 2 == 0 && (last_parm_reg - i) >= 1) ! 1216: increment = 2; ! 1217: else ! 1218: increment = 1; ! 1219: ! 1220: fprintf (file, "\tmov%s r%d,g%d\n", ! 1221: (increment == 4 ? "q" : increment == 3 ? "t" ! 1222: : increment == 2 ? "l": ""), j, i); ! 1223: } ! 1224: } ! 1225: ! 1226: /* Output code for the function epilogue. */ ! 1227: ! 1228: void ! 1229: i960_function_epilogue (file, size) ! 1230: FILE *file; ! 1231: unsigned int size; ! 1232: { ! 1233: if (i960_leaf_ret_reg >= 0) ! 1234: { ! 1235: fprintf (file, "LR%d: ret\n", ret_label); ! 1236: return; ! 1237: } ! 1238: ! 1239: if (*epilogue_string == 0) ! 1240: { ! 1241: register rtx tmp; ! 1242: ! 1243: /* Emit a return insn, but only if control can fall through to here. */ ! 1244: ! 1245: tmp = get_last_insn (); ! 1246: while (tmp) ! 1247: { ! 1248: if (GET_CODE (tmp) == BARRIER) ! 1249: return; ! 1250: if (GET_CODE (tmp) == CODE_LABEL) ! 1251: break; ! 1252: if (GET_CODE (tmp) == JUMP_INSN) ! 1253: { ! 1254: if (GET_CODE (PATTERN (tmp)) == RETURN) ! 1255: return; ! 1256: break; ! 1257: } ! 1258: if (GET_CODE (tmp) == NOTE) ! 1259: { ! 1260: tmp = PREV_INSN (tmp); ! 1261: continue; ! 1262: } ! 1263: break; ! 1264: } ! 1265: fprintf (file, "LR%d: ret\n", ret_label); ! 1266: return; ! 1267: } ! 1268: ! 1269: fprintf (file, "LR%d:\n", ret_label); ! 1270: ! 1271: fprintf (file, "\t#EPILOGUE#\n"); ! 1272: ! 1273: /* Output the string created by the prologue which will restore all ! 1274: registers saved by the prologue. */ ! 1275: ! 1276: if (epilogue_string[0] != '\0') ! 1277: fprintf (file, "%s", epilogue_string); ! 1278: ! 1279: /* Must clear g14 on return. */ ! 1280: ! 1281: if (current_function_args_size != 0) ! 1282: fprintf (file, "\tmov 0,g14\n"); ! 1283: ! 1284: fprintf (file, "\tret\n"); ! 1285: fprintf (file, "\t#End Epilogue#\n"); ! 1286: } ! 1287: ! 1288: /* Output code for a call insn. */ ! 1289: ! 1290: char * ! 1291: i960_output_call_insn (target, argsize_rtx, arg_pointer, insn) ! 1292: register rtx target, argsize_rtx, arg_pointer, insn; ! 1293: { ! 1294: int argsize = INTVAL (argsize_rtx); ! 1295: rtx nexti = next_real_insn (insn); ! 1296: rtx operands[2]; ! 1297: ! 1298: operands[0] = target; ! 1299: operands[1] = arg_pointer; ! 1300: ! 1301: if (current_function_args_size != 0) ! 1302: output_asm_insn ("mov g14,r3", operands); ! 1303: ! 1304: if (argsize > 48) ! 1305: output_asm_insn ("lda %a1,g14", operands); ! 1306: else if (current_function_args_size != 0) ! 1307: output_asm_insn ("mov 0,g14", operands); ! 1308: ! 1309: /* The code used to assume that calls to SYMBOL_REFs could not be more ! 1310: than 24 bits away (b vs bx, callj vs callx). This is not true. This ! 1311: feature is now implemented by relaxing in the GNU linker. It can convert ! 1312: bx to b if in range, and callx to calls/call/balx/bal as appropriate. */ ! 1313: ! 1314: /* Nexti could be zero if the called routine is volatile. */ ! 1315: if (optimize && (*epilogue_string == 0) && argsize == 0 && tail_call_ok ! 1316: && (nexti == 0 || GET_CODE (PATTERN (nexti)) == RETURN)) ! 1317: { ! 1318: /* Delete following return insn. */ ! 1319: if (nexti && no_labels_between_p (insn, nexti)) ! 1320: delete_insn (nexti); ! 1321: output_asm_insn ("bx %0", operands); ! 1322: return "# notreached"; ! 1323: } ! 1324: ! 1325: output_asm_insn ("callx %0", operands); ! 1326: ! 1327: if (current_function_args_size != 0) ! 1328: output_asm_insn ("mov r3,g14", operands); ! 1329: ! 1330: return ""; ! 1331: } ! 1332: ! 1333: /* Output code for a return insn. */ ! 1334: ! 1335: char * ! 1336: i960_output_ret_insn (insn) ! 1337: register rtx insn; ! 1338: { ! 1339: static char lbuf[20]; ! 1340: ! 1341: if (*epilogue_string != 0) ! 1342: { ! 1343: if (! TARGET_CODE_ALIGN && next_real_insn (insn) == 0) ! 1344: return ""; ! 1345: ! 1346: sprintf (lbuf, "b LR%d", ret_label); ! 1347: return lbuf; ! 1348: } ! 1349: ! 1350: if (current_function_args_size != 0) ! 1351: output_asm_insn ("mov 0,g14", 0); ! 1352: ! 1353: if (i960_leaf_ret_reg >= 0) ! 1354: { ! 1355: sprintf (lbuf, "bx (%s)", reg_names[i960_leaf_ret_reg]); ! 1356: return lbuf; ! 1357: } ! 1358: return "ret"; ! 1359: } ! 1360: ! 1361: #if 0 ! 1362: /* Return a character string representing the branch prediction ! 1363: opcode to be tacked on an instruction. This must at least ! 1364: return a null string. */ ! 1365: ! 1366: char * ! 1367: i960_br_predict_opcode (lab_ref, insn) ! 1368: rtx lab_ref, insn; ! 1369: { ! 1370: if (TARGET_BRANCH_PREDICT) ! 1371: { ! 1372: unsigned long label_uid; ! 1373: ! 1374: if (GET_CODE (lab_ref) == CODE_LABEL) ! 1375: label_uid = INSN_UID (lab_ref); ! 1376: else if (GET_CODE (lab_ref) == LABEL_REF) ! 1377: label_uid = INSN_UID (XEXP (lab_ref, 0)); ! 1378: else ! 1379: return ".f"; ! 1380: ! 1381: /* If not optimizing, then the insn_addresses array will not be ! 1382: valid. In this case, always return ".t" since most branches ! 1383: are taken. If optimizing, return .t for backward branches ! 1384: and .f for forward branches. */ ! 1385: if (! optimize ! 1386: || insn_addresses[label_uid] < insn_addresses[INSN_UID (insn)]) ! 1387: return ".t"; ! 1388: return ".f"; ! 1389: } ! 1390: ! 1391: return ""; ! 1392: } ! 1393: #endif ! 1394: ! 1395: /* Print the operand represented by rtx X formatted by code CODE. */ ! 1396: ! 1397: void ! 1398: i960_print_operand (file, x, code) ! 1399: FILE *file; ! 1400: rtx x; ! 1401: char code; ! 1402: { ! 1403: enum rtx_code rtxcode = GET_CODE (x); ! 1404: ! 1405: if (rtxcode == REG) ! 1406: { ! 1407: switch (code) ! 1408: { ! 1409: case 'D': ! 1410: /* Second reg of a double. */ ! 1411: fprintf (file, "%s", reg_names[REGNO (x)+1]); ! 1412: break; ! 1413: ! 1414: case 0: ! 1415: fprintf (file, "%s", reg_names[REGNO (x)]); ! 1416: break; ! 1417: ! 1418: default: ! 1419: abort (); ! 1420: } ! 1421: return; ! 1422: } ! 1423: else if (rtxcode == MEM) ! 1424: { ! 1425: output_address (XEXP (x, 0)); ! 1426: return; ! 1427: } ! 1428: else if (rtxcode == CONST_INT) ! 1429: { ! 1430: if (INTVAL (x) > 9999 || INTVAL (x) < -999) ! 1431: fprintf (file, "0x%x", INTVAL (x)); ! 1432: else ! 1433: fprintf (file, "%d", INTVAL (x)); ! 1434: return; ! 1435: } ! 1436: else if (rtxcode == CONST_DOUBLE) ! 1437: { ! 1438: double d; ! 1439: ! 1440: if (x == CONST0_RTX (DFmode) || x == CONST0_RTX (SFmode)) ! 1441: { ! 1442: fprintf (file, "0f0.0"); ! 1443: return; ! 1444: } ! 1445: else if (x == CONST1_RTX (DFmode) || x == CONST1_RTX (SFmode)) ! 1446: { ! 1447: fprintf (file, "0f1.0"); ! 1448: return; ! 1449: } ! 1450: ! 1451: /* This better be a comment. */ ! 1452: REAL_VALUE_FROM_CONST_DOUBLE (d, x); ! 1453: fprintf (file, "%#g", d); ! 1454: return; ! 1455: } ! 1456: ! 1457: switch(code) ! 1458: { ! 1459: case 'B': ! 1460: /* Branch or jump, depending on assembler. */ ! 1461: if (TARGET_ASM_COMPAT) ! 1462: fputs ("j", file); ! 1463: else ! 1464: fputs ("b", file); ! 1465: break; ! 1466: ! 1467: case 'S': ! 1468: /* Sign of condition. */ ! 1469: if ((rtxcode == EQ) || (rtxcode == NE) || (rtxcode == GTU) ! 1470: || (rtxcode == LTU) || (rtxcode == GEU) || (rtxcode == LEU)) ! 1471: fputs ("o", file); ! 1472: else if ((rtxcode == GT) || (rtxcode == LT) ! 1473: || (rtxcode == GE) || (rtxcode == LE)) ! 1474: fputs ("i", file); ! 1475: else ! 1476: abort(); ! 1477: break; ! 1478: ! 1479: case 'I': ! 1480: /* Inverted condition. */ ! 1481: rtxcode = reverse_condition (rtxcode); ! 1482: goto normal; ! 1483: ! 1484: case 'X': ! 1485: /* Inverted condition w/ reversed operands. */ ! 1486: rtxcode = reverse_condition (rtxcode); ! 1487: /* Fallthrough. */ ! 1488: ! 1489: case 'R': ! 1490: /* Reversed operand condition. */ ! 1491: rtxcode = swap_condition (rtxcode); ! 1492: /* Fallthrough. */ ! 1493: ! 1494: case 'C': ! 1495: /* Normal condition. */ ! 1496: normal: ! 1497: if (rtxcode == EQ) { fputs ("e", file); return; } ! 1498: else if (rtxcode == NE) { fputs ("ne", file); return; } ! 1499: else if (rtxcode == GT) { fputs ("g", file); return; } ! 1500: else if (rtxcode == GTU) { fputs ("g", file); return; } ! 1501: else if (rtxcode == LT) { fputs ("l", file); return; } ! 1502: else if (rtxcode == LTU) { fputs ("l", file); return; } ! 1503: else if (rtxcode == GE) { fputs ("ge", file); return; } ! 1504: else if (rtxcode == GEU) { fputs ("ge", file); return; } ! 1505: else if (rtxcode == LE) { fputs ("le", file); return; } ! 1506: else if (rtxcode == LEU) { fputs ("le", file); return; } ! 1507: else abort (); ! 1508: break; ! 1509: ! 1510: case 0: ! 1511: output_addr_const (file, x); ! 1512: break; ! 1513: ! 1514: default: ! 1515: abort (); ! 1516: } ! 1517: ! 1518: return; ! 1519: } ! 1520: ! 1521: /* Print a memory address as an operand to reference that memory location. ! 1522: ! 1523: This is exactly the same as legitimate_address_p, except that it the prints ! 1524: addresses instead of recognizing them. */ ! 1525: ! 1526: void ! 1527: i960_print_operand_addr (file, addr) ! 1528: FILE *file; ! 1529: register rtx addr; ! 1530: { ! 1531: rtx breg, ireg; ! 1532: rtx scale, offset; ! 1533: ! 1534: ireg = 0; ! 1535: breg = 0; ! 1536: offset = 0; ! 1537: scale = const1_rtx; ! 1538: ! 1539: if (GET_CODE (addr) == REG) ! 1540: breg = addr; ! 1541: else if (CONSTANT_P (addr)) ! 1542: offset = addr; ! 1543: else if (GET_CODE (addr) == PLUS) ! 1544: { ! 1545: rtx op0, op1; ! 1546: ! 1547: op0 = XEXP (addr, 0); ! 1548: op1 = XEXP (addr, 1); ! 1549: ! 1550: if (GET_CODE (op0) == REG) ! 1551: { ! 1552: breg = op0; ! 1553: if (GET_CODE (op1) == REG) ! 1554: ireg = op1; ! 1555: else if (CONSTANT_P (op1)) ! 1556: offset = op1; ! 1557: else ! 1558: abort (); ! 1559: } ! 1560: else if (GET_CODE (op0) == PLUS) ! 1561: { ! 1562: if (GET_CODE (XEXP (op0, 0)) == MULT) ! 1563: { ! 1564: ireg = XEXP (XEXP (op0, 0), 0); ! 1565: scale = XEXP (XEXP (op0, 0), 1); ! 1566: if (GET_CODE (XEXP (op0, 1)) == REG) ! 1567: { ! 1568: breg = XEXP (op0, 1); ! 1569: offset = op1; ! 1570: } ! 1571: else ! 1572: abort (); ! 1573: } ! 1574: else if (GET_CODE (XEXP (op0, 0)) == REG) ! 1575: { ! 1576: breg = XEXP (op0, 0); ! 1577: if (GET_CODE (XEXP (op0, 1)) == REG) ! 1578: { ! 1579: ireg = XEXP (op0, 1); ! 1580: offset = op1; ! 1581: } ! 1582: else ! 1583: abort (); ! 1584: } ! 1585: else ! 1586: abort (); ! 1587: } ! 1588: else if (GET_CODE (op0) == MULT) ! 1589: { ! 1590: ireg = XEXP (op0, 0); ! 1591: scale = XEXP (op0, 1); ! 1592: if (GET_CODE (op1) == REG) ! 1593: breg = op1; ! 1594: else if (CONSTANT_P (op1)) ! 1595: offset = op1; ! 1596: else ! 1597: abort (); ! 1598: } ! 1599: else ! 1600: abort (); ! 1601: } ! 1602: else if (GET_CODE (addr) == MULT) ! 1603: { ! 1604: ireg = XEXP (addr, 0); ! 1605: scale = XEXP (addr, 1); ! 1606: } ! 1607: else ! 1608: abort (); ! 1609: ! 1610: if (offset) ! 1611: output_addr_const (file, offset); ! 1612: if (breg) ! 1613: fprintf (file, "(%s)", reg_names[REGNO (breg)]); ! 1614: if (ireg) ! 1615: fprintf (file, "[%s*%d]", reg_names[REGNO (ireg)], INTVAL (scale)); ! 1616: } ! 1617: ! 1618: /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression ! 1619: that is a valid memory address for an instruction. ! 1620: The MODE argument is the machine mode for the MEM expression ! 1621: that wants to use this address. ! 1622: ! 1623: On 80960, legitimate addresses are: ! 1624: base ld (g0),r0 ! 1625: disp (12 or 32 bit) ld foo,r0 ! 1626: base + index ld (g0)[g1*1],r0 ! 1627: base + displ ld 0xf00(g0),r0 ! 1628: base + index*scale + displ ld 0xf00(g0)[g1*4],r0 ! 1629: index*scale + base ld (g0)[g1*4],r0 ! 1630: index*scale + displ ld 0xf00[g1*4],r0 ! 1631: index*scale ld [g1*4],r0 ! 1632: index + base + displ ld 0xf00(g0)[g1*1],r0 ! 1633: ! 1634: In each case, scale can be 1, 2, 4, 8, or 16. */ ! 1635: ! 1636: /* This is exactly the same as i960_print_operand_addr, except that ! 1637: it recognizes addresses instead of printing them. ! 1638: ! 1639: It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should ! 1640: convert common non-canonical forms to canonical form so that they will ! 1641: be recognized. */ ! 1642: ! 1643: /* These two macros allow us to accept either a REG or a SUBREG anyplace ! 1644: where a register is valid. */ ! 1645: ! 1646: #define RTX_OK_FOR_BASE_P(X, STRICT) \ ! 1647: ((GET_CODE (X) == REG \ ! 1648: && (STRICT ? REG_OK_FOR_BASE_P_STRICT (X) : REG_OK_FOR_BASE_P (X))) \ ! 1649: || (GET_CODE (X) == SUBREG \ ! 1650: && GET_CODE (SUBREG_REG (X)) == REG \ ! 1651: && (STRICT ? REG_OK_FOR_BASE_P_STRICT (SUBREG_REG (X)) \ ! 1652: : REG_OK_FOR_BASE_P (SUBREG_REG (X))))) ! 1653: ! 1654: #define RTX_OK_FOR_INDEX_P(X, STRICT) \ ! 1655: ((GET_CODE (X) == REG \ ! 1656: && (STRICT ? REG_OK_FOR_INDEX_P_STRICT (X) : REG_OK_FOR_INDEX_P (X)))\ ! 1657: || (GET_CODE (X) == SUBREG \ ! 1658: && GET_CODE (SUBREG_REG (X)) == REG \ ! 1659: && (STRICT ? REG_OK_FOR_INDEX_P_STRICT (SUBREG_REG (X)) \ ! 1660: : REG_OK_FOR_INDEX_P (SUBREG_REG (X))))) ! 1661: ! 1662: int ! 1663: legitimate_address_p (mode, addr, strict) ! 1664: enum machine_mode mode; ! 1665: register rtx addr; ! 1666: int strict; ! 1667: { ! 1668: if (RTX_OK_FOR_BASE_P (addr, strict)) ! 1669: return 1; ! 1670: else if (CONSTANT_P (addr)) ! 1671: return 1; ! 1672: else if (GET_CODE (addr) == PLUS) ! 1673: { ! 1674: rtx op0, op1; ! 1675: ! 1676: if (! TARGET_COMPLEX_ADDR && ! reload_completed) ! 1677: return 0; ! 1678: ! 1679: op0 = XEXP (addr, 0); ! 1680: op1 = XEXP (addr, 1); ! 1681: ! 1682: if (RTX_OK_FOR_BASE_P (op0, strict)) ! 1683: { ! 1684: if (RTX_OK_FOR_INDEX_P (op1, strict)) ! 1685: return 1; ! 1686: else if (CONSTANT_P (op1)) ! 1687: return 1; ! 1688: else ! 1689: return 0; ! 1690: } ! 1691: else if (GET_CODE (op0) == PLUS) ! 1692: { ! 1693: if (GET_CODE (XEXP (op0, 0)) == MULT) ! 1694: { ! 1695: if (! (RTX_OK_FOR_INDEX_P (XEXP (XEXP (op0, 0), 0), strict) ! 1696: && SCALE_TERM_P (XEXP (XEXP (op0, 0), 1)))) ! 1697: return 0; ! 1698: ! 1699: if (RTX_OK_FOR_BASE_P (XEXP (op0, 1), strict) ! 1700: && CONSTANT_P (op1)) ! 1701: return 1; ! 1702: else ! 1703: return 0; ! 1704: } ! 1705: else if (RTX_OK_FOR_BASE_P (XEXP (op0, 0), strict)) ! 1706: { ! 1707: if (RTX_OK_FOR_INDEX_P (XEXP (op0, 1), strict) ! 1708: && CONSTANT_P (op1)) ! 1709: return 1; ! 1710: else ! 1711: return 0; ! 1712: } ! 1713: else ! 1714: return 0; ! 1715: } ! 1716: else if (GET_CODE (op0) == MULT) ! 1717: { ! 1718: if (! (RTX_OK_FOR_INDEX_P (XEXP (op0, 0), strict) ! 1719: && SCALE_TERM_P (XEXP (op0, 1)))) ! 1720: return 0; ! 1721: ! 1722: if (RTX_OK_FOR_BASE_P (op1, strict)) ! 1723: return 1; ! 1724: else if (CONSTANT_P (op1)) ! 1725: return 1; ! 1726: else ! 1727: return 0; ! 1728: } ! 1729: else ! 1730: return 0; ! 1731: } ! 1732: else if (GET_CODE (addr) == MULT) ! 1733: { ! 1734: if (! TARGET_COMPLEX_ADDR && ! reload_completed) ! 1735: return 0; ! 1736: ! 1737: return (RTX_OK_FOR_INDEX_P (XEXP (addr, 0), strict) ! 1738: && SCALE_TERM_P (XEXP (addr, 1))); ! 1739: } ! 1740: else ! 1741: return 0; ! 1742: } ! 1743: ! 1744: /* Try machine-dependent ways of modifying an illegitimate address ! 1745: to be legitimate. If we find one, return the new, valid address. ! 1746: This macro is used in only one place: `memory_address' in explow.c. ! 1747: ! 1748: This converts some non-canonical addresses to canonical form so they ! 1749: can be recognized. */ ! 1750: ! 1751: rtx ! 1752: legitimize_address (x, oldx, mode) ! 1753: register rtx x; ! 1754: register rtx oldx; ! 1755: enum machine_mode mode; ! 1756: { ! 1757: if (GET_CODE (x) == SYMBOL_REF) ! 1758: { ! 1759: abort (); ! 1760: x = copy_to_reg (x); ! 1761: } ! 1762: ! 1763: if (! TARGET_COMPLEX_ADDR && ! reload_completed) ! 1764: return x; ! 1765: ! 1766: /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const))) ! 1767: into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be ! 1768: created by virtual register instantiation, register elimination, and ! 1769: similar optimizations. */ ! 1770: if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT ! 1771: && GET_CODE (XEXP (x, 1)) == PLUS) ! 1772: x = gen_rtx (PLUS, Pmode, ! 1773: gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)), ! 1774: XEXP (XEXP (x, 1), 1)); ! 1775: ! 1776: /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) ! 1777: into (plus (plus (mult (reg) (const)) (reg)) (const)). */ ! 1778: else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS ! 1779: && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT ! 1780: && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS ! 1781: && CONSTANT_P (XEXP (x, 1))) ! 1782: { ! 1783: rtx constant, other; ! 1784: ! 1785: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 1786: { ! 1787: constant = XEXP (x, 1); ! 1788: other = XEXP (XEXP (XEXP (x, 0), 1), 1); ! 1789: } ! 1790: else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT) ! 1791: { ! 1792: constant = XEXP (XEXP (XEXP (x, 0), 1), 1); ! 1793: other = XEXP (x, 1); ! 1794: } ! 1795: else ! 1796: constant = 0; ! 1797: ! 1798: if (constant) ! 1799: x = gen_rtx (PLUS, Pmode, ! 1800: gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0), ! 1801: XEXP (XEXP (XEXP (x, 0), 1), 0)), ! 1802: plus_constant (other, INTVAL (constant))); ! 1803: } ! 1804: ! 1805: return x; ! 1806: } ! 1807: ! 1808: #if 0 ! 1809: /* Return the most stringent alignment that we are willing to consider ! 1810: objects of size SIZE and known alignment ALIGN as having. */ ! 1811: ! 1812: int ! 1813: i960_alignment (size, align) ! 1814: int size; ! 1815: int align; ! 1816: { ! 1817: int i; ! 1818: ! 1819: if (! TARGET_STRICT_ALIGN) ! 1820: if (TARGET_IC_COMPAT2_0 || align >= 4) ! 1821: { ! 1822: i = i960_object_bytes_bitalign (size) / BITS_PER_UNIT; ! 1823: if (i > align) ! 1824: align = i; ! 1825: } ! 1826: ! 1827: return align; ! 1828: } ! 1829: #endif ! 1830: ! 1831: /* Modes for condition codes. */ ! 1832: #define C_MODES \ ! 1833: ((1 << (int) CCmode) | (1 << (int) CC_UNSmode) | (1<< (int) CC_CHKmode)) ! 1834: ! 1835: /* Modes for single-word (and smaller) quantities. */ ! 1836: #define S_MODES \ ! 1837: (~C_MODES \ ! 1838: & ~ ((1 << (int) DImode) | (1 << (int) TImode) \ ! 1839: | (1 << (int) DFmode) | (1 << (int) TFmode))) ! 1840: ! 1841: /* Modes for double-word (and smaller) quantities. */ ! 1842: #define D_MODES \ ! 1843: (~C_MODES \ ! 1844: & ~ ((1 << (int) TImode) | (1 << (int) TFmode))) ! 1845: ! 1846: /* Modes for quad-word quantities. */ ! 1847: #define T_MODES (~C_MODES) ! 1848: ! 1849: /* Modes for single-float quantities. */ ! 1850: #define SF_MODES ((1 << (int) SFmode)) ! 1851: ! 1852: /* Modes for double-float quantities. */ ! 1853: #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode)) ! 1854: ! 1855: /* Modes for quad-float quantities. */ ! 1856: #define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode)) ! 1857: ! 1858: unsigned int hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] = { ! 1859: T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, ! 1860: T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, ! 1861: T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, ! 1862: T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, ! 1863: ! 1864: TF_MODES, TF_MODES, TF_MODES, TF_MODES, C_MODES}; ! 1865: ! 1866: ! 1867: /* Return the minimum alignment of an expression rtx X in bytes. This takes ! 1868: advantage of machine specific facts, such as knowing that the frame pointer ! 1869: is always 16 byte aligned. */ ! 1870: ! 1871: int ! 1872: i960_expr_alignment (x, size) ! 1873: rtx x; ! 1874: int size; ! 1875: { ! 1876: int align = 1; ! 1877: ! 1878: if (x == 0) ! 1879: return 1; ! 1880: ! 1881: switch (GET_CODE(x)) ! 1882: { ! 1883: case CONST_INT: ! 1884: align = INTVAL(x); ! 1885: ! 1886: if ((align & 0xf) == 0) ! 1887: align = 16; ! 1888: else if ((align & 0x7) == 0) ! 1889: align = 8; ! 1890: else if ((align & 0x3) == 0) ! 1891: align = 4; ! 1892: else if ((align & 0x1) == 0) ! 1893: align = 2; ! 1894: else ! 1895: align = 1; ! 1896: break; ! 1897: ! 1898: case PLUS: ! 1899: align = MIN (i960_expr_alignment (XEXP (x, 0), size), ! 1900: i960_expr_alignment (XEXP (x, 1), size)); ! 1901: break; ! 1902: ! 1903: case SYMBOL_REF: ! 1904: /* If this is a valid program, objects are guaranteed to be ! 1905: correctly aligned for whatever size the reference actually is. */ ! 1906: align = i960_object_bytes_bitalign (size) / BITS_PER_UNIT; ! 1907: break; ! 1908: ! 1909: case REG: ! 1910: if (REGNO (x) == FRAME_POINTER_REGNUM) ! 1911: align = 16; ! 1912: break; ! 1913: ! 1914: case ASHIFT: ! 1915: case LSHIFT: ! 1916: align = i960_expr_alignment (XEXP (x, 0)); ! 1917: ! 1918: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 1919: { ! 1920: align = align << INTVAL (XEXP (x, 1)); ! 1921: align = MIN (align, 16); ! 1922: } ! 1923: break; ! 1924: ! 1925: case MULT: ! 1926: align = (i960_expr_alignment (XEXP (x, 0), size) * ! 1927: i960_expr_alignment (XEXP (x, 1), size)); ! 1928: ! 1929: align = MIN (align, 16); ! 1930: break; ! 1931: } ! 1932: ! 1933: return align; ! 1934: } ! 1935: ! 1936: /* Return true if it is possible to reference both BASE and OFFSET, which ! 1937: have alignment at least as great as 4 byte, as if they had alignment valid ! 1938: for an object of size SIZE. */ ! 1939: ! 1940: int ! 1941: i960_improve_align (base, offset, size) ! 1942: rtx base; ! 1943: rtx offset; ! 1944: int size; ! 1945: { ! 1946: int i, j; ! 1947: ! 1948: /* We have at least a word reference to the object, so we know it has to ! 1949: be aligned at least to 4 bytes. */ ! 1950: ! 1951: i = MIN (i960_expr_alignment (base, 4), ! 1952: i960_expr_alignment (offset, 4)); ! 1953: ! 1954: i = MAX (i, 4); ! 1955: ! 1956: /* We know the size of the request. If strict align is not enabled, we ! 1957: can guess that the alignment is OK for the requested size. */ ! 1958: ! 1959: if (! TARGET_STRICT_ALIGN) ! 1960: if ((j = (i960_object_bytes_bitalign (size) / BITS_PER_UNIT)) > i) ! 1961: i = j; ! 1962: ! 1963: return (i >= size); ! 1964: } ! 1965: ! 1966: /* Return true if it is possible to access BASE and OFFSET, which have 4 byte ! 1967: (SImode) alignment as if they had 16 byte (TImode) alignment. */ ! 1968: ! 1969: int ! 1970: i960_si_ti (base, offset) ! 1971: rtx base; ! 1972: rtx offset; ! 1973: { ! 1974: return i960_improve_align (base, offset, 16); ! 1975: } ! 1976: ! 1977: /* Return true if it is possible to access BASE and OFFSET, which have 4 byte ! 1978: (SImode) alignment as if they had 8 byte (DImode) alignment. */ ! 1979: ! 1980: int ! 1981: i960_si_di (base, offset) ! 1982: rtx base; ! 1983: rtx offset; ! 1984: { ! 1985: return i960_improve_align (base, offset, 8); ! 1986: } ! 1987: ! 1988: /* Return raw values of size and alignment (in words) for the data ! 1989: type being accessed. These values will be rounded by the caller. */ ! 1990: ! 1991: static void ! 1992: i960_arg_size_and_align (mode, type, size_out, align_out) ! 1993: enum machine_mode mode; ! 1994: tree type; ! 1995: int *size_out; ! 1996: int *align_out; ! 1997: { ! 1998: int size, align; ! 1999: ! 2000: /* Use formal alignment requirements of type being passed, except make ! 2001: it at least a word. If we don't have a type, this is a library call, ! 2002: and the parm has to be of scalar type. In this case, consider its ! 2003: formal alignment requirement to be its size in words. */ ! 2004: ! 2005: if (mode == BLKmode) ! 2006: size = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ! 2007: else if (mode == VOIDmode) ! 2008: { ! 2009: /* End of parm list. */ ! 2010: assert (type != 0 && TYPE_MODE (type) == VOIDmode); ! 2011: size = 1; ! 2012: } ! 2013: else ! 2014: size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ! 2015: ! 2016: if (type == 0) ! 2017: align = size; ! 2018: else if (TYPE_ALIGN (type) >= BITS_PER_WORD) ! 2019: align = TYPE_ALIGN (type) / BITS_PER_WORD; ! 2020: else ! 2021: align = 1; ! 2022: ! 2023: *size_out = size; ! 2024: *align_out = align; ! 2025: } ! 2026: ! 2027: /* On the 80960 the first 12 args are in registers and the rest are pushed. ! 2028: Any arg that is bigger than 4 words is placed on the stack and all ! 2029: subsequent arguments are placed on the stack. ! 2030: ! 2031: Additionally, parameters with an alignment requirement stronger than ! 2032: a word must be be aligned appropriately. */ ! 2033: ! 2034: /* Update CUM to advance past an argument described by MODE and TYPE. */ ! 2035: ! 2036: void ! 2037: i960_function_arg_advance (cum, mode, type, named) ! 2038: CUMULATIVE_ARGS *cum; ! 2039: enum machine_mode mode; ! 2040: tree type; ! 2041: int named; ! 2042: { ! 2043: int size, align; ! 2044: ! 2045: i960_arg_size_and_align (mode, type, &size, &align); ! 2046: ! 2047: if (named == 0 || size > 4 || cum->ca_nstackparms != 0 ! 2048: || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS ! 2049: || MUST_PASS_IN_STACK (mode, type)) ! 2050: cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align) + size; ! 2051: else ! 2052: cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align) + size; ! 2053: } ! 2054: ! 2055: /* Return the register that the argument described by MODE and TYPE is ! 2056: passed in, or else return 0 if it is passed on the stack. */ ! 2057: ! 2058: rtx ! 2059: i960_function_arg (cum, mode, type, named) ! 2060: CUMULATIVE_ARGS *cum; ! 2061: enum machine_mode mode; ! 2062: tree type; ! 2063: int named; ! 2064: { ! 2065: rtx ret; ! 2066: int size, align; ! 2067: ! 2068: i960_arg_size_and_align (mode, type, &size, &align); ! 2069: ! 2070: if (named == 0 || size > 4 || cum->ca_nstackparms != 0 ! 2071: || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS ! 2072: || MUST_PASS_IN_STACK (mode, type)) ! 2073: { ! 2074: cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align); ! 2075: ret = 0; ! 2076: } ! 2077: else ! 2078: { ! 2079: cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align); ! 2080: ret = gen_rtx (REG, mode, cum->ca_nregparms); ! 2081: } ! 2082: ! 2083: return ret; ! 2084: } ! 2085: ! 2086: /* Floating-point support. */ ! 2087: ! 2088: void ! 2089: i960_output_double (file, value) ! 2090: FILE *file; ! 2091: double value; ! 2092: { ! 2093: if (REAL_VALUE_ISINF (value)) ! 2094: { ! 2095: fprintf (file, "\t.word 0\n"); ! 2096: fprintf (file, "\t.word 0x7ff00000 # Infinity\n"); ! 2097: } ! 2098: else ! 2099: fprintf (file, "\t.double 0d%.17e\n", (value)); ! 2100: } ! 2101: ! 2102: void ! 2103: i960_output_float (file, value) ! 2104: FILE *file; ! 2105: double value; ! 2106: { ! 2107: if (REAL_VALUE_ISINF (value)) ! 2108: fprintf (file, "\t.word 0x7f800000 # Infinity\n"); ! 2109: else ! 2110: fprintf (file, "\t.float 0f%.12e\n", (value)); ! 2111: } ! 2112: ! 2113: /* Return the number of bits that an object of size N bytes is aligned to. */ ! 2114: ! 2115: int ! 2116: i960_object_bytes_bitalign (n) ! 2117: int n; ! 2118: { ! 2119: if (n > 8) n = 128; ! 2120: else if (n > 4) n = 64; ! 2121: else if (n > 2) n = 32; ! 2122: else if (n > 1) n = 16; ! 2123: else n = 8; ! 2124: ! 2125: return n; ! 2126: } ! 2127: ! 2128: /* Compute the size of an aggregate type TSIZE. */ ! 2129: ! 2130: tree ! 2131: i960_round_size (tsize) ! 2132: tree tsize; ! 2133: { ! 2134: int size, byte_size, align; ! 2135: ! 2136: if (TREE_CODE (tsize) != INTEGER_CST) ! 2137: return tsize; ! 2138: ! 2139: size = TREE_INT_CST_LOW (tsize); ! 2140: byte_size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; ! 2141: align = i960_object_bytes_bitalign (byte_size); ! 2142: ! 2143: /* Handle #pragma align. */ ! 2144: if (align > i960_maxbitalignment) ! 2145: align = i960_maxbitalignment; ! 2146: ! 2147: if (size % align) ! 2148: size = ((size / align) + 1) * align; ! 2149: ! 2150: return size_int (size); ! 2151: } ! 2152: ! 2153: /* Compute the alignment for an aggregate type TSIZE. */ ! 2154: ! 2155: int ! 2156: i960_round_align (align, tsize) ! 2157: int align; ! 2158: tree tsize; ! 2159: { ! 2160: int byte_size; ! 2161: ! 2162: if (TREE_CODE (tsize) != INTEGER_CST) ! 2163: return align; ! 2164: ! 2165: byte_size = (TREE_INT_CST_LOW (tsize) + BITS_PER_UNIT - 1) / BITS_PER_UNIT; ! 2166: align = i960_object_bytes_bitalign (byte_size); ! 2167: return align; ! 2168: } ! 2169: ! 2170: /* Do any needed setup for a varargs function. For the i960, we must ! 2171: create a register parameter block if one doesn't exist, and then copy ! 2172: all register parameters to memory. */ ! 2173: ! 2174: void ! 2175: i960_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) ! 2176: CUMULATIVE_ARGS *cum; ! 2177: enum machine_mode mode; ! 2178: tree type; ! 2179: int *pretend_size; ! 2180: int no_rtl; ! 2181: { ! 2182: if (cum->ca_nregparms < NPARM_REGS) ! 2183: { ! 2184: int first_reg_offset = cum->ca_nregparms; ! 2185: ! 2186: if (first_reg_offset > NPARM_REGS) ! 2187: first_reg_offset = NPARM_REGS; ! 2188: ! 2189: if (! (no_rtl) && first_reg_offset != NPARM_REGS) ! 2190: { ! 2191: rtx label = gen_label_rtx (); ! 2192: emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx)); ! 2193: emit_jump_insn (gen_bne (label)); ! 2194: emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx, ! 2195: stack_pointer_rtx)); ! 2196: emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx, ! 2197: memory_address (SImode, ! 2198: plus_constant (stack_pointer_rtx, ! 2199: 48)))); ! 2200: emit_label (label); ! 2201: move_block_from_reg ! 2202: (first_reg_offset, ! 2203: gen_rtx (MEM, BLKmode, virtual_incoming_args_rtx), ! 2204: NPARM_REGS - first_reg_offset, ! 2205: (NPARM_REGS - first_reg_offset) * UNITS_PER_WORD); ! 2206: } ! 2207: *pretend_size = (NPARM_REGS - first_reg_offset) * UNITS_PER_WORD; ! 2208: } ! 2209: } ! 2210: ! 2211: /* Calculate the final size of the reg parm stack space for the current ! 2212: function, based on how many bytes would be allocated on the stack. */ ! 2213: ! 2214: int ! 2215: i960_final_reg_parm_stack_space (const_size, var_size) ! 2216: int const_size; ! 2217: tree var_size; ! 2218: { ! 2219: if (var_size || const_size > 48) ! 2220: return 48; ! 2221: else ! 2222: return 0; ! 2223: } ! 2224: ! 2225: /* Calculate the size of the reg parm stack space. This is a bit complicated ! 2226: on the i960. */ ! 2227: ! 2228: int ! 2229: i960_reg_parm_stack_space (fndecl) ! 2230: tree fndecl; ! 2231: { ! 2232: /* In this case, we are called from emit_library_call, and we don't need ! 2233: to pretend we have more space for parameters than what's apparent. */ ! 2234: if (fndecl == 0) ! 2235: return 0; ! 2236: ! 2237: /* In this case, we are called from locate_and_pad_parms when we're ! 2238: not IN_REGS, so we have an arg block. */ ! 2239: if (fndecl != current_function_decl) ! 2240: return 48; ! 2241: ! 2242: /* Otherwise, we have an arg block if the current function has more than ! 2243: 48 bytes of parameters. */ ! 2244: if (current_function_args_size != 0) ! 2245: return 48; ! 2246: else ! 2247: return 0; ! 2248: } ! 2249: ! 2250: /* Return the register class of a scratch register needed to copy IN into ! 2251: or out of a register in CLASS in MODE. If it can be done directly, ! 2252: NO_REGS is returned. */ ! 2253: ! 2254: enum reg_class ! 2255: secondary_reload_class (class, mode, in) ! 2256: enum reg_class class; ! 2257: enum machine_mode mode; ! 2258: rtx in; ! 2259: { ! 2260: int regno = -1; ! 2261: ! 2262: if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) ! 2263: regno = true_regnum (in); ! 2264: ! 2265: /* We can place anything into LOCAL_OR_GLOBAL_REGS and can put ! 2266: LOCAL_OR_GLOBAL_REGS into anything. */ ! 2267: if (class == LOCAL_OR_GLOBAL_REGS || class == LOCAL_REGS ! 2268: || class == GLOBAL_REGS || (regno >= 0 && regno < 32)) ! 2269: return NO_REGS; ! 2270: ! 2271: /* We can place any hard register, 0.0, and 1.0 into FP_REGS. */ ! 2272: if (class == FP_REGS ! 2273: && ((regno >= 0 && regno < FIRST_PSEUDO_REGISTER) ! 2274: || in == CONST0_RTX (mode) || in == CONST1_RTX (mode))) ! 2275: return NO_REGS; ! 2276: ! 2277: return LOCAL_OR_GLOBAL_REGS; ! 2278: } ! 2279: ! 2280: /* Look at the opcode P, and set i96_last_insn_type to indicate which ! 2281: function unit it executed on. */ ! 2282: ! 2283: /* ??? This would make more sense as an attribute. */ ! 2284: ! 2285: void ! 2286: i960_scan_opcode (p) ! 2287: char *p; ! 2288: { ! 2289: switch (*p) ! 2290: { ! 2291: case 'a': ! 2292: case 'd': ! 2293: case 'e': ! 2294: case 'm': ! 2295: case 'n': ! 2296: case 'o': ! 2297: case 'r': ! 2298: /* Ret is not actually of type REG, but it won't matter, because no ! 2299: insn will ever follow it. */ ! 2300: case 'u': ! 2301: case 'x': ! 2302: i960_last_insn_type = I_TYPE_REG; ! 2303: break; ! 2304: ! 2305: case 'b': ! 2306: if (p[1] == 'x' || p[3] == 'x') ! 2307: i960_last_insn_type = I_TYPE_MEM; ! 2308: i960_last_insn_type = I_TYPE_CTRL; ! 2309: break; ! 2310: ! 2311: case 'f': ! 2312: case 't': ! 2313: i960_last_insn_type = I_TYPE_CTRL; ! 2314: break; ! 2315: ! 2316: case 'c': ! 2317: if (p[1] == 'a') ! 2318: { ! 2319: if (p[4] == 'x') ! 2320: i960_last_insn_type = I_TYPE_MEM; ! 2321: else ! 2322: i960_last_insn_type = I_TYPE_CTRL; ! 2323: } ! 2324: else if (p[1] == 'm') ! 2325: { ! 2326: if (p[3] == 'd') ! 2327: i960_last_insn_type = I_TYPE_REG; ! 2328: else if (p[4] == 'b' || p[4] == 'j') ! 2329: i960_last_insn_type = I_TYPE_CTRL; ! 2330: else ! 2331: i960_last_insn_type = I_TYPE_REG; ! 2332: } ! 2333: else ! 2334: i960_last_insn_type = I_TYPE_REG; ! 2335: break; ! 2336: ! 2337: case 'l': ! 2338: i960_last_insn_type = I_TYPE_MEM; ! 2339: break; ! 2340: ! 2341: case 's': ! 2342: if (p[1] == 't') ! 2343: i960_last_insn_type = I_TYPE_MEM; ! 2344: else ! 2345: i960_last_insn_type = I_TYPE_REG; ! 2346: break; ! 2347: } ! 2348: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.