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