Simplify mips branch handling. Retire T2 from use. Use TCG for branches.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4320 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
f730fd27b8
commit
3945462805
@ -148,7 +148,6 @@ struct CPUMIPSState {
|
|||||||
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
||||||
target_ulong t0;
|
target_ulong t0;
|
||||||
target_ulong t1;
|
target_ulong t1;
|
||||||
target_ulong t2;
|
|
||||||
#endif
|
#endif
|
||||||
target_ulong HI[MIPS_TC_MAX][MIPS_DSP_ACC];
|
target_ulong HI[MIPS_TC_MAX][MIPS_DSP_ACC];
|
||||||
target_ulong LO[MIPS_TC_MAX][MIPS_DSP_ACC];
|
target_ulong LO[MIPS_TC_MAX][MIPS_DSP_ACC];
|
||||||
|
@ -13,11 +13,9 @@ register struct CPUMIPSState *env asm(AREG0);
|
|||||||
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
||||||
#define T0 (env->t0)
|
#define T0 (env->t0)
|
||||||
#define T1 (env->t1)
|
#define T1 (env->t1)
|
||||||
#define T2 (env->t2)
|
|
||||||
#else
|
#else
|
||||||
register target_ulong T0 asm(AREG1);
|
register target_ulong T0 asm(AREG2);
|
||||||
register target_ulong T1 asm(AREG2);
|
register target_ulong T1 asm(AREG3);
|
||||||
register target_ulong T2 asm(AREG3);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (USE_HOST_FLOAT_REGS)
|
#if defined (USE_HOST_FLOAT_REGS)
|
||||||
|
@ -247,12 +247,6 @@
|
|||||||
#include "fop_template.c"
|
#include "fop_template.c"
|
||||||
#undef FTN
|
#undef FTN
|
||||||
|
|
||||||
void op_dup_T0 (void)
|
|
||||||
{
|
|
||||||
T2 = T0;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void op_load_HI (void)
|
void op_load_HI (void)
|
||||||
{
|
{
|
||||||
T0 = env->HI[env->current_tc][PARAM1];
|
T0 = env->HI[env->current_tc][PARAM1];
|
||||||
@ -1096,19 +1090,13 @@ OP_COND(ltz, (target_long)T0 < 0);
|
|||||||
/* Branch to register */
|
/* Branch to register */
|
||||||
void op_save_breg_target (void)
|
void op_save_breg_target (void)
|
||||||
{
|
{
|
||||||
env->btarget = T2;
|
env->btarget = T1;
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void op_restore_breg_target (void)
|
|
||||||
{
|
|
||||||
T2 = env->btarget;
|
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void op_breg (void)
|
void op_breg (void)
|
||||||
{
|
{
|
||||||
env->PC[env->current_tc] = T2;
|
env->PC[env->current_tc] = env->btarget;
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1129,25 +1117,13 @@ void op_save_btarget64 (void)
|
|||||||
/* Conditional branch */
|
/* Conditional branch */
|
||||||
void op_set_bcond (void)
|
void op_set_bcond (void)
|
||||||
{
|
{
|
||||||
T2 = T0;
|
env->bcond = T0;
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void op_save_bcond (void)
|
void op_jnz_bcond (void)
|
||||||
{
|
{
|
||||||
env->bcond = T2;
|
if (env->bcond)
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void op_restore_bcond (void)
|
|
||||||
{
|
|
||||||
T2 = env->bcond;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void op_jnz_T2 (void)
|
|
||||||
{
|
|
||||||
if (T2)
|
|
||||||
GOTO_LABEL_PARAM(1);
|
GOTO_LABEL_PARAM(1);
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
@ -3116,12 +3092,6 @@ void op_debug (void)
|
|||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void op_set_lladdr (void)
|
|
||||||
{
|
|
||||||
env->CP0_LLAddr = T2;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_pre_eret (void);
|
void debug_pre_eret (void);
|
||||||
void debug_post_eret (void);
|
void debug_post_eret (void);
|
||||||
void op_eret (void)
|
void op_eret (void)
|
||||||
|
@ -43,12 +43,6 @@ void glue(op_store_T1_gpr_gpr, REG) (void)
|
|||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void glue(op_load_gpr_T2_gpr, REG) (void)
|
|
||||||
{
|
|
||||||
T2 = env->gpr[env->current_tc][REG];
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void glue(op_load_srsgpr_T0_gpr, REG) (void)
|
void glue(op_load_srsgpr_T0_gpr, REG) (void)
|
||||||
{
|
{
|
||||||
@ -78,7 +72,6 @@ void glue(op_store_T0_srsgpr_gpr, REG) (void)
|
|||||||
|
|
||||||
SET_RESET(T0, _T0)
|
SET_RESET(T0, _T0)
|
||||||
SET_RESET(T1, _T1)
|
SET_RESET(T1, _T1)
|
||||||
SET_RESET(T2, _T2)
|
|
||||||
|
|
||||||
#undef SET_RESET
|
#undef SET_RESET
|
||||||
|
|
||||||
@ -92,7 +85,6 @@ SET_RESET(T2, _T2)
|
|||||||
|
|
||||||
SET64(T0, _T0)
|
SET64(T0, _T0)
|
||||||
SET64(T1, _T1)
|
SET64(T1, _T1)
|
||||||
SET64(T2, _T2)
|
|
||||||
|
|
||||||
#undef SET64
|
#undef SET64
|
||||||
|
|
||||||
|
@ -421,6 +421,8 @@ enum {
|
|||||||
OPC_NMSUB_PS= 0x3E | OPC_CP3,
|
OPC_NMSUB_PS= 0x3E | OPC_CP3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* global register indices */
|
||||||
|
static TCGv cpu_env, current_tc_regs, cpu_T[2];
|
||||||
|
|
||||||
const unsigned char *regnames[] =
|
const unsigned char *regnames[] =
|
||||||
{ "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
{ "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
||||||
@ -448,7 +450,6 @@ static always_inline void func(int n) \
|
|||||||
/* General purpose registers moves */
|
/* General purpose registers moves */
|
||||||
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
|
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
|
||||||
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
|
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
|
||||||
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
|
|
||||||
|
|
||||||
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
|
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
|
||||||
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
|
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
|
||||||
@ -599,15 +600,6 @@ do { \
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define GEN_LOAD_REG_T2(Rn) \
|
|
||||||
do { \
|
|
||||||
if (Rn == 0) { \
|
|
||||||
gen_op_reset_T2(); \
|
|
||||||
} else { \
|
|
||||||
gen_op_load_gpr_T2(Rn); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define GEN_LOAD_SRSREG_TN(Tn, Rn) \
|
#define GEN_LOAD_SRSREG_TN(Tn, Rn) \
|
||||||
do { \
|
do { \
|
||||||
if (Rn == 0) { \
|
if (Rn == 0) { \
|
||||||
@ -714,14 +706,9 @@ static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
|
|||||||
ctx->saved_hflags = ctx->hflags;
|
ctx->saved_hflags = ctx->hflags;
|
||||||
switch (ctx->hflags & MIPS_HFLAG_BMASK) {
|
switch (ctx->hflags & MIPS_HFLAG_BMASK) {
|
||||||
case MIPS_HFLAG_BR:
|
case MIPS_HFLAG_BR:
|
||||||
gen_op_save_breg_target();
|
|
||||||
break;
|
break;
|
||||||
case MIPS_HFLAG_BC:
|
case MIPS_HFLAG_BC:
|
||||||
gen_op_save_bcond();
|
|
||||||
/* fall through */
|
|
||||||
case MIPS_HFLAG_BL:
|
case MIPS_HFLAG_BL:
|
||||||
/* bcond was already saved by the BL insn */
|
|
||||||
/* fall through */
|
|
||||||
case MIPS_HFLAG_B:
|
case MIPS_HFLAG_B:
|
||||||
gen_save_btarget(ctx->btarget);
|
gen_save_btarget(ctx->btarget);
|
||||||
break;
|
break;
|
||||||
@ -734,15 +721,11 @@ static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
|
|||||||
ctx->saved_hflags = ctx->hflags;
|
ctx->saved_hflags = ctx->hflags;
|
||||||
switch (ctx->hflags & MIPS_HFLAG_BMASK) {
|
switch (ctx->hflags & MIPS_HFLAG_BMASK) {
|
||||||
case MIPS_HFLAG_BR:
|
case MIPS_HFLAG_BR:
|
||||||
gen_op_restore_breg_target();
|
|
||||||
break;
|
|
||||||
case MIPS_HFLAG_B:
|
|
||||||
ctx->btarget = env->btarget;
|
|
||||||
break;
|
break;
|
||||||
case MIPS_HFLAG_BC:
|
case MIPS_HFLAG_BC:
|
||||||
case MIPS_HFLAG_BL:
|
case MIPS_HFLAG_BL:
|
||||||
|
case MIPS_HFLAG_B:
|
||||||
ctx->btarget = env->btarget;
|
ctx->btarget = env->btarget;
|
||||||
gen_op_restore_bcond();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1770,6 +1753,19 @@ static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong des
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void tcg_gen_set_bcond(void)
|
||||||
|
{
|
||||||
|
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tcg_gen_jnz_bcond(int label)
|
||||||
|
{
|
||||||
|
int r_tmp = tcg_temp_new(TCG_TYPE_TL);
|
||||||
|
|
||||||
|
tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
|
||||||
|
tcg_gen_brcond_tl(TCG_COND_NE, r_tmp, tcg_const_i32(0), label);
|
||||||
|
}
|
||||||
|
|
||||||
/* Branches (before delay slot) */
|
/* Branches (before delay slot) */
|
||||||
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
|
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
|
||||||
int rs, int rt, int32_t offset)
|
int rs, int rt, int32_t offset)
|
||||||
@ -1838,7 +1834,8 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
|
|||||||
generate_exception(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GEN_LOAD_REG_T2(rs);
|
GEN_LOAD_REG_T1(rs);
|
||||||
|
gen_op_save_breg_target();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MIPS_INVAL("branch/jump");
|
MIPS_INVAL("branch/jump");
|
||||||
@ -1983,7 +1980,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
|
|||||||
MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
|
MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
|
||||||
not_likely:
|
not_likely:
|
||||||
ctx->hflags |= MIPS_HFLAG_BC;
|
ctx->hflags |= MIPS_HFLAG_BC;
|
||||||
gen_op_set_bcond();
|
tcg_gen_set_bcond();
|
||||||
break;
|
break;
|
||||||
case OPC_BLTZALL:
|
case OPC_BLTZALL:
|
||||||
gen_op_ltz();
|
gen_op_ltz();
|
||||||
@ -1991,8 +1988,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
|
|||||||
MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
|
MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
|
||||||
likely:
|
likely:
|
||||||
ctx->hflags |= MIPS_HFLAG_BL;
|
ctx->hflags |= MIPS_HFLAG_BL;
|
||||||
gen_op_set_bcond();
|
tcg_gen_set_bcond();
|
||||||
gen_op_save_bcond();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MIPS_INVAL("conditional branch/jump");
|
MIPS_INVAL("conditional branch/jump");
|
||||||
@ -4863,8 +4859,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
|
|||||||
opn = "bc1tl";
|
opn = "bc1tl";
|
||||||
likely:
|
likely:
|
||||||
ctx->hflags |= MIPS_HFLAG_BL;
|
ctx->hflags |= MIPS_HFLAG_BL;
|
||||||
gen_op_set_bcond();
|
tcg_gen_set_bcond();
|
||||||
gen_op_save_bcond();
|
|
||||||
break;
|
break;
|
||||||
case OPC_BC1FANY2:
|
case OPC_BC1FANY2:
|
||||||
gen_op_bc1any2f(cc);
|
gen_op_bc1any2f(cc);
|
||||||
@ -4883,7 +4878,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
|
|||||||
opn = "bc1any4t";
|
opn = "bc1any4t";
|
||||||
not_likely:
|
not_likely:
|
||||||
ctx->hflags |= MIPS_HFLAG_BC;
|
ctx->hflags |= MIPS_HFLAG_BC;
|
||||||
gen_op_set_bcond();
|
tcg_gen_set_bcond();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MIPS_INVAL(opn);
|
MIPS_INVAL(opn);
|
||||||
@ -6056,7 +6051,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
|||||||
/* Handle blikely not taken case */
|
/* Handle blikely not taken case */
|
||||||
MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
|
MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
|
||||||
l1 = gen_new_label();
|
l1 = gen_new_label();
|
||||||
gen_op_jnz_T2(l1);
|
tcg_gen_jnz_bcond(l1);
|
||||||
gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
|
gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
|
||||||
gen_goto_tb(ctx, 1, ctx->pc + 4);
|
gen_goto_tb(ctx, 1, ctx->pc + 4);
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
@ -6612,7 +6607,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
|||||||
{
|
{
|
||||||
int l1;
|
int l1;
|
||||||
l1 = gen_new_label();
|
l1 = gen_new_label();
|
||||||
gen_op_jnz_T2(l1);
|
tcg_gen_jnz_bcond(l1);
|
||||||
gen_goto_tb(ctx, 1, ctx->pc + 4);
|
gen_goto_tb(ctx, 1, ctx->pc + 4);
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
gen_goto_tb(ctx, 0, ctx->btarget);
|
gen_goto_tb(ctx, 0, ctx->btarget);
|
||||||
@ -6877,6 +6872,29 @@ void cpu_dump_state (CPUState *env, FILE *f,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mips_tcg_init(void)
|
||||||
|
{
|
||||||
|
static int inited;
|
||||||
|
|
||||||
|
/* Initialize various static tables. */
|
||||||
|
if (inited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
|
||||||
|
current_tc_regs = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG1, "current_tc_regs");
|
||||||
|
#if TARGET_LONG_BITS > HOST_LONG_BITS
|
||||||
|
cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
|
||||||
|
TCG_AREG0, offsetof(CPUState, t0), "T0");
|
||||||
|
cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
|
||||||
|
TCG_AREG0, offsetof(CPUState, t1), "T1");
|
||||||
|
#else
|
||||||
|
cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T0");
|
||||||
|
cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T1");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inited = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#include "translate_init.c"
|
#include "translate_init.c"
|
||||||
|
|
||||||
CPUMIPSState *cpu_mips_init (const char *cpu_model)
|
CPUMIPSState *cpu_mips_init (const char *cpu_model)
|
||||||
@ -6894,6 +6912,7 @@ CPUMIPSState *cpu_mips_init (const char *cpu_model)
|
|||||||
|
|
||||||
cpu_exec_init(env);
|
cpu_exec_init(env);
|
||||||
env->cpu_model_str = cpu_model;
|
env->cpu_model_str = cpu_model;
|
||||||
|
mips_tcg_init();
|
||||||
cpu_reset(env);
|
cpu_reset(env);
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user