Use TCG for MIPS GPR moves.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4356 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2008-05-06 10:57:59 +00:00
parent b7ef7bf225
commit 958fb4a92c
4 changed files with 83 additions and 42 deletions

View File

@ -158,6 +158,7 @@ struct CPUMIPSState {
CPUMIPSTLBContext *tlb;
CPUMIPSFPUContext *fpu;
uint32_t current_tc;
target_ulong *current_tc_gprs;
uint32_t SEGBITS;
target_ulong SEGMask;

View File

@ -14,8 +14,8 @@ register struct CPUMIPSState *env asm(AREG0);
#define T0 (env->t0)
#define T1 (env->t1)
#else
register target_ulong T0 asm(AREG2);
register target_ulong T1 asm(AREG3);
register target_ulong T0 asm(AREG1);
register target_ulong T1 asm(AREG2);
#endif
#if defined (USE_HOST_FLOAT_REGS)

View File

@ -422,41 +422,71 @@ enum {
};
/* global register indices */
static TCGv cpu_env, current_tc_regs, cpu_T[2];
static TCGv cpu_env, current_tc_gprs, cpu_T[2];
/* General purpose registers moves */
const unsigned char *regnames[] =
{ "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
/* Warning: no function for r0 register (hard wired to zero) */
#define GEN32(func, NAME) \
static GenOpFunc *NAME ## _table [32] = { \
NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
}; \
static always_inline void func(int n) \
{ \
NAME ## _table[n](); \
static inline void gen_op_load_gpr_TN(int t_index, int reg)
{
tcg_gen_ld_tl(cpu_T[t_index], current_tc_gprs, sizeof(target_ulong) * reg);
}
/* General purpose registers moves */
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
static inline void gen_op_load_gpr_T0(int reg)
{
gen_op_load_gpr_TN(0, reg);
}
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
static inline void gen_op_load_gpr_T1(int reg)
{
gen_op_load_gpr_TN(1, reg);
}
static inline void gen_op_store_gpr_TN(int t_index, int reg)
{
tcg_gen_st_tl(cpu_T[t_index], current_tc_gprs, sizeof(target_ulong) * reg);
}
static inline void gen_op_store_gpr_T0(int reg)
{
gen_op_store_gpr_TN(0, reg);
}
static inline void gen_op_store_gpr_T1(int reg)
{
gen_op_store_gpr_TN(1, reg);
}
/* Moves to/from shadow registers */
GEN32(gen_op_load_srsgpr_T0, gen_op_load_srsgpr_T0_gpr);
GEN32(gen_op_store_T0_srsgpr, gen_op_store_T0_srsgpr_gpr);
static inline void gen_op_load_srsgpr_T0(int reg)
{
int r_tmp = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
tcg_gen_ld_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg);
}
static inline void gen_op_store_srsgpr_T0(int reg)
{
int r_tmp = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl));
tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS);
tcg_gen_andi_i32(r_tmp, r_tmp, 0xf);
tcg_gen_muli_i32(r_tmp, r_tmp, sizeof(target_ulong) * 32);
tcg_gen_add_i32(r_tmp, cpu_env, r_tmp);
tcg_gen_st_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg);
}
static const char *fregnames[] =
{ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
@ -634,7 +664,7 @@ do { \
#define GEN_STORE_T0_REG(Rn) \
do { \
if (Rn != 0) { \
glue(gen_op_store_T0,_gpr)(Rn); \
gen_op_store_gpr_T0(Rn); \
ctx->glue(last_T0,_store) = gen_opc_ptr; \
ctx->glue(last_T0,_gpr) = Rn; \
} \
@ -643,14 +673,13 @@ do { \
#define GEN_STORE_T1_REG(Rn) \
do { \
if (Rn != 0) \
glue(gen_op_store_T1,_gpr)(Rn); \
gen_op_store_gpr_T1(Rn); \
} while (0)
#define GEN_STORE_TN_SRSREG(Rn, Tn) \
do { \
if (Rn != 0) { \
glue(glue(gen_op_store_, Tn),_srsgpr)(Rn); \
} \
if (Rn != 0) \
glue(gen_op_store_srsgpr_, Tn)(Rn); \
} while (0)
#define GEN_LOAD_FREG_FTN(FTn, Fn) \
@ -813,6 +842,7 @@ static always_inline void check_mips_64(DisasContext *ctx)
generate_exception(ctx, EXCP_RI);
}
/* load/store instructions. */
#if defined(CONFIG_USER_ONLY)
#define op_ldst(name) gen_op_##name##_raw()
#define OP_LD_TABLE(width)
@ -1638,7 +1668,7 @@ static void gen_cl (DisasContext *ctx, uint32_t opc,
generate_exception(ctx, EXCP_RI);
return;
}
gen_op_store_T0_gpr(rd);
gen_op_store_gpr_T0(rd);
MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
}
@ -1870,12 +1900,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
return;
case OPC_BLTZAL: /* 0 < 0 */
GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
gen_op_store_T0_gpr(31);
gen_op_store_gpr_T0(31);
MIPS_DEBUG("bnever and link");
return;
case OPC_BLTZALL: /* 0 < 0 likely */
GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
gen_op_store_T0_gpr(31);
gen_op_store_gpr_T0(31);
/* Skip the instruction in the delay slot */
MIPS_DEBUG("bnever, link and skip");
ctx->pc += 4;
@ -2002,7 +2032,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
ctx->btarget = btarget;
if (blink > 0) {
GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
gen_op_store_T0_gpr(blink);
gen_op_store_gpr_T0(blink);
}
}
@ -4721,7 +4751,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
return;
}
gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
gen_op_store_T0_gpr(rt);
gen_op_store_gpr_T0(rt);
opn = "mfc0";
break;
case OPC_MTC0:
@ -4738,7 +4768,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
return;
}
gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
gen_op_store_T0_gpr(rt);
gen_op_store_gpr_T0(rt);
opn = "dmfc0";
break;
case OPC_DMTC0:
@ -4757,7 +4787,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
}
gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
gen_op_store_T0_gpr(rd);
gen_op_store_gpr_T0(rd);
opn = "mftr";
break;
case OPC_MTTR:
@ -6806,8 +6836,13 @@ void fpu_dump_state(CPUState *env, FILE *f,
void dump_fpu (CPUState *env)
{
if (loglevel) {
fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
env->PC[env->current_tc], env->HI[env->current_tc][0], env->LO[env->current_tc][0], env->hflags, env->btarget, env->bcond);
fprintf(logfile,
"pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
" LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx
" %04x\n",
env->PC[env->current_tc], env->HI[env->current_tc][0],
env->LO[env->current_tc][0], env->hflags, env->btarget,
env->bcond);
fpu_dump_state(env, logfile, fprintf, 0);
}
}
@ -6881,15 +6916,18 @@ static void mips_tcg_init(void)
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");
current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR,
TCG_AREG0,
offsetof(CPUState, current_tc_gprs),
"current_tc_gprs");
#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");
cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
#endif
inited = 1;

View File

@ -543,6 +543,8 @@ static int cpu_mips_register (CPUMIPSState *env, const mips_def_t *def)
env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask;
env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
env->CP0_SRSCtl = def->CP0_SRSCtl;
env->current_tc = 0;
env->current_tc_gprs = &env->gpr[env->current_tc][0];
env->SEGBITS = def->SEGBITS;
env->SEGMask = (target_ulong)((1ULL << def->SEGBITS) - 1);
#if defined(TARGET_MIPS64)