|
|
1.1.1.4 ! root 1: /* Output routines for GCC for Hitachi Super-H. ! 2: Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. 1.1 root 3: 1.1.1.4 ! root 4: This file is part of GNU CC. 1.1 root 5: 1.1.1.4 ! root 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 59 Temple Place - Suite 330, ! 19: Boston, MA 02111-1307, USA. */ 1.1.1.3 root 20: 1.1.1.4 ! root 21: /* Contributed by Steve Chamberlain ([email protected]). ! 22: Improved by Jim Wilson ([email protected]). */ 1.1.1.3 root 23: 1.1.1.4 ! root 24: #include "config.h" 1.1 root 25: 26: #include <stdio.h> 1.1.1.4 ! root 27: 1.1 root 28: #include "rtl.h" 29: #include "tree.h" 30: #include "flags.h" 1.1.1.4 ! root 31: #include "insn-flags.h" 1.1 root 32: #include "expr.h" 1.1.1.4 ! root 33: #include "regs.h" ! 34: #include "hard-reg-set.h" ! 35: #include "output.h" 1.1 root 36: 1.1.1.4 ! root 37: #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0) ! 38: #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1) 1.1 root 39: 1.1.1.4 ! root 40: /* ??? The pragma interrupt support will not work for SH3. */ ! 41: /* This is set by #pragma interrupt and #pragma trapa, and causes gcc to ! 42: output code for the next function appropriate for an interrupt handler. */ 1.1.1.3 root 43: int pragma_interrupt; 1.1 root 44: 1.1.1.4 ! root 45: /* This is set by #pragma trapa, and is similar to the above, except that ! 46: the compiler doesn't emit code to preserve all registers. */ ! 47: static int pragma_trapa; ! 48: ! 49: /* This is used for communication between SETUP_INCOMING_VARARGS and ! 50: sh_expand_prologue. */ 1.1 root 51: int current_function_anonymous_args; 1.1.1.2 root 52: 1.1.1.4 ! root 53: /* Global variables from toplev.c and final.c that are used within, but ! 54: not declared in any header file. */ ! 55: extern char *version_string; ! 56: extern int *insn_addresses; 1.1 root 57: 58: /* Global variables for machine-dependent things. */ 59: 1.1.1.4 ! root 60: /* Which cpu are we scheduling for. */ ! 61: enum processor_type sh_cpu; ! 62: 1.1 root 63: /* Saved operands from the last compare to use when we generate an scc 1.1.1.4 ! root 64: or bcc insn. */ 1.1 root 65: 66: rtx sh_compare_op0; 67: rtx sh_compare_op1; 68: 69: /* Provides the class number of the smallest class containing 1.1.1.4 ! root 70: reg number. */ 1.1 root 71: 72: int regno_reg_class[FIRST_PSEUDO_REGISTER] = 73: { 74: R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, 75: GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, 76: GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, 77: GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, 1.1.1.3 root 78: GENERAL_REGS, PR_REGS, T_REGS, NO_REGS, 79: MAC_REGS, MAC_REGS, 1.1 root 80: }; 81: 82: /* Provide reg_class from a letter such as appears in the machine 1.1.1.4 ! root 83: description. */ 1.1 root 84: 85: enum reg_class reg_class_from_letter[] = 86: { 87: /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS, 88: /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS, 89: /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS, 90: /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS, 91: /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS, 92: /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS, 93: /* y */ NO_REGS, /* z */ R0_REGS 94: }; 1.1.1.2 root 95: 1.1.1.4 ! root 96: /* Print the operand address in x to the stream. */ 1.1 root 97: 98: void 99: print_operand_address (stream, x) 100: FILE *stream; 101: rtx x; 102: { 103: switch (GET_CODE (x)) 104: { 105: case REG: 106: fprintf (stream, "@%s", reg_names[REGNO (x)]); 107: break; 1.1.1.4 ! root 108: 1.1 root 109: case PLUS: 110: { 111: rtx base = XEXP (x, 0); 112: rtx index = XEXP (x, 1); 113: 114: switch (GET_CODE (index)) 115: { 116: case CONST_INT: 1.1.1.4 ! root 117: fprintf (stream, "@(%d,%s)", INTVAL (index), 1.1 root 118: reg_names[REGNO (base)]); 119: break; 120: 121: case REG: 1.1.1.2 root 122: fprintf (stream, "@(r0,%s)", 123: reg_names[MAX (REGNO (base), REGNO (index))]); 1.1 root 124: break; 125: 126: default: 1.1.1.2 root 127: debug_rtx (x); 1.1 root 128: abort (); 129: } 130: } 131: break; 1.1.1.4 ! root 132: 1.1 root 133: case PRE_DEC: 134: fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]); 135: break; 136: 137: case POST_INC: 138: fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]); 139: break; 140: 141: default: 142: output_addr_const (stream, x); 143: break; 144: } 145: } 146: 147: /* Print operand x (an rtx) in assembler syntax to file stream 148: according to modifier code. 149: 1.1.1.2 root 150: '.' print a .s if insn needs delay slot 1.1.1.3 root 151: '@' print rte or rts depending upon pragma interruptness 1.1.1.4 ! root 152: '#' output a nop if there is nothing to put in the delay slot 1.1.1.2 root 153: 'O' print a constant without the # 1.1.1.4 ! root 154: 'R' print the LSW of a dp value - changes if in little endian ! 155: 'S' print the MSW of a dp value - changes if in little endian ! 156: 'T' print the next word of a dp value - same as 'R' in big endian mode. */ 1.1 root 157: 158: void 159: print_operand (stream, x, code) 160: FILE *stream; 161: rtx x; 162: int code; 163: { 164: switch (code) 165: { 1.1.1.2 root 166: case '.': 1.1.1.4 ! root 167: if (final_sequence ! 168: && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) 1.1.1.2 root 169: fprintf (stream, ".s"); 170: break; 1.1.1.3 root 171: case '@': 172: if (pragma_interrupt) 173: fprintf (stream, "rte"); 174: else 175: fprintf (stream, "rts"); 176: break; 1.1 root 177: case '#': 1.1.1.4 ! root 178: /* Output a nop if there's nothing in the delay slot. */ 1.1 root 179: if (dbr_sequence_length () == 0) 1.1.1.4 ! root 180: fprintf (stream, "\n\tnop"); 1.1 root 181: break; 1.1.1.2 root 182: case 'O': 1.1.1.3 root 183: output_addr_const (stream, x); 1.1 root 184: break; 1.1.1.4 ! root 185: case 'R': ! 186: fputs (reg_names[REGNO (x) + LSW], (stream)); 1.1.1.2 root 187: break; 1.1.1.4 ! root 188: case 'S': ! 189: fputs (reg_names[REGNO (x) + MSW], (stream)); 1.1.1.3 root 190: break; 1.1.1.4 ! root 191: case 'T': ! 192: /* Next word of a double. */ 1.1 root 193: switch (GET_CODE (x)) 194: { 195: case REG: 196: fputs (reg_names[REGNO (x) + 1], (stream)); 197: break; 198: case MEM: 1.1.1.4 ! root 199: print_operand_address (stream, ! 200: XEXP (adj_offsettable_operand (x, 4), 0)); 1.1 root 201: break; 202: } 203: break; 204: default: 205: switch (GET_CODE (x)) 206: { 207: case REG: 208: fputs (reg_names[REGNO (x)], (stream)); 209: break; 210: case MEM: 211: output_address (XEXP (x, 0)); 212: break; 213: default: 214: fputc ('#', stream); 215: output_addr_const (stream, x); 216: break; 217: } 218: break; 219: } 220: } 221: 1.1.1.3 root 222: /* Emit code to perform a block move. Choose the best method. 223: 224: OPERANDS[0] is the destination. 225: OPERANDS[1] is the source. 226: OPERANDS[2] is the size. 227: OPERANDS[3] is the alignment safe to use. */ 228: 229: int 230: expand_block_move (operands) 231: rtx *operands; 232: { 233: int align = INTVAL (operands[3]); 234: int constp = (GET_CODE (operands[2]) == CONST_INT); 235: int bytes = (constp ? INTVAL (operands[2]) : 0); 236: 1.1.1.4 ! root 237: /* If it isn't a constant number of bytes, or if it doesn't have 4 byte ! 238: alignment, or if it isn't a multiple of 4 bytes, then fail. */ ! 239: if (! constp || align < 4 || (bytes % 4 != 0)) 1.1.1.3 root 240: return 0; 241: 1.1.1.4 ! root 242: if (bytes < 64) 1.1.1.3 root 243: { 244: char entry[30]; 245: tree entry_name; 246: rtx func_addr_rtx; 247: rtx r4 = gen_rtx (REG, SImode, 4); 248: rtx r5 = gen_rtx (REG, SImode, 5); 1.1.1.4 ! root 249: ! 250: sprintf (entry, "__movstrSI%d", bytes); 1.1.1.3 root 251: entry_name = get_identifier (entry); 252: 1.1.1.4 ! root 253: func_addr_rtx ! 254: = copy_to_mode_reg (Pmode, ! 255: gen_rtx (SYMBOL_REF, Pmode, ! 256: IDENTIFIER_POINTER (entry_name))); 1.1.1.3 root 257: emit_insn (gen_move_insn (r4, XEXP (operands[0], 0))); 258: emit_insn (gen_move_insn (r5, XEXP (operands[1], 0))); 259: emit_insn (gen_block_move_real (func_addr_rtx)); 260: return 1; 261: } 1.1.1.4 ! root 262: ! 263: /* This is the same number of bytes as a memcpy call, but to a different ! 264: less common function name, so this will occasionally use more space. */ ! 265: if (! TARGET_SMALLCODE) 1.1.1.3 root 266: { 267: tree entry_name; 268: rtx func_addr_rtx; 1.1.1.4 ! root 269: int final_switch, while_loop; 1.1.1.3 root 270: rtx r4 = gen_rtx (REG, SImode, 4); 271: rtx r5 = gen_rtx (REG, SImode, 5); 272: rtx r6 = gen_rtx (REG, SImode, 6); 273: 1.1.1.4 ! root 274: entry_name = get_identifier ("__movstr"); ! 275: func_addr_rtx ! 276: = copy_to_mode_reg (Pmode, ! 277: gen_rtx (SYMBOL_REF, Pmode, ! 278: IDENTIFIER_POINTER (entry_name))); 1.1.1.3 root 279: emit_insn (gen_move_insn (r4, XEXP (operands[0], 0))); 280: emit_insn (gen_move_insn (r5, XEXP (operands[1], 0))); 281: 1.1.1.4 ! root 282: /* r6 controls the size of the move. 16 is decremented from it ! 283: for each 64 bytes moved. Then the negative bit left over is used ! 284: as an index into a list of move instructions. e.g., a 72 byte move ! 285: would be set up with size(r6) = 14, for one iteration through the ! 286: big while loop, and a switch of -2 for the last part. */ ! 287: ! 288: final_switch = 16 - ((bytes / 4) % 16); ! 289: while_loop = ((bytes / 4) / 16 - 1) * 16; ! 290: emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch))); ! 291: emit_insn (gen_block_lump_real (func_addr_rtx)); ! 292: return 1; 1.1.1.3 root 293: } 294: 295: return 0; 296: } 297: 1.1 root 298: /* Prepare operands for a move define_expand; specifically, one of the 1.1.1.4 ! root 299: operands must be in a register. */ 1.1 root 300: 1.1.1.2 root 301: int 1.1 root 302: prepare_move_operands (operands, mode) 303: rtx operands[]; 304: enum machine_mode mode; 305: { 1.1.1.4 ! root 306: /* Copy the source to a register if both operands aren't registers. */ ! 307: if (! reload_in_progress && ! reload_completed ! 308: && ! register_operand (operands[0], mode) ! 309: && ! register_operand (operands[1], mode)) ! 310: operands[1] = copy_to_mode_reg (mode, operands[1]); ! 311: ! 312: return 0; ! 313: } ! 314: ! 315: /* Prepare the operands for an scc instruction; make sure that the ! 316: compare has been done. */ ! 317: rtx ! 318: prepare_scc_operands (code) ! 319: enum rtx_code code; ! 320: { ! 321: rtx t_reg = gen_rtx (REG, SImode, T_REG); ! 322: enum rtx_code oldcode = code; ! 323: enum machine_mode mode; ! 324: ! 325: /* First need a compare insn. */ ! 326: switch (code) 1.1 root 327: { 1.1.1.4 ! root 328: case NE: ! 329: /* It isn't possible to handle this case. */ ! 330: abort (); ! 331: case LT: ! 332: code = GT; ! 333: break; ! 334: case LE: ! 335: code = GE; ! 336: break; ! 337: case LTU: ! 338: code = GTU; ! 339: break; ! 340: case LEU: ! 341: code = GEU; ! 342: break; 1.1 root 343: } 1.1.1.4 ! root 344: if (code != oldcode) 1.1.1.3 root 345: { 1.1.1.4 ! root 346: rtx tmp = sh_compare_op0; ! 347: sh_compare_op0 = sh_compare_op1; ! 348: sh_compare_op1 = tmp; 1.1.1.3 root 349: } 1.1.1.2 root 350: 1.1.1.4 ! root 351: mode = GET_MODE (sh_compare_op0); ! 352: if (mode == VOIDmode) ! 353: mode = GET_MODE (sh_compare_op1); 1.1.1.3 root 354: 1.1.1.4 ! root 355: sh_compare_op0 = force_reg (mode, sh_compare_op0); ! 356: if (code != EQ && code != NE ! 357: && (sh_compare_op1 != const0_rtx ! 358: || code == GTU || code == GEU || code == LTU || code == LEU)) ! 359: sh_compare_op1 = force_reg (mode, sh_compare_op1); 1.1.1.3 root 360: 1.1.1.4 ! root 361: emit_insn (gen_rtx (SET, VOIDmode, t_reg, ! 362: gen_rtx (code, SImode, sh_compare_op0, ! 363: sh_compare_op1))); 1.1.1.3 root 364: 1.1.1.4 ! root 365: return t_reg; 1.1 root 366: } 367: 1.1.1.4 ! root 368: /* Called from the md file, set up the operands of a compare instruction. */ ! 369: ! 370: void ! 371: from_compare (operands, code) ! 372: rtx *operands; 1.1.1.3 root 373: int code; 1.1 root 374: { 1.1.1.4 ! root 375: if (code != EQ && code != NE) 1.1 root 376: { 1.1.1.4 ! root 377: /* Force args into regs, since we can't use constants here. */ 1.1.1.3 root 378: sh_compare_op0 = force_reg (SImode, sh_compare_op0); 1.1.1.4 ! root 379: if (sh_compare_op1 != const0_rtx ! 380: || code == GTU || code == GEU || code == LTU || code == LEU) ! 381: sh_compare_op1 = force_reg (SImode, sh_compare_op1); 1.1 root 382: } 1.1.1.4 ! root 383: operands[1] = sh_compare_op0; ! 384: operands[2] = sh_compare_op1; 1.1 root 385: } 386: 1.1.1.4 ! root 387: /* Functions to output assembly code. */ 1.1 root 388: 1.1.1.2 root 389: /* Return a sequence of instructions to perform DI or DF move. 1.1 root 390: 1.1.1.2 root 391: Since the SH cannot move a DI or DF in one instruction, we have 1.1.1.4 ! root 392: to take care when we see overlapping source and dest registers. */ 1.1.1.3 root 393: 1.1 root 394: char * 1.1.1.3 root 395: output_movedouble (insn, operands, mode) 396: rtx insn; 1.1 root 397: rtx operands[]; 398: enum machine_mode mode; 399: { 1.1.1.2 root 400: rtx dst = operands[0]; 401: rtx src = operands[1]; 402: 1.1.1.3 root 403: if (GET_CODE (dst) == MEM 1.1.1.4 ! root 404: && GET_CODE (XEXP (dst, 0)) == PRE_DEC) ! 405: return "mov.l %T1,%0\n\tmov.l %1,%0"; ! 406: 1.1.1.2 root 407: if (register_operand (dst, mode) 408: && register_operand (src, mode)) 1.1 root 409: { 1.1.1.2 root 410: if (REGNO (src) == MACH_REG) 1.1.1.4 ! root 411: return "sts mach,%S0\n\tsts macl,%R0"; 1.1 root 412: 1.1.1.4 ! root 413: /* When mov.d r1,r2 do r2->r3 then r1->r2; ! 414: when mov.d r1,r0 do r1->r0 then r2->r1. */ 1.1.1.2 root 415: 416: if (REGNO (src) + 1 == REGNO (dst)) 1.1.1.4 ! root 417: return "mov %T1,%T0\n\tmov %1,%0"; 1.1.1.2 root 418: else 1.1.1.4 ! root 419: return "mov %1,%0\n\tmov %T1,%T0"; 1.1.1.2 root 420: } 421: else if (GET_CODE (src) == CONST_INT) 1.1 root 422: { 1.1.1.4 ! root 423: if (INTVAL (src) < 0) ! 424: output_asm_insn ("mov #-1,%S0", operands); 1.1 root 425: else 1.1.1.4 ! root 426: output_asm_insn ("mov #0,%S0", operands); 1.1 root 427: 1.1.1.4 ! root 428: return "mov %1,%R0"; 1.1.1.3 root 429: } 1.1.1.2 root 430: else if (GET_CODE (src) == MEM) 1.1 root 431: { 1.1.1.4 ! root 432: int ptrreg = -1; 1.1.1.2 root 433: int dreg = REGNO (dst); 434: rtx inside = XEXP (src, 0); 1.1 root 435: 436: if (GET_CODE (inside) == REG) 1.1.1.4 ! root 437: ptrreg = REGNO (inside); ! 438: else if (GET_CODE (inside) == SUBREG) ! 439: ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside); 1.1 root 440: else if (GET_CODE (inside) == PLUS) 441: { 1.1.1.4 ! root 442: ptrreg = REGNO (XEXP (inside, 0)); ! 443: /* ??? A r0+REG address shouldn't be possible here, because it isn't ! 444: an offsettable address. Unfortunately, offsettable addresses use ! 445: QImode to check the offset, and a QImode offsettable address ! 446: requires r0 for the other operand, which is not currently ! 447: supported, so we can't use the 'o' constraint. ! 448: Thus we must check for and handle r0+REG addresses here. ! 449: We punt for now, since this is likely very rare. */ ! 450: if (GET_CODE (XEXP (inside, 1)) == REG) ! 451: abort (); 1.1 root 452: } 1.1.1.3 root 453: else if (GET_CODE (inside) == LABEL_REF) 1.1.1.4 ! root 454: return "mov.l %1,%0\n\tmov.l %1+4,%T0"; 1.1.1.3 root 455: else if (GET_CODE (inside) == POST_INC) 1.1.1.4 ! root 456: return "mov.l %1,%0\n\tmov.l %1,%T0"; 1.1 root 457: else 458: abort (); 459: 1.1.1.4 ! root 460: /* Work out the safe way to copy. Copy into the second half first. */ ! 461: if (dreg == ptrreg) ! 462: return "mov.l %T1,%T0\n\tmov.l %1,%0"; 1.1 root 463: } 464: 1.1.1.4 ! root 465: return "mov.l %1,%0\n\tmov.l %T1,%T0"; 1.1 root 466: } 467: 1.1.1.4 ! root 468: /* Print an instruction which would have gone into a delay slot after ! 469: another instruction, but couldn't because the other instruction expanded ! 470: into a sequence where putting the slot insn at the end wouldn't work. */ 1.1.1.2 root 471: 1.1.1.4 ! root 472: static void ! 473: print_slot (insn) ! 474: rtx insn; 1.1 root 475: { 1.1.1.4 ! root 476: final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1); 1.1.1.3 root 477: 1.1.1.4 ! root 478: INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; 1.1.1.3 root 479: } 480: 1.1.1.4 ! root 481: /* We can't tell if we need a register as a scratch for the jump ! 482: until after branch shortening, and then it's too late to allocate a ! 483: register the 'proper' way. These instruction sequences are rare ! 484: anyway, so to avoid always using a reg up from our limited set, we'll ! 485: grab one when we need one on output. */ 1.1.1.3 root 486: 1.1.1.4 ! root 487: /* ??? Should fix compiler so that using a clobber scratch in jump ! 488: instructions works, and then this will be unnecessary. */ 1.1.1.3 root 489: 490: char * 491: output_far_jump (insn, op) 492: rtx insn; 493: rtx op; 494: { 495: rtx thislab = gen_label_rtx (); 496: 1.1.1.4 ! root 497: /* Output the delay slot insn first if any. */ 1.1.1.3 root 498: if (dbr_sequence_length ()) 1.1.1.4 ! root 499: print_slot (final_sequence); 1.1.1.2 root 500: 1.1.1.4 ! root 501: output_asm_insn ("mov.l r13,@-r15", 0); ! 502: output_asm_insn ("mov.l %O0,r13", &thislab); ! 503: output_asm_insn ("jmp @r13", 0); ! 504: output_asm_insn ("mov.l @r15+,r13", 0); 1.1.1.3 root 505: output_asm_insn (".align 2", 0); 506: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab)); 507: output_asm_insn (".long %O0", &op); 508: return ""; 509: } 1.1 root 510: 1.1.1.4 ! root 511: /* Local label counter, used for constants in the pool and inside ! 512: pattern branches. */ ! 513: ! 514: static int lf = 100; ! 515: ! 516: /* Output code for ordinary branches. */ ! 517: 1.1 root 518: char * 1.1.1.4 ! root 519: output_branch (logic, insn, operands) 1.1 root 520: int logic; 1.1.1.2 root 521: rtx insn; 1.1.1.4 ! root 522: rtx *operands; 1.1 root 523: { 524: int label = lf++; 1.1.1.3 root 525: 1.1 root 526: switch (get_attr_length (insn)) 527: { 528: case 2: 1.1.1.4 ! root 529: /* A branch with an unfilled delay slot. */ ! 530: case 4: ! 531: /* Simple branch in range -252..+258 bytes */ 1.1.1.2 root 532: return logic ? "bt%. %l0" : "bf%. %l0"; 1.1 root 533: 534: case 6: 1.1.1.4 ! root 535: /* A branch with an unfilled delay slot. */ ! 536: case 8: ! 537: /* Branch in range -4092..+4098 bytes. */ 1.1.1.2 root 538: { 1.1.1.4 ! root 539: /* The call to print_slot will clobber the operands. */ ! 540: rtx op0 = operands[0]; 1.1.1.2 root 541: 1.1.1.4 ! root 542: /* If the instruction in the delay slot is annulled (true), then ! 543: there is no delay slot where we can put it now. The only safe ! 544: place for it is after the label. */ 1.1.1.2 root 545: 1.1.1.4 ! root 546: if (final_sequence) 1.1.1.2 root 547: { 1.1.1.4 ! root 548: fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't', ! 549: INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) ! 550: ? "" : ".s", label); ! 551: if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) ! 552: print_slot (final_sequence); 1.1.1.2 root 553: } 554: else 1.1.1.4 ! root 555: fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label); 1.1.1.2 root 556: 1.1.1.4 ! root 557: output_asm_insn ("bra %l0", &op0); ! 558: fprintf (asm_out_file, "\tnop\n"); 1.1.1.2 root 559: fprintf (asm_out_file, "LF%d:\n", label); 1.1.1.4 ! root 560: ! 561: if (final_sequence ! 562: && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) ! 563: print_slot (final_sequence); 1.1.1.2 root 564: } 1.1 root 565: return ""; 1.1.1.2 root 566: 1.1.1.3 root 567: case 16: 1.1.1.4 ! root 568: /* A branch with an unfilled delay slot. */ ! 569: case 18: ! 570: /* Branches a long way away. */ 1.1.1.2 root 571: { 1.1.1.4 ! root 572: /* The call to print_slot will clobber the operands. */ ! 573: rtx op0 = operands[0]; 1.1.1.2 root 574: 1.1.1.4 ! root 575: /* If the instruction in the delay slot is annulled (true), then ! 576: there is no delay slot where we can put it now. The only safe ! 577: place for it is after the label. */ 1.1.1.2 root 578: 1.1.1.4 ! root 579: if (final_sequence) 1.1.1.2 root 580: { 1.1.1.4 ! root 581: fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't', ! 582: INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) ! 583: ? "" : ".s", label); ! 584: if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) ! 585: print_slot (final_sequence); 1.1.1.2 root 586: } 1.1.1.4 ! root 587: else ! 588: fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label); 1.1.1.2 root 589: 1.1.1.4 ! root 590: output_far_jump (insn, op0); 1.1.1.2 root 591: fprintf (asm_out_file, "LF%d:\n", label); 1.1.1.4 ! root 592: ! 593: if (final_sequence ! 594: && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) ! 595: print_slot (final_sequence); 1.1.1.2 root 596: } 1.1.1.4 ! root 597: return ""; 1.1 root 598: } 599: return "bad"; 600: } 601: 1.1.1.4 ! root 602: /* A copy of the option structure defined in toplev.c. */ 1.1 root 603: 1.1.1.3 root 604: struct option 1.1 root 605: { 1.1.1.3 root 606: char *string; 607: int *variable; 608: int on_value; 609: }; 1.1.1.2 root 610: 1.1.1.4 ! root 611: /* Output a single output option string NAME to FILE, without generating ! 612: lines longer than MAX. */ ! 613: 1.1.1.3 root 614: static int 615: output_option (file, sep, type, name, indent, pos, max) 616: FILE *file; 617: char *sep; 618: char *type; 619: char *name; 620: char *indent; 621: int pos; 622: int max; 623: { 624: if (strlen (sep) + strlen (type) + strlen (name) + pos > max) 1.1 root 625: { 1.1.1.3 root 626: fprintf (file, indent); 627: return fprintf (file, "%s%s", type, name); 1.1.1.2 root 628: } 1.1.1.3 root 629: return pos + fprintf (file, "%s%s%s", sep, type, name); 630: } 1.1 root 631: 1.1.1.4 ! root 632: /* A copy of the target_switches variable in toplev.c. */ ! 633: 1.1.1.3 root 634: static struct 635: { 636: char *name; 637: int value; 1.1.1.4 ! root 638: } m_options[] = TARGET_SWITCHES; 1.1 root 639: 1.1.1.4 ! root 640: /* Output all options to the assembly language file. */ 1.1 root 641: 1.1.1.3 root 642: static void 643: output_options (file, f_options, f_len, W_options, W_len, 644: pos, max, sep, indent, term) 645: FILE *file; 646: struct option *f_options; 647: struct option *W_options; 648: int f_len, W_len; 649: int pos; 650: int max; 651: char *sep; 652: char *indent; 653: char *term; 654: { 655: register int j; 1.1 root 656: 1.1.1.3 root 657: if (optimize) 658: pos = output_option (file, sep, "-O", "", indent, pos, max); 659: if (write_symbols != NO_DEBUG) 660: pos = output_option (file, sep, "-g", "", indent, pos, max); 661: if (profile_flag) 662: pos = output_option (file, sep, "-p", "", indent, pos, max); 663: if (profile_block_flag) 664: pos = output_option (file, sep, "-a", "", indent, pos, max); 1.1 root 665: 1.1.1.3 root 666: for (j = 0; j < f_len; j++) 667: if (*f_options[j].variable == f_options[j].on_value) 668: pos = output_option (file, sep, "-f", f_options[j].string, 669: indent, pos, max); 1.1 root 670: 1.1.1.3 root 671: for (j = 0; j < W_len; j++) 672: if (*W_options[j].variable == W_options[j].on_value) 673: pos = output_option (file, sep, "-W", W_options[j].string, 674: indent, pos, max); 1.1 root 675: 1.1.1.3 root 676: for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++) 677: if (m_options[j].name[0] != '\0' 678: && m_options[j].value > 0 679: && ((m_options[j].value & target_flags) 680: == m_options[j].value)) 681: pos = output_option (file, sep, "-m", m_options[j].name, 682: indent, pos, max); 1.1 root 683: 1.1.1.3 root 684: fprintf (file, term); 685: } 686: 1.1.1.4 ! root 687: /* Output to FILE the start of the assembler file. */ ! 688: 1.1.1.3 root 689: void 690: output_file_start (file, f_options, f_len, W_options, W_len) 691: FILE *file; 692: struct option *f_options; 693: struct option *W_options; 694: int f_len, W_len; 695: { 696: register int pos; 697: 698: output_file_directive (file, main_input_filename); 699: 700: /* Switch to the data section so that the coffsem symbol and the 701: gcc2_compiled. symbol aren't in the text section. */ 702: data_section (); 703: 1.1.1.4 ! root 704: pos = fprintf (file, "\n! Hitachi SH cc1 (%s) arguments:", version_string); 1.1.1.3 root 705: output_options (file, f_options, f_len, W_options, W_len, 706: pos, 75, " ", "\n! ", "\n\n"); 1.1.1.4 ! root 707: ! 708: if (TARGET_LITTLE_ENDIAN) ! 709: fprintf (file, "\t.little\n"); 1.1.1.3 root 710: } 711: 1.1.1.4 ! root 712: /* Actual number of instructions used to make a shift by N. */ ! 713: static char ashiftrt_insns[] = ! 714: { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2}; ! 715: ! 716: /* Left shift and logical right shift are the same. */ ! 717: static char shift_insns[] = ! 718: { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3}; ! 719: ! 720: /* Individual shift amounts needed to get the above length sequences. ! 721: One bit right shifts clobber the T bit, so when possible, put one bit ! 722: shifts in the middle of the sequence, so the ends are eligible for ! 723: branch delay slots. */ ! 724: static short shift_amounts[32][5] = { ! 725: {0}, {1}, {2}, {2, 1}, ! 726: {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2}, ! 727: {8}, {8, 1}, {8, 2}, {8, 1, 2}, ! 728: {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8}, ! 729: {16}, {16, 1}, {16, 2}, {16, 1, 2}, ! 730: {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8}, ! 731: {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2}, ! 732: {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}}; ! 733: ! 734: /* This is used in length attributes in sh.md to help compute the length ! 735: of arbitrary constant shift instructions. */ 1.1.1.3 root 736: 1.1.1.4 ! root 737: int ! 738: shift_insns_rtx (insn) ! 739: rtx insn; ! 740: { ! 741: rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); ! 742: int shift_count = INTVAL (XEXP (set_src, 1)); ! 743: enum rtx_code shift_code = GET_CODE (set_src); ! 744: ! 745: switch (shift_code) ! 746: { ! 747: case ASHIFTRT: ! 748: return ashiftrt_insns[shift_count]; ! 749: case LSHIFTRT: ! 750: case ASHIFT: ! 751: return shift_insns[shift_count]; ! 752: default: ! 753: abort(); ! 754: } ! 755: } 1.1.1.3 root 756: 1.1.1.4 ! root 757: /* Return the cost of a shift. */ 1.1.1.3 root 758: 759: int 1.1.1.4 ! root 760: shiftcosts (x) ! 761: rtx x; 1.1.1.3 root 762: { 1.1.1.4 ! root 763: int value = INTVAL (XEXP (x, 1)); 1.1.1.3 root 764: 1.1.1.4 ! root 765: /* If shift by a non constant, then this will be expensive. */ ! 766: if (GET_CODE (XEXP (x, 1)) != CONST_INT) ! 767: { ! 768: if (TARGET_SH3) ! 769: return 2; ! 770: /* If not an sh3 then we don't even have an instruction for it. */ ! 771: return 20; ! 772: } ! 773: ! 774: /* Otherwise, return the true cost in instructions. */ ! 775: if (GET_CODE (x) == ASHIFTRT) ! 776: return ashiftrt_insns[value]; ! 777: else ! 778: return shift_insns[value]; 1.1.1.3 root 779: } 1.1.1.2 root 780: 1.1.1.4 ! root 781: /* Return the cost of an AND operation. */ ! 782: 1.1.1.2 root 783: int 1.1.1.4 ! root 784: andcosts (x) ! 785: rtx x; 1.1 root 786: { 787: int i; 1.1.1.4 ! root 788: ! 789: /* Anding with a register is a single cycle and instruction. */ ! 790: if (GET_CODE (XEXP (x, 1)) != CONST_INT) ! 791: return 1; ! 792: ! 793: i = INTVAL (XEXP (x, 1)); ! 794: /* These constants are single cycle extu.[bw] instructions. */ 1.1.1.3 root 795: if (i == 0xff || i == 0xffff) 1.1.1.4 ! root 796: return 1; ! 797: /* Constants that can be used in an and immediate instruction is a single ! 798: cycle, but this requires r0, so make it a little more expensive. */ ! 799: if (CONST_OK_FOR_L (i)) 1.1.1.3 root 800: return 2; 1.1.1.4 ! root 801: /* Constants that can be loaded with a mov immediate and an and. ! 802: This case is probably unnecessary. */ 1.1.1.3 root 803: if (CONST_OK_FOR_I (i)) 1.1.1.4 ! root 804: return 2; ! 805: /* Any other constants requires a 2 cycle pc-relative load plus an and. ! 806: This case is probably unnecessary. */ ! 807: return 3; 1.1.1.3 root 808: } 1.1.1.2 root 809: 1.1.1.4 ! root 810: /* Return the cost of a multiply. */ ! 811: int ! 812: multcosts (x) ! 813: rtx x; 1.1.1.3 root 814: { 1.1.1.4 ! root 815: if (TARGET_SH2) 1.1 root 816: { 1.1.1.4 ! root 817: /* We have a mul insn, so we can never take more than the mul and the ! 818: read of the mac reg, but count more because of the latency and extra ! 819: reg usage. */ ! 820: if (TARGET_SMALLCODE) ! 821: return 2; ! 822: return 3; ! 823: } ! 824: ! 825: /* If we're aiming at small code, then just count the number of ! 826: insns in a multiply call sequence. */ ! 827: if (TARGET_SMALLCODE) ! 828: return 5; ! 829: ! 830: /* Otherwise count all the insns in the routine we'd be calling too. */ ! 831: return 20; ! 832: } ! 833: ! 834: /* Code to expand a shift. */ ! 835: ! 836: void ! 837: gen_ashift (type, n, reg) ! 838: int type; ! 839: int n; ! 840: rtx reg; ! 841: { ! 842: /* Negative values here come from the shift_amounts array. */ ! 843: if (n < 0) ! 844: { ! 845: if (type == ASHIFT) ! 846: type = LSHIFTRT; ! 847: else ! 848: type = ASHIFT; ! 849: n = -n; ! 850: } ! 851: ! 852: switch (type) ! 853: { ! 854: case ASHIFTRT: ! 855: emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n))); ! 856: break; ! 857: case LSHIFTRT: ! 858: if (n == 1) ! 859: emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n))); ! 860: else ! 861: emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n))); ! 862: break; ! 863: case ASHIFT: ! 864: emit_insn (gen_ashlsi3_k (reg, reg, GEN_INT (n))); ! 865: break; ! 866: } ! 867: } ! 868: ! 869: /* Output RTL to split a constant shift into its component SH constant ! 870: shift instructions. */ ! 871: ! 872: /* ??? For SH3, should reject constant shifts when slower than loading the ! 873: shift count into a register? */ ! 874: ! 875: int ! 876: gen_shifty_op (code, operands) ! 877: int code; ! 878: rtx *operands; ! 879: { ! 880: int value = INTVAL (operands[2]); ! 881: int max, i; ! 882: ! 883: if (value == 31) ! 884: { ! 885: if (code == LSHIFTRT) 1.1.1.3 root 886: { 1.1.1.4 ! root 887: emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); ! 888: emit_insn (gen_movt (operands[0])); ! 889: return; 1.1.1.3 root 890: } 1.1.1.4 ! root 891: else if (code == ASHIFT) 1.1.1.3 root 892: { 1.1.1.4 ! root 893: /* There is a two instruction sequence for 31 bit left shifts, ! 894: but it requires r0. */ ! 895: if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0) ! 896: { ! 897: emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx)); ! 898: emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); ! 899: return; ! 900: } 1.1.1.3 root 901: } 902: } 1.1.1.4 ! root 903: ! 904: max = shift_insns[value]; ! 905: for (i = 0; i < max; i++) ! 906: gen_ashift (code, shift_amounts[value][i], operands[0]); 1.1.1.3 root 907: } 1.1.1.2 root 908: 1.1.1.4 ! root 909: /* Output RTL for an arithmetic right shift. */ ! 910: ! 911: /* ??? Rewrite to use super-optimizer sequences. */ ! 912: 1.1.1.3 root 913: int 1.1.1.4 ! root 914: expand_ashiftrt (operands) ! 915: rtx *operands; 1.1.1.3 root 916: { 1.1.1.4 ! root 917: rtx wrk; ! 918: char func[18]; ! 919: tree func_name; ! 920: int value; ! 921: ! 922: if (TARGET_SH3 && GET_CODE (operands[2]) != CONST_INT) ! 923: { ! 924: rtx count = copy_to_mode_reg (SImode, operands[2]); ! 925: emit_insn (gen_negsi2 (count, count)); ! 926: emit_insn (gen_ashrsi3_d (operands[0], operands[1], count)); ! 927: return 1; ! 928: } ! 929: if (GET_CODE (operands[2]) != CONST_INT) ! 930: return 0; ! 931: ! 932: value = INTVAL (operands[2]); ! 933: ! 934: if (value == 31) ! 935: { ! 936: emit_insn (gen_ashrsi2_31 (operands[0], operands[1])); ! 937: return 1; ! 938: } ! 939: else if (value >= 16 && value <= 19) ! 940: { ! 941: wrk = gen_reg_rtx (SImode); ! 942: emit_insn (gen_ashrsi2_16 (wrk, operands[1])); ! 943: value -= 16; ! 944: while (value--) ! 945: gen_ashift (ASHIFTRT, 1, wrk); ! 946: emit_move_insn (operands[0], wrk); ! 947: return 1; ! 948: } ! 949: /* Expand a short sequence inline, longer call a magic routine. */ ! 950: else if (value <= 5) ! 951: { ! 952: wrk = gen_reg_rtx (SImode); ! 953: emit_move_insn (wrk, operands[1]); ! 954: while (value--) ! 955: gen_ashift (ASHIFTRT, 1, wrk); ! 956: emit_move_insn (operands[0], wrk); ! 957: return 1; ! 958: } ! 959: ! 960: wrk = gen_reg_rtx (Pmode); ! 961: ! 962: /* Load the value into an arg reg and call a helper. */ ! 963: emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); ! 964: sprintf (func, "__ashiftrt_r4_%d", value); ! 965: func_name = get_identifier (func); ! 966: emit_move_insn (wrk, gen_rtx (SYMBOL_REF, Pmode, ! 967: IDENTIFIER_POINTER (func_name))); ! 968: emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk)); ! 969: emit_move_insn (operands[0], gen_rtx (REG, SImode, 4)); ! 970: return 1; ! 971: } ! 972: ! 973: /* The SH cannot load a large constant into a register, constants have to ! 974: come from a pc relative load. The reference of a pc relative load ! 975: instruction must be less than 1k infront of the instruction. This ! 976: means that we often have to dump a constant inside a function, and ! 977: generate code to branch around it. ! 978: ! 979: It is important to minimize this, since the branches will slow things ! 980: down and make things bigger. ! 981: ! 982: Worst case code looks like: ! 983: ! 984: mov.l L1,rn ! 985: bra L2 ! 986: nop ! 987: align ! 988: L1: .long value ! 989: L2: ! 990: .. 1.1.1.3 root 991: 1.1.1.4 ! root 992: mov.l L3,rn ! 993: bra L4 ! 994: nop ! 995: align ! 996: L3: .long value ! 997: L4: ! 998: .. 1.1.1.3 root 999: 1.1.1.4 ! root 1000: We fix this by performing a scan before scheduling, which notices which ! 1001: instructions need to have their operands fetched from the constant table ! 1002: and builds the table. 1.1.1.3 root 1003: 1.1.1.4 ! root 1004: The algorithm is: 1.1.1.3 root 1005: 1.1.1.4 ! root 1006: scan, find an instruction which needs a pcrel move. Look forward, find the ! 1007: last barrier which is within MAX_COUNT bytes of the requirement. ! 1008: If there isn't one, make one. Process all the instructions between ! 1009: the find and the barrier. 1.1.1.3 root 1010: 1.1.1.4 ! root 1011: In the above example, we can tell that L3 is within 1k of L1, so ! 1012: the first move can be shrunk from the 3 insn+constant sequence into ! 1013: just 1 insn, and the constant moved to L3 to make: 1.1.1.3 root 1014: 1.1.1.4 ! root 1015: mov.l L1,rn ! 1016: .. ! 1017: mov.l L3,rn ! 1018: bra L4 ! 1019: nop ! 1020: align ! 1021: L3:.long value ! 1022: L4:.long value 1.1.1.3 root 1023: 1.1.1.4 ! root 1024: Then the second move becomes the target for the shortening process. */ 1.1.1.3 root 1025: 1.1.1.4 ! root 1026: typedef struct ! 1027: { ! 1028: rtx value; /* Value in table. */ ! 1029: rtx label; /* Label of value. */ ! 1030: enum machine_mode mode; /* Mode of value. */ ! 1031: } pool_node; 1.1.1.2 root 1032: 1.1.1.4 ! root 1033: /* The maximum number of constants that can fit into one pool, since ! 1034: the pc relative range is 0...1020 bytes and constants are at least 4 ! 1035: bytes long. */ 1.1.1.2 root 1036: 1.1.1.4 ! root 1037: #define MAX_POOL_SIZE (1020/4) ! 1038: static pool_node pool_vector[MAX_POOL_SIZE]; ! 1039: static int pool_size; 1.1.1.2 root 1040: 1.1.1.4 ! root 1041: /* ??? If we need a constant in HImode which is the truncated value of a ! 1042: constant we need in SImode, we could combine the two entries thus saving ! 1043: two bytes. Is this common enough to be worth the effort of implementing ! 1044: it? */ ! 1045: ! 1046: /* ??? This stuff should be done at the same time that we shorten branches. ! 1047: As it is now, we must assume that all branches are the maximum size, and ! 1048: this causes us to almost always output constant pools sooner than ! 1049: necessary. */ 1.1.1.2 root 1050: 1.1.1.4 ! root 1051: /* Add a constant to the pool and return its label. */ 1.1.1.2 root 1052: 1.1.1.4 ! root 1053: static rtx ! 1054: add_constant (x, mode) ! 1055: rtx x; ! 1056: enum machine_mode mode; 1.1.1.3 root 1057: { 1058: int i; 1.1.1.4 ! root 1059: rtx lab; ! 1060: ! 1061: /* First see if we've already got it. */ ! 1062: for (i = 0; i < pool_size; i++) 1.1.1.3 root 1063: { 1.1.1.4 ! root 1064: if (x->code == pool_vector[i].value->code ! 1065: && mode == pool_vector[i].mode) 1.1.1.3 root 1066: { 1.1.1.4 ! root 1067: if (x->code == CODE_LABEL) ! 1068: { ! 1069: if (XINT (x, 3) != XINT (pool_vector[i].value, 3)) ! 1070: continue; ! 1071: } ! 1072: if (rtx_equal_p (x, pool_vector[i].value)) ! 1073: return pool_vector[i].label; 1.1.1.3 root 1074: } 1075: } 1.1.1.2 root 1076: 1.1.1.4 ! root 1077: /* Need a new one. */ ! 1078: pool_vector[pool_size].value = x; ! 1079: lab = gen_label_rtx (); ! 1080: pool_vector[pool_size].mode = mode; ! 1081: pool_vector[pool_size].label = lab; ! 1082: pool_size++; ! 1083: return lab; 1.1 root 1084: } 1.1.1.4 ! root 1085: ! 1086: /* Output the literal table. */ 1.1 root 1087: 1.1.1.3 root 1088: static void 1089: dump_table (scan) 1090: rtx scan; 1091: { 1092: int i; 1093: int need_align = 1; 1.1 root 1094: 1.1.1.4 ! root 1095: /* Do two passes, first time dump out the HI sized constants. */ 1.1 root 1096: 1.1.1.3 root 1097: for (i = 0; i < pool_size; i++) 1098: { 1.1.1.4 ! root 1099: pool_node *p = &pool_vector[i]; ! 1100: 1.1.1.3 root 1101: if (p->mode == HImode) 1102: { 1103: if (need_align) 1104: { 1105: scan = emit_insn_after (gen_align_2 (), scan); 1106: need_align = 0; 1107: } 1108: scan = emit_label_after (p->label, scan); 1109: scan = emit_insn_after (gen_consttable_2 (p->value), scan); 1110: } 1111: } 1.1.1.4 ! root 1112: 1.1.1.3 root 1113: need_align = 1; 1.1 root 1114: 1.1.1.3 root 1115: for (i = 0; i < pool_size; i++) 1.1 root 1116: { 1.1.1.4 ! root 1117: pool_node *p = &pool_vector[i]; 1.1 root 1118: 1.1.1.3 root 1119: switch (p->mode) 1120: { 1121: case HImode: 1122: break; 1123: case SImode: 1124: if (need_align) 1125: { 1126: need_align = 0; 1127: scan = emit_label_after (gen_label_rtx (), scan); 1128: scan = emit_insn_after (gen_align_4 (), scan); 1129: } 1130: scan = emit_label_after (p->label, scan); 1131: scan = emit_insn_after (gen_consttable_4 (p->value), scan); 1132: break; 1133: case DImode: 1134: if (need_align) 1135: { 1136: need_align = 0; 1137: scan = emit_label_after (gen_label_rtx (), scan); 1138: scan = emit_insn_after (gen_align_4 (), scan); 1139: } 1140: scan = emit_label_after (p->label, scan); 1141: scan = emit_insn_after (gen_consttable_8 (p->value), scan); 1142: break; 1143: default: 1144: abort (); 1145: break; 1146: } 1.1.1.2 root 1147: } 1148: 1.1.1.3 root 1149: scan = emit_insn_after (gen_consttable_end (), scan); 1150: scan = emit_barrier_after (scan); 1151: pool_size = 0; 1152: } 1153: 1.1.1.4 ! root 1154: /* Return non-zero if constant would be an ok source for a ! 1155: mov.w instead of a mov.l. */ 1.1.1.2 root 1156: 1.1.1.4 ! root 1157: static int ! 1158: hi_const (src) 1.1.1.3 root 1159: rtx src; 1160: { 1.1.1.4 ! root 1161: return (GET_CODE (src) == CONST_INT ! 1162: && INTVAL (src) >= -32768 ! 1163: && INTVAL (src) <= 32767); 1.1 root 1164: } 1165: 1.1.1.4 ! root 1166: /* Non-zero if the insn is a move instruction which needs to be fixed. */ ! 1167: ! 1168: /* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the ! 1169: CONST_DOUBLE input value is CONST_OK_FOR_I. For a SFmode move, we don't ! 1170: need to fix it if the input value is CONST_OK_FOR_I. */ 1.1 root 1171: 1.1.1.4 ! root 1172: static int ! 1173: broken_move (insn) ! 1174: rtx insn; ! 1175: { ! 1176: if (GET_CODE (insn) == INSN ! 1177: && GET_CODE (PATTERN (insn)) == SET ! 1178: /* We can load any 8 bit value if we don't care what the high ! 1179: order bits end up as. */ ! 1180: && GET_MODE (SET_DEST (PATTERN (insn))) != QImode ! 1181: && CONSTANT_P (SET_SRC (PATTERN (insn))) ! 1182: && (GET_CODE (SET_SRC (PATTERN (insn))) != CONST_INT ! 1183: || ! CONST_OK_FOR_I (INTVAL (SET_SRC (PATTERN (insn)))))) 1.1.1.3 root 1184: return 1; 1.1 root 1185: 1.1.1.4 ! root 1186: return 0; 1.1.1.3 root 1187: } 1.1 root 1188: 1.1.1.4 ! root 1189: /* Find the last barrier from insn FROM which is close enough to hold the ! 1190: constant pool. If we can't find one, then create one near the end of ! 1191: the range. */ ! 1192: ! 1193: /* ??? It would be good to put constant pool tables between a case jump and ! 1194: the jump table. This fails for two reasons. First, there is no ! 1195: barrier after the case jump. This is a bug in the casesi pattern. ! 1196: Second, inserting the table here may break the mova instruction that ! 1197: loads the jump table address, by moving the jump table too far away. ! 1198: We fix that problem by never outputting the constant pool between a mova ! 1199: and its label. */ 1.1 root 1200: 1.1.1.4 ! root 1201: static rtx 1.1.1.3 root 1202: find_barrier (from) 1203: rtx from; 1204: { 1205: int count_si = 0; 1206: int count_hi = 0; 1207: int found_hi = 0; 1208: int found_si = 0; 1209: rtx found_barrier = 0; 1.1.1.4 ! root 1210: rtx found_mova = 0; ! 1211: ! 1212: /* For HImode: range is 510, add 4 because pc counts from address of ! 1213: second instruction after this one, subtract 2 for the jump instruction ! 1214: that we may need to emit before the table. This gives 512. ! 1215: For SImode: range is 1020, add 4 because pc counts from address of ! 1216: second instruction after this one, subtract 2 in case pc is 2 byte ! 1217: aligned, subtract 2 for the jump instruction that we may need to emit ! 1218: before the table. This gives 1020. */ ! 1219: while (from && count_si < 1020 && count_hi < 512) 1.1.1.3 root 1220: { 1.1.1.4 ! root 1221: int inc = get_attr_length (from); ! 1222: 1.1.1.3 root 1223: if (GET_CODE (from) == BARRIER) 1.1.1.4 ! root 1224: found_barrier = from; 1.1.1.3 root 1225: 1.1.1.4 ! root 1226: if (broken_move (from)) 1.1.1.3 root 1227: { 1228: rtx src = SET_SRC (PATTERN (from)); 1.1.1.4 ! root 1229: 1.1.1.3 root 1230: if (hi_const (src)) 1.1.1.4 ! root 1231: { ! 1232: found_hi = 1; ! 1233: /* We put the short constants before the long constants, so ! 1234: we must count the length of short constants in the range ! 1235: for the long constants. */ ! 1236: /* ??? This isn't optimal, but is easy to do. */ ! 1237: if (found_si) ! 1238: count_si += 2; ! 1239: } 1.1.1.3 root 1240: else 1241: found_si = 1; 1242: } 1.1.1.4 ! root 1243: ! 1244: if (GET_CODE (from) == INSN ! 1245: && GET_CODE (PATTERN (from)) == SET ! 1246: && GET_CODE (SET_SRC (PATTERN (from))) == UNSPEC ! 1247: && XINT (SET_SRC (PATTERN (from)), 1) == 1) ! 1248: found_mova = from; ! 1249: else if (GET_CODE (from) == JUMP_INSN ! 1250: && (GET_CODE (PATTERN (from)) == ADDR_VEC ! 1251: || GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC)) ! 1252: found_mova = 0; ! 1253: 1.1.1.3 root 1254: if (found_si) 1255: count_si += inc; 1256: if (found_hi) 1257: count_hi += inc; 1258: from = NEXT_INSN (from); 1.1 root 1259: } 1260: 1.1.1.4 ! root 1261: /* Insert the constant pool table before the mova instruction, to prevent ! 1262: the mova label reference from going out of range. */ ! 1263: if (found_mova) ! 1264: from = found_mova; ! 1265: ! 1266: if (! found_barrier) 1.1 root 1267: { 1.1.1.4 ! root 1268: /* We didn't find a barrier in time to dump our stuff, ! 1269: so we'll make one. */ 1.1.1.3 root 1270: rtx label = gen_label_rtx (); 1.1.1.4 ! root 1271: ! 1272: /* If we exceeded the range, then we must back up over the last ! 1273: instruction we looked at. Otherwise, we just need to undo the ! 1274: NEXT_INSN at the end of the loop. */ ! 1275: if (count_hi > 512 || count_si > 1020) ! 1276: from = PREV_INSN (PREV_INSN (from)); ! 1277: else ! 1278: from = PREV_INSN (from); ! 1279: ! 1280: /* Walk back to be just before any jump or label. ! 1281: Putting it before a label reduces the number of times the branch ! 1282: around the constant pool table will be hit. Putting it before ! 1283: a jump makes it more likely that the bra delay slot will be ! 1284: filled. */ ! 1285: while (GET_CODE (from) == JUMP_INSN || GET_CODE (from) == NOTE 1.1.1.3 root 1286: || GET_CODE (from) == CODE_LABEL) 1.1.1.4 ! root 1287: from = PREV_INSN (from); ! 1288: 1.1.1.3 root 1289: from = emit_jump_insn_after (gen_jump (label), from); 1290: JUMP_LABEL (from) = label; 1.1.1.4 ! root 1291: LABEL_NUSES (label) = 1; 1.1.1.3 root 1292: found_barrier = emit_barrier_after (from); 1293: emit_label_after (label, found_barrier); 1.1 root 1294: } 1295: 1.1.1.4 ! root 1296: return found_barrier; 1.1.1.3 root 1297: } 1.1.1.2 root 1298: 1.1.1.4 ! root 1299: /* Exported to toplev.c. 1.1.1.2 root 1300: 1.1.1.3 root 1301: Scan the function looking for move instructions which have to be changed to 1.1.1.4 ! root 1302: pc-relative loads and insert the literal tables. */ 1.1.1.2 root 1303: 1.1.1.3 root 1304: void 1305: machine_dependent_reorg (first) 1306: rtx first; 1307: { 1308: rtx insn; 1.1.1.4 ! root 1309: 1.1.1.3 root 1310: for (insn = first; insn; insn = NEXT_INSN (insn)) 1.1.1.2 root 1311: { 1.1.1.3 root 1312: if (broken_move (insn)) 1.1.1.2 root 1313: { 1.1.1.3 root 1314: rtx scan; 1.1.1.4 ! root 1315: /* Scan ahead looking for a barrier to stick the constant table ! 1316: behind. */ 1.1.1.3 root 1317: rtx barrier = find_barrier (insn); 1318: 1.1.1.4 ! root 1319: /* Now find all the moves between the points and modify them. */ 1.1.1.3 root 1320: for (scan = insn; scan != barrier; scan = NEXT_INSN (scan)) 1.1.1.2 root 1321: { 1.1.1.3 root 1322: if (broken_move (scan)) 1323: { 1324: rtx pat = PATTERN (scan); 1325: rtx src = SET_SRC (pat); 1326: rtx dst = SET_DEST (pat); 1327: enum machine_mode mode = GET_MODE (dst); 1328: rtx lab; 1329: rtx newinsn; 1330: rtx newsrc; 1331: 1332: if (mode == SImode && hi_const (src)) 1333: { 1.1.1.4 ! root 1334: int offset = 0; ! 1335: 1.1.1.3 root 1336: mode = HImode; 1337: while (GET_CODE (dst) == SUBREG) 1.1.1.4 ! root 1338: { ! 1339: offset += SUBREG_WORD (dst); ! 1340: dst = SUBREG_REG (dst); ! 1341: } ! 1342: dst = gen_rtx (REG, HImode, REGNO (dst) + offset); 1.1.1.3 root 1343: } 1.1.1.4 ! root 1344: 1.1.1.3 root 1345: lab = add_constant (src, mode); 1346: newsrc = gen_rtx (MEM, mode, 1347: gen_rtx (LABEL_REF, VOIDmode, lab)); 1.1.1.4 ! root 1348: RTX_UNCHANGING_P (newsrc) = 1; ! 1349: newinsn = emit_insn_after (gen_rtx (SET, VOIDmode, ! 1350: dst, newsrc), scan); 1.1.1.3 root 1351: 1352: delete_insn (scan); 1353: scan = newinsn; 1354: } 1.1.1.2 root 1355: } 1.1.1.3 root 1356: dump_table (barrier); 1.1.1.2 root 1357: } 1358: } 1359: } 1360: 1.1.1.4 ! root 1361: /* Dump out instruction addresses, which is useful for debugging the ! 1362: constant pool table stuff. */ ! 1363: ! 1364: /* ??? This is unnecessary, and probably should be deleted. This makes ! 1365: the insn_addresses declaration above unnecessary. */ ! 1366: ! 1367: /* ??? The addresses printed by this routine for insns are nonsense for ! 1368: insns which are inside of a sequence where none of the inner insns have ! 1369: variable length. This is because the second pass of shorten_branches ! 1370: does not bother to update them. */ ! 1371: ! 1372: void ! 1373: final_prescan_insn (insn, opvec, noperands) ! 1374: rtx insn; ! 1375: rtx *opvec; ! 1376: int noperands; ! 1377: { ! 1378: if (TARGET_DUMPISIZE) ! 1379: fprintf (asm_out_file, "\n! at %04x\n", insn_addresses[INSN_UID (insn)]); ! 1380: } ! 1381: ! 1382: /* Dump out any constants accumulated in the final pass. These will ! 1383: will only be labels. */ ! 1384: ! 1385: char * ! 1386: output_jump_label_table () ! 1387: { ! 1388: int i; ! 1389: ! 1390: if (pool_size) ! 1391: { ! 1392: fprintf (asm_out_file, "\t.align 2\n"); ! 1393: for (i = 0; i < pool_size; i++) ! 1394: { ! 1395: pool_node *p = &pool_vector[i]; ! 1396: ! 1397: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", ! 1398: CODE_LABEL_NUMBER (p->label)); ! 1399: output_asm_insn (".long %O0", &p->value); ! 1400: } ! 1401: pool_size = 0; ! 1402: } ! 1403: ! 1404: return ""; ! 1405: } ! 1406: ! 1407: /* A full frame looks like: ! 1408: ! 1409: arg-5 ! 1410: arg-4 ! 1411: [ if current_function_anonymous_args ! 1412: arg-3 ! 1413: arg-2 ! 1414: arg-1 ! 1415: arg-0 ] ! 1416: saved-fp ! 1417: saved-r10 ! 1418: saved-r11 ! 1419: saved-r12 ! 1420: saved-pr ! 1421: local-n ! 1422: .. ! 1423: local-1 ! 1424: local-0 <- fp points here. */ ! 1425: ! 1426: /* Number of bytes pushed for anonymous args, used to pass information ! 1427: between expand_prologue and expand_epilogue. */ ! 1428: ! 1429: static int extra_push; ! 1430: ! 1431: /* Adjust the stack and return the number of bytes taken to do it. */ ! 1432: ! 1433: static void ! 1434: output_stack_adjust (size, reg) ! 1435: int size; ! 1436: rtx reg; ! 1437: { ! 1438: if (size) ! 1439: { ! 1440: rtx val = GEN_INT (size); ! 1441: rtx insn; ! 1442: ! 1443: if (! CONST_OK_FOR_I (size)) ! 1444: { ! 1445: rtx reg = gen_rtx (REG, SImode, 3); ! 1446: emit_insn (gen_movsi (reg, val)); ! 1447: val = reg; ! 1448: } ! 1449: ! 1450: insn = gen_addsi3 (reg, reg, val); ! 1451: emit_insn (insn); ! 1452: } ! 1453: } ! 1454: ! 1455: /* Output RTL to push register RN onto the stack. */ 1.1.1.3 root 1456: 1.1.1.4 ! root 1457: static void ! 1458: push (rn) ! 1459: int rn; 1.1.1.2 root 1460: { 1.1.1.4 ! root 1461: rtx x; ! 1462: x = emit_insn (gen_push (gen_rtx (REG, SImode, rn))); ! 1463: REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, ! 1464: gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0); 1.1.1.2 root 1465: } 1466: 1.1.1.4 ! root 1467: /* Output RTL to pop register RN from the stack. */ 1.1.1.2 root 1468: 1.1.1.4 ! root 1469: static void ! 1470: pop (rn) ! 1471: int rn; 1.1.1.2 root 1472: { 1.1.1.4 ! root 1473: rtx x; ! 1474: x = emit_insn (gen_pop (gen_rtx (REG, SImode, rn))); ! 1475: REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, ! 1476: gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0); 1.1.1.2 root 1477: } 1478: 1.1.1.4 ! root 1479: /* Generate code to push the regs specified in the mask, and return ! 1480: the number of bytes the insns take. */ 1.1.1.2 root 1481: 1.1.1.3 root 1482: static void 1.1.1.4 ! root 1483: push_regs (mask) ! 1484: int mask; 1.1.1.2 root 1485: { 1.1.1.4 ! root 1486: int i; ! 1487: ! 1488: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 1489: if (mask & (1 << i)) ! 1490: push (i); 1.1.1.2 root 1491: } 1492: 1.1.1.4 ! root 1493: /* Work out the registers which need to be saved, both as a mask and a ! 1494: count. ! 1495: ! 1496: If doing a pragma interrupt function, then push all regs used by the ! 1497: function, and if we call another function (we can tell by looking at PR), ! 1498: make sure that all the regs it clobbers are safe too. */ ! 1499: 1.1.1.3 root 1500: static int 1.1.1.4 ! root 1501: calc_live_regs (count_ptr) ! 1502: int *count_ptr; 1.1.1.2 root 1503: { 1.1.1.4 ! root 1504: int reg; ! 1505: int live_regs_mask = 0; ! 1506: int count = 0; ! 1507: ! 1508: for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++) 1.1.1.3 root 1509: { 1.1.1.4 ! root 1510: if (pragma_interrupt && ! pragma_trapa) ! 1511: { ! 1512: /* Need to save all the regs ever live. */ ! 1513: if ((regs_ever_live[reg] ! 1514: || (call_used_regs[reg] && regs_ever_live[PR_REG])) ! 1515: && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM ! 1516: && reg != T_REG && reg != GBR_REG) ! 1517: { ! 1518: live_regs_mask |= 1 << reg; ! 1519: count++; ! 1520: } ! 1521: } ! 1522: else ! 1523: { ! 1524: /* Only push those regs which are used and need to be saved. */ ! 1525: if (regs_ever_live[reg] && ! call_used_regs[reg]) ! 1526: { ! 1527: live_regs_mask |= (1 << reg); ! 1528: count++; ! 1529: } ! 1530: } 1.1.1.3 root 1531: } 1.1.1.2 root 1532: 1.1.1.4 ! root 1533: *count_ptr = count; ! 1534: return live_regs_mask; ! 1535: } 1.1.1.2 root 1536: 1.1.1.4 ! root 1537: /* Code to generate prologue and epilogue sequences */ 1.1.1.2 root 1538: 1539: void 1540: sh_expand_prologue () 1541: { 1542: int live_regs_mask; 1.1.1.4 ! root 1543: int d, i; 1.1.1.2 root 1544: live_regs_mask = calc_live_regs (&d); 1545: 1.1.1.3 root 1546: /* We have pretend args if we had an object sent partially in registers 1.1.1.4 ! root 1547: and partially on the stack, e.g. a large structure. */ ! 1548: output_stack_adjust (-current_function_pretend_args_size, stack_pointer_rtx); 1.1.1.2 root 1549: 1.1.1.4 ! root 1550: extra_push = 0; ! 1551: ! 1552: /* This is set by SETUP_VARARGS to indicate that this is a varargs ! 1553: routine. Clear it here so that the next function isn't affected. */ 1.1.1.2 root 1554: if (current_function_anonymous_args) 1555: { 1.1.1.4 ! root 1556: current_function_anonymous_args = 0; ! 1557: ! 1558: /* Push arg regs as if they'd been provided by caller in stack. */ 1.1.1.2 root 1559: for (i = 0; i < NPARM_REGS; i++) 1560: { 1561: int rn = NPARM_REGS + FIRST_PARM_REG - i - 1; 1.1.1.4 ! root 1562: if (i > (NPARM_REGS - current_function_args_info ! 1563: - current_function_varargs)) 1.1.1.2 root 1564: break; 1565: push (rn); 1566: extra_push += 4; 1567: } 1568: } 1.1.1.3 root 1569: push_regs (live_regs_mask); 1.1.1.4 ! root 1570: output_stack_adjust (-get_frame_size (), stack_pointer_rtx); 1.1.1.2 root 1571: 1572: if (frame_pointer_needed) 1.1.1.4 ! root 1573: emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); 1.1.1.2 root 1574: } 1575: 1576: void 1577: sh_expand_epilogue () 1578: { 1579: int live_regs_mask; 1.1.1.4 ! root 1580: int d, i; 1.1.1.2 root 1581: 1582: live_regs_mask = calc_live_regs (&d); 1583: 1584: if (frame_pointer_needed) 1585: { 1.1.1.4 ! root 1586: /* We deliberately make the add dependent on the frame_pointer, ! 1587: to ensure that instruction scheduling won't move the stack pointer ! 1588: adjust before instructions reading from the frame. This can fail ! 1589: if there is an interrupt which then writes to the stack. */ ! 1590: output_stack_adjust (get_frame_size (), frame_pointer_rtx); 1.1.1.2 root 1591: emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); 1592: } 1.1.1.4 ! root 1593: else ! 1594: output_stack_adjust (get_frame_size (), stack_pointer_rtx); 1.1.1.2 root 1595: 1.1.1.4 ! root 1596: /* Pop all the registers. */ 1.1.1.3 root 1597: 1.1.1.2 root 1598: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1599: { 1600: int j = (FIRST_PSEUDO_REGISTER - 1) - i; 1601: if (live_regs_mask & (1 << j)) 1.1.1.4 ! root 1602: pop (j); 1.1.1.2 root 1603: } 1604: 1.1.1.4 ! root 1605: output_stack_adjust (extra_push + current_function_pretend_args_size, ! 1606: stack_pointer_rtx); ! 1607: } 1.1.1.2 root 1608: 1.1.1.4 ! root 1609: /* Clear variables at function end. */ 1.1.1.3 root 1610: 1.1.1.4 ! root 1611: void ! 1612: function_epilogue (stream, size) ! 1613: FILE *stream; ! 1614: int size; ! 1615: { ! 1616: pragma_interrupt = pragma_trapa = 0; 1.1.1.2 root 1617: } 1618: 1.1.1.3 root 1619: /* Define the offset between two registers, one to be eliminated, and 1620: the other its replacement, at the start of a routine. */ 1.1.1.2 root 1621: 1.1.1.3 root 1622: int 1623: initial_elimination_offset (from, to) 1624: int from; 1625: int to; 1626: { 1627: int regs_saved; 1628: int total_saved_regs_space; 1629: int total_auto_space = get_frame_size (); 1630: 1631: calc_live_regs (®s_saved); 1632: total_saved_regs_space = (regs_saved) * 4; 1633: 1634: if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) 1.1.1.4 ! root 1635: return total_saved_regs_space + total_auto_space; ! 1636: 1.1.1.3 root 1637: if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 1.1.1.4 ! root 1638: return total_saved_regs_space + total_auto_space; ! 1639: ! 1640: /* Initial gap between fp and sp is 0. */ 1.1.1.3 root 1641: if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 1.1.1.4 ! root 1642: return 0; ! 1643: 1.1.1.3 root 1644: abort (); 1645: } 1.1.1.4 ! root 1646: 1.1.1.3 root 1647: /* Handle machine specific pragmas to be semi-compatible with Hitachi 1.1.1.4 ! root 1648: compiler. */ 1.1.1.2 root 1649: 1650: int 1.1.1.3 root 1651: handle_pragma (file) 1652: FILE *file; 1.1.1.2 root 1653: { 1.1.1.3 root 1654: int c; 1655: char pbuf[200]; 1656: int psize = 0; 1.1.1.2 root 1657: 1.1.1.3 root 1658: c = getc (file); 1659: while (c == ' ' || c == '\t') 1660: c = getc (file); 1661: 1662: if (c == '\n' || c == EOF) 1663: return c; 1664: 1665: while (psize < sizeof (pbuf) - 1 && c != '\n') 1666: { 1667: pbuf[psize++] = c; 1668: if (psize == 9 && strncmp (pbuf, "interrupt", 9) == 0) 1669: { 1670: pragma_interrupt = 1; 1671: return ' '; 1672: } 1673: if (psize == 5 && strncmp (pbuf, "trapa", 5) == 0) 1674: { 1675: pragma_interrupt = pragma_trapa = 1; 1676: return ' '; 1677: } 1678: c = getc (file); 1679: } 1680: return c; 1681: } 1682: 1.1.1.4 ! root 1683: /* Predicates used by the templates. */ 1.1.1.3 root 1684: 1.1.1.4 ! root 1685: /* Returns 1 if OP is MACL, MACH or PR. The input must be a REG rtx. ! 1686: Used only in general_movsrc_operand. */ 1.1.1.3 root 1687: 1.1.1.4 ! root 1688: int ! 1689: system_reg_operand (op, mode) ! 1690: rtx op; ! 1691: enum machine_mode mode; 1.1.1.3 root 1692: { 1.1.1.4 ! root 1693: switch (REGNO (op)) 1.1.1.3 root 1694: { 1.1.1.4 ! root 1695: case PR_REG: ! 1696: case MACL_REG: ! 1697: case MACH_REG: ! 1698: return 1; 1.1.1.3 root 1699: } 1.1.1.4 ! root 1700: return 0; 1.1.1.3 root 1701: } 1702: 1703: /* Returns 1 if OP can be source of a simple move operation. 1704: Same as general_operand, but a LABEL_REF is valid, PRE_DEC is 1.1.1.4 ! root 1705: invalid as are subregs of system registers. */ 1.1.1.3 root 1706: 1707: int 1708: general_movsrc_operand (op, mode) 1709: rtx op; 1710: enum machine_mode mode; 1711: { 1712: if (GET_CODE (op) == MEM) 1713: { 1714: rtx inside = XEXP (op, 0); 1715: if (GET_CODE (inside) == CONST) 1716: inside = XEXP (inside, 0); 1717: 1718: if (GET_CODE (inside) == LABEL_REF) 1719: return 1; 1720: 1721: if (GET_CODE (inside) == PLUS 1.1.1.4 ! root 1722: && GET_CODE (XEXP (inside, 0)) == LABEL_REF ! 1723: && GET_CODE (XEXP (inside, 1)) == CONST_INT) 1.1.1.3 root 1724: return 1; 1725: 1.1.1.4 ! root 1726: /* Only post inc allowed. */ ! 1727: if (GET_CODE (inside) == PRE_DEC) 1.1.1.3 root 1728: return 0; 1729: } 1730: 1731: if ((mode == QImode || mode == HImode) 1732: && (GET_CODE (op) == SUBREG 1733: && GET_CODE (XEXP (op, 0)) == REG 1734: && system_reg_operand (XEXP (op, 0), mode))) 1735: return 0; 1736: 1737: return general_operand (op, mode); 1.1.1.2 root 1738: } 1739: 1.1.1.3 root 1740: /* Returns 1 if OP can be a destination of a move. 1741: Same as general_operand, but no preinc allowed. */ 1742: 1.1.1.2 root 1743: int 1.1.1.3 root 1744: general_movdst_operand (op, mode) 1745: rtx op; 1746: enum machine_mode mode; 1.1.1.2 root 1747: { 1.1.1.4 ! root 1748: /* Only pre dec allowed. */ ! 1749: if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) 1.1.1.3 root 1750: return 0; 1751: 1752: return general_operand (op, mode); 1753: } 1754: 1755: /* Returns 1 if OP is a normal arithmetic register. */ 1756: 1757: int 1758: arith_reg_operand (op, mode) 1759: rtx op; 1760: enum machine_mode mode; 1761: { 1762: if (register_operand (op, mode)) 1763: { 1764: if (GET_CODE (op) == REG) 1765: return (REGNO (op) != T_REG 1.1.1.4 ! root 1766: && REGNO (op) != PR_REG ! 1767: && REGNO (op) != MACH_REG ! 1768: && REGNO (op) != MACL_REG); 1.1.1.3 root 1769: return 1; 1770: } 1771: return 0; 1772: } 1773: 1774: /* Returns 1 if OP is a valid source operand for an arithmetic insn. */ 1775: 1776: int 1777: arith_operand (op, mode) 1778: rtx op; 1779: enum machine_mode mode; 1780: { 1781: if (arith_reg_operand (op, mode)) 1782: return 1; 1783: 1.1.1.4 ! root 1784: if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op))) ! 1785: return 1; ! 1786: 1.1.1.3 root 1787: return 0; 1788: } 1789: 1.1.1.4 ! root 1790: /* Returns 1 if OP is a valid source operand for a compare insn. */ 1.1.1.3 root 1791: 1792: int 1.1.1.4 ! root 1793: arith_reg_or_0_operand (op, mode) 1.1.1.3 root 1794: rtx op; 1795: enum machine_mode mode; 1796: { 1797: if (arith_reg_operand (op, mode)) 1798: return 1; 1799: 1.1.1.4 ! root 1800: if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op))) ! 1801: return 1; ! 1802: 1.1.1.3 root 1803: return 0; 1804: } 1805: 1.1.1.4 ! root 1806: /* Returns 1 if OP is a valid source operand for a logical operation. */ 1.1.1.3 root 1807: 1808: int 1.1.1.4 ! root 1809: logical_operand (op, mode) 1.1.1.3 root 1810: rtx op; 1811: enum machine_mode mode; 1812: { 1813: if (arith_reg_operand (op, mode)) 1814: return 1; 1.1.1.4 ! root 1815: ! 1816: if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op))) 1.1.1.3 root 1817: return 1; 1.1.1.4 ! root 1818: 1.1.1.3 root 1819: return 0; 1820: } 1.1.1.4 ! root 1821: 1.1.1.3 root 1822: /* Determine where to put an argument to a function. 1823: Value is zero to push the argument on the stack, 1824: or a hard register in which to store the argument. 1825: 1826: MODE is the argument's machine mode. 1827: TYPE is the data type of the argument (as a tree). 1828: This is null for libcalls where that information may 1829: not be available. 1830: CUM is a variable of type CUMULATIVE_ARGS which gives info about 1831: the preceding args and about the function being called. 1832: NAMED is nonzero if this argument is a named parameter 1833: (otherwise it is an extra parameter matching an ellipsis). */ 1834: 1835: rtx 1836: sh_function_arg (cum, mode, type, named) 1837: CUMULATIVE_ARGS cum; 1838: enum machine_mode mode; 1839: tree type; 1840: int named; 1841: { 1842: if (named) 1843: { 1.1.1.4 ! root 1844: int rr = (ROUND_REG (cum, mode)); 1.1.1.3 root 1845: 1846: if (rr < NPARM_REGS) 1.1.1.4 ! root 1847: return ((type == 0 || ! TREE_ADDRESSABLE (type)) ! 1848: ? gen_rtx (REG, mode, FIRST_PARM_REG + rr) : 0); 1.1.1.3 root 1849: } 1850: return 0; 1851: } 1852: 1853: /* For an arg passed partly in registers and partly in memory, 1854: this is the number of registers used. 1855: For args passed entirely in registers or entirely in memory, zero. 1856: Any arg that starts in the first 4 regs but won't entirely fit in them 1857: needs partial registers on the SH. */ 1858: 1859: int 1.1.1.4 ! root 1860: sh_function_arg_partial_nregs (cum, mode, type, named) ! 1861: CUMULATIVE_ARGS cum; ! 1862: enum machine_mode mode; ! 1863: tree type; ! 1864: int named; ! 1865: { ! 1866: if (cum < NPARM_REGS) ! 1867: { ! 1868: if ((type == 0 || ! TREE_ADDRESSABLE (type)) ! 1869: && (cum + (mode == BLKmode ! 1870: ? ROUND_ADVANCE (int_size_in_bytes (type)) ! 1871: : ROUND_ADVANCE (GET_MODE_SIZE (mode))) - NPARM_REGS > 0)) ! 1872: return NPARM_REGS - cum; 1.1.1.3 root 1873: } 1874: return 0; 1875: } 1.1.1.4 ! root 1876: ! 1877: /* Return non-zero if REG is not used after INSN. ! 1878: We assume REG is a reload reg, and therefore does ! 1879: not live past labels or calls or jumps. */ ! 1880: int ! 1881: reg_unused_after (reg, insn) ! 1882: rtx reg; ! 1883: rtx insn; ! 1884: { ! 1885: enum rtx_code code; ! 1886: rtx set; 1.1.1.3 root 1887: 1.1.1.4 ! root 1888: /* If the reg is set by this instruction, then it is safe for our ! 1889: case. Disregard the case where this is a store to memory, since ! 1890: we are checking a register used in the store address. */ ! 1891: set = single_set (insn); ! 1892: if (set && GET_CODE (SET_DEST (set)) != MEM ! 1893: && reg_overlap_mentioned_p (reg, SET_DEST (set))) ! 1894: return 1; 1.1.1.3 root 1895: 1.1.1.4 ! root 1896: while (insn = NEXT_INSN (insn)) ! 1897: { ! 1898: code = GET_CODE (insn); ! 1899: ! 1900: #if 0 ! 1901: /* If this is a label that existed before reload, then the register ! 1902: if dead here. However, if this is a label added by reorg, then ! 1903: the register may still be live here. We can't tell the difference, ! 1904: so we just ignore labels completely. */ ! 1905: if (code == CODE_LABEL) ! 1906: return 1; ! 1907: /* else */ ! 1908: #endif ! 1909: ! 1910: /* If this is a sequence, we must handle them all at once. ! 1911: We could have for instance a call that sets the target register, ! 1912: and a insn in a delay slot that uses the register. In this case, ! 1913: we must return 0. */ ! 1914: if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) ! 1915: { ! 1916: int i; ! 1917: int retval = 0; ! 1918: ! 1919: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) ! 1920: { ! 1921: rtx this_insn = XVECEXP (PATTERN (insn), 0, i); ! 1922: rtx set = single_set (this_insn); ! 1923: ! 1924: if (GET_CODE (this_insn) == CALL_INSN) ! 1925: code = CALL_INSN; ! 1926: ! 1927: if (set && reg_overlap_mentioned_p (reg, SET_SRC (set))) ! 1928: return 0; ! 1929: if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) ! 1930: { ! 1931: if (GET_CODE (SET_DEST (set)) != MEM) ! 1932: retval = 1; ! 1933: else ! 1934: return 0; ! 1935: } ! 1936: if (set == 0 ! 1937: && reg_overlap_mentioned_p (reg, PATTERN (this_insn))) ! 1938: return 0; ! 1939: } ! 1940: if (retval == 1) ! 1941: return 1; ! 1942: } ! 1943: else if (GET_RTX_CLASS (code) == 'i') ! 1944: { ! 1945: rtx set = single_set (insn); ! 1946: ! 1947: if (set && reg_overlap_mentioned_p (reg, SET_SRC (set))) ! 1948: return 0; ! 1949: if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) ! 1950: return GET_CODE (SET_DEST (set)) != MEM; ! 1951: if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn))) ! 1952: return 0; ! 1953: } ! 1954: ! 1955: if (code == CALL_INSN && call_used_regs[REGNO (reg)]) ! 1956: return 1; ! 1957: } ! 1958: return 1; 1.1.1.2 root 1959: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.