aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2014-03-23 17:45:23 +0000
committerRichard Henderson <rth@twiddle.net>2014-05-24 08:45:13 -0700
commitf9a716325facc32064d491ddbce4aa2e81f9a1ce (patch)
treef59c4f4225009f90f05450595465ecfeb44944d9
parent7dae901d2d0476945a2dc353bb685501fd365868 (diff)
tcg-mips: Split large ldst offsets
Use this to reduce goto_tb by one insn. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r--tcg/mips/tcg-target.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 2d2073f7e9..5ccfb1d76c 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -480,16 +480,18 @@ static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
}
}
-static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg,
- TCGReg arg1, TCGArg arg2)
+static void tcg_out_ldst(TCGContext *s, int opc, TCGReg data,
+ TCGReg addr, intptr_t ofs)
{
- if (arg2 == (int16_t) arg2) {
- tcg_out_opc_imm(s, opc, arg, arg1, arg2);
- } else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
- tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
- tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
+ int16_t lo = ofs;
+ if (ofs != lo) {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, ofs - lo);
+ if (addr != TCG_REG_ZERO) {
+ tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, addr);
+ }
+ addr = TCG_REG_AT;
}
+ tcg_out_opc_imm(s, opc, data, addr, lo);
}
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
@@ -1315,9 +1317,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_abort();
} else {
/* indirect jump method */
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT,
- (uintptr_t)(s->tb_next + args[0]));
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_ZERO,
+ (uintptr_t)(s->tb_next + args[0]));
tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
}
tcg_out_nop(s);