?? mips.c.svn-base
字號:
if (no_new_pseudos) emit_move_insn (dest, x), x = dest; else x = force_reg (mode, x); x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value)); } emit_insn (gen_rtx_SET (VOIDmode, dest, x));}/* Subroutine of mips_legitimize_move. Move constant SRC into register DEST given that SRC satisfies immediate_operand but doesn't satisfy move_operand. */static voidmips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src){ rtx base; HOST_WIDE_INT offset; enum mips_symbol_type symbol_type; /* Split moves of big integers into smaller pieces. In mips16 code, it's better to force the constant into memory instead. */ if (GET_CODE (src) == CONST_INT && !TARGET_MIPS16) { mips_move_integer (dest, INTVAL (src)); return; } /* See if the symbol can be split. For mips16, this is often worse than forcing it in the constant pool since it needs the single-register form of addiu or daddiu. */ if (!TARGET_MIPS16 && mips_symbolic_constant_p (src, &symbol_type) && mips_split_p[symbol_type]) { emit_move_insn (dest, mips_split_symbol (dest, src)); return; } /* If we have (const (plus symbol offset)), load the symbol first and then add in the offset. This is usually better than forcing the constant into memory, at least in non-mips16 code. */ mips_split_const (src, &base, &offset); if (!TARGET_MIPS16 && offset != 0 && (!no_new_pseudos || SMALL_OPERAND (offset))) { base = mips_force_temporary (dest, base); emit_move_insn (dest, mips_add_offset (0, base, offset)); return; } src = force_const_mem (mode, src); /* When using explicit relocs, constant pool references are sometimes not legitimate addresses. */ if (!memory_operand (src, VOIDmode)) src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0))); emit_move_insn (dest, src);}/* If (set DEST SRC) is not a valid instruction, emit an equivalent sequence that is valid. */boolmips_legitimize_move (enum machine_mode mode, rtx dest, rtx src){ if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) { emit_move_insn (dest, force_reg (mode, src)); return true; } /* Check for individual, fully-reloaded mflo and mfhi instructions. */ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD && REG_P (src) && MD_REG_P (REGNO (src)) && REG_P (dest) && GP_REG_P (REGNO (dest))) { int other_regno = REGNO (src) == HI_REGNUM ? LO_REGNUM : HI_REGNUM; if (GET_MODE_SIZE (mode) <= 4) emit_insn (gen_mfhilo_si (gen_rtx_REG (SImode, REGNO (dest)), gen_rtx_REG (SImode, REGNO (src)), gen_rtx_REG (SImode, other_regno))); else emit_insn (gen_mfhilo_di (gen_rtx_REG (DImode, REGNO (dest)), gen_rtx_REG (DImode, REGNO (src)), gen_rtx_REG (DImode, other_regno))); return true; } /* We need to deal with constants that would be legitimate immediate_operands but not legitimate move_operands. */ if (CONSTANT_P (src) && !move_operand (src, mode)) { mips_legitimize_const_move (mode, dest, src); set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); return true; } return false;}/* We need a lot of little routines to check constant values on the mips16. These are used to figure out how long the instruction will be. It would be much better to do this using constraints, but there aren't nearly enough letters available. */static intm16_check_op (rtx op, int low, int high, int mask){ return (GET_CODE (op) == CONST_INT && INTVAL (op) >= low && INTVAL (op) <= high && (INTVAL (op) & mask) == 0);}intm16_uimm3_b (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, 0x1, 0x8, 0);}intm16_simm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0x8, 0x7, 0);}intm16_nsimm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0x7, 0x8, 0);}intm16_simm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0x10, 0xf, 0);}intm16_nsimm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0xf, 0x10, 0);}intm16_uimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, (- 0x10) << 2, 0xf << 2, 3);}intm16_nuimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, (- 0xf) << 2, 0x10 << 2, 3);}intm16_simm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0x80, 0x7f, 0);}intm16_nsimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0x7f, 0x80, 0);}intm16_uimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, 0x0, 0xff, 0);}intm16_nuimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0xff, 0x0, 0);}intm16_uimm8_m1_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, - 0x1, 0xfe, 0);}intm16_uimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, 0x0, 0xff << 2, 3);}intm16_nuimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, (- 0xff) << 2, 0x0, 3);}intm16_simm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, (- 0x80) << 3, 0x7f << 3, 7);}intm16_nsimm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ return m16_check_op (op, (- 0x7f) << 3, 0x80 << 3, 7);}static boolmips_rtx_costs (rtx x, int code, int outer_code, int *total){ enum machine_mode mode = GET_MODE (x); switch (code) { case CONST_INT: if (!TARGET_MIPS16) { /* Always return 0, since we don't have different sized instructions, hence different costs according to Richard Kenner */ *total = 0; return true; } /* A number between 1 and 8 inclusive is efficient for a shift. Otherwise, we will need an extended instruction. */ if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT || (outer_code) == LSHIFTRT) { if (INTVAL (x) >= 1 && INTVAL (x) <= 8) *total = 0; else *total = COSTS_N_INSNS (1); return true; } /* We can use cmpi for an xor with an unsigned 16 bit value. */ if ((outer_code) == XOR && INTVAL (x) >= 0 && INTVAL (x) < 0x10000) { *total = 0; return true; } /* We may be able to use slt or sltu for a comparison with a signed 16 bit value. (The boundary conditions aren't quite right, but this is just a heuristic anyhow.) */ if (((outer_code) == LT || (outer_code) == LE || (outer_code) == GE || (outer_code) == GT || (outer_code) == LTU || (outer_code) == LEU || (outer_code) == GEU || (outer_code) == GTU) && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000) { *total = 0; return true; } /* Equality comparisons with 0 are cheap. */ if (((outer_code) == EQ || (outer_code) == NE) && INTVAL (x) == 0) { *total = 0; return true; } /* Constants in the range 0...255 can be loaded with an unextended instruction. They are therefore as cheap as a register move. Given the choice between "li R1,0...255" and "move R1,R2" (where R2 is a known constant), it is usually better to use "li", since we do not want to unnecessarily extend the lifetime of R2. */ if (outer_code == SET && INTVAL (x) >= 0 && INTVAL (x) < 256) { *total = 0; return true; } /* Otherwise fall through to the handling below. */ case CONST: case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: if (LEGITIMATE_CONSTANT_P (x)) { *total = COSTS_N_INSNS (1); return true; } else { /* The value will need to be fetched from the constant pool. */ *total = CONSTANT_POOL_COST; return true; } case MEM: { /* If the address is legitimate, return the number of instructions it needs, otherwise use the default handling. */ int n = mips_address_insns (XEXP (x, 0), GET_MODE (x)); if (n > 0) { *total = COSTS_N_INSNS (1 + n); return true; } return false; } case FFS: *total = COSTS_N_INSNS (6); return true; case NOT: *total = COSTS_N_INSNS ((mode == DImode && !TARGET_64BIT) ? 2 : 1); return true; case AND: case IOR: case XOR: if (mode == DImode && !TARGET_64BIT) { *total = COSTS_N_INSNS (2); return true; } return false; case ASHIFT: case ASHIFTRT: case LSHIFTRT: if (mode == DImode && !TARGET_64BIT) { *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) ? 4 : 12); return true; } return false; case ABS: if (mode == SFmode || mode == DFmode) *total = COSTS_N_INSNS (1); else *total = COSTS_N_INSNS (4); return true; case LO_SUM: *total = COSTS_N_INSNS (1); return true; case PLUS: case MINUS: if (mode == SFmode || mode == DFmode) { if (TUNE_MIPS3000 || TUNE_MIPS3900) *total = COSTS_N_INSNS (2); else if (TUNE_MIPS6000) *total = COSTS_N_INSNS (3); else if (TUNE_SB1) *total = COSTS_N_INSNS (4); else *total = COSTS_N_INSNS (6); return true; } if (mode == DImode && !TARGET_64BIT) { *total = COSTS_N_INSNS (4); return true; } return false; case NEG: if (mode == DImode && !TARGET_64BIT) { *total = 4; return true; } return false; case MULT: if (mode == SFmode) { if (TUNE_MIPS3000 || TUNE_MIPS3900 || TUNE_MIPS5000 || TUNE_SB1) *total = COSTS_N_INSNS (4); else if (TUNE_MIPS6000 || TUNE_MIPS5400 || TUNE_MIPS5500) *total = COSTS_N_INSNS (5); else *total = COSTS_N_INSNS (7); return true; } if (mode == DFmode) { if (TUNE_SB1) *total = COSTS_N_INSNS (4); else if (TUNE_MIPS3000 || TUNE_MIPS3900 || TUNE_MIPS5000) *total = COSTS_N_INSNS (5); else if (TUNE_MIPS6000 || TUNE_MIPS5400 || TUNE_MIPS5500) *total = COSTS_N_INSNS (6); else
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -