Convert some MIPS load/store instructions to TCG.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4369 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
36271893ab
commit
aaa9128a02
@ -247,30 +247,6 @@
|
||||
#include "fop_template.c"
|
||||
#undef FTN
|
||||
|
||||
void op_load_HI (void)
|
||||
{
|
||||
T0 = env->HI[env->current_tc][PARAM1];
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_store_HI (void)
|
||||
{
|
||||
env->HI[env->current_tc][PARAM1] = T0;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_load_LO (void)
|
||||
{
|
||||
T0 = env->LO[env->current_tc][PARAM1];
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_store_LO (void)
|
||||
{
|
||||
env->LO[env->current_tc][PARAM1] = T0;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* Load and store */
|
||||
#define MEMSUFFIX _raw
|
||||
#include "op_mem.c"
|
||||
|
@ -56,37 +56,3 @@ void glue(op_store_T0_srsgpr_gpr, REG) (void)
|
||||
FORCE_RET();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (TN)
|
||||
#define SET_RESET(treg, tregname) \
|
||||
void glue(op_set, tregname)(void) \
|
||||
{ \
|
||||
treg = (int32_t)PARAM1; \
|
||||
FORCE_RET(); \
|
||||
} \
|
||||
void glue(op_reset, tregname)(void) \
|
||||
{ \
|
||||
treg = 0; \
|
||||
FORCE_RET(); \
|
||||
} \
|
||||
|
||||
SET_RESET(T0, _T0)
|
||||
SET_RESET(T1, _T1)
|
||||
|
||||
#undef SET_RESET
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define SET64(treg, tregname) \
|
||||
void glue(op_set64, tregname)(void) \
|
||||
{ \
|
||||
treg = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; \
|
||||
FORCE_RET(); \
|
||||
}
|
||||
|
||||
SET64(T0, _T0)
|
||||
SET64(T1, _T1)
|
||||
|
||||
#undef SET64
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -488,6 +488,50 @@ static inline void gen_op_store_srsgpr_T0(int reg)
|
||||
tcg_gen_st_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg);
|
||||
}
|
||||
|
||||
/* Load immediates, zero being a special case. */
|
||||
static inline void gen_op_set_T0(target_ulong arg)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_T[0], arg);
|
||||
}
|
||||
|
||||
static inline void gen_op_set_T1(target_ulong arg)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_T[1], arg);
|
||||
}
|
||||
|
||||
static inline void gen_op_reset_T0(void)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_T[0], 0);
|
||||
}
|
||||
|
||||
static inline void gen_op_reset_T1(void)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_T[1], 0);
|
||||
}
|
||||
|
||||
/* Moves to/from HI/LO registers. */
|
||||
static inline void gen_op_load_HI(int reg)
|
||||
{
|
||||
tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, HI[reg]));
|
||||
}
|
||||
|
||||
static inline void gen_op_store_HI(int reg)
|
||||
{
|
||||
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, HI[reg]));
|
||||
}
|
||||
|
||||
static inline void gen_op_load_LO(int reg)
|
||||
{
|
||||
tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, LO[reg]));
|
||||
}
|
||||
|
||||
static inline void gen_op_store_LO(int reg)
|
||||
{
|
||||
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, LO[reg]));
|
||||
}
|
||||
|
||||
|
||||
/* Floating point register moves. */
|
||||
static const char *fregnames[] =
|
||||
{ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
||||
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
|
||||
@ -639,18 +683,6 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define GEN_LOAD_IMM_TN(Tn, Imm) \
|
||||
do { \
|
||||
if (Imm == 0) { \
|
||||
glue(gen_op_reset_, Tn)(); \
|
||||
} else if ((int32_t)Imm == Imm) { \
|
||||
glue(gen_op_set_, Tn)(Imm); \
|
||||
} else { \
|
||||
glue(gen_op_set64_, Tn)(((uint64_t)Imm) >> 32, (uint32_t)Imm); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define GEN_LOAD_IMM_TN(Tn, Imm) \
|
||||
do { \
|
||||
if (Imm == 0) { \
|
||||
@ -659,7 +691,6 @@ do { \
|
||||
glue(gen_op_set_, Tn)(Imm); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define GEN_STORE_T0_REG(Rn) \
|
||||
do { \
|
||||
@ -759,6 +790,24 @@ static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static always_inline void
|
||||
generate_tcg_exception_err (DisasContext *ctx, int excp, int err)
|
||||
{
|
||||
save_cpu_state(ctx, 1);
|
||||
if (err == 0)
|
||||
gen_op_raise_exception(excp);
|
||||
else
|
||||
gen_op_raise_exception_err(excp, err);
|
||||
gen_op_interrupt_restart();
|
||||
tcg_gen_exit_tb(0);
|
||||
}
|
||||
|
||||
static always_inline void
|
||||
generate_tcg_exception (DisasContext *ctx, int excp)
|
||||
{
|
||||
generate_tcg_exception_err (ctx, excp, 0);
|
||||
}
|
||||
|
||||
static always_inline void generate_exception_err (DisasContext *ctx, int excp, int err)
|
||||
{
|
||||
#if defined MIPS_DEBUG_DISAS
|
||||
@ -864,30 +913,15 @@ static GenOpFunc *gen_op_s##width[] = { \
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
OP_LD_TABLE(d);
|
||||
OP_LD_TABLE(dl);
|
||||
OP_LD_TABLE(dr);
|
||||
OP_ST_TABLE(d);
|
||||
OP_ST_TABLE(dl);
|
||||
OP_ST_TABLE(dr);
|
||||
OP_LD_TABLE(ld);
|
||||
OP_ST_TABLE(cd);
|
||||
OP_LD_TABLE(wu);
|
||||
#endif
|
||||
OP_LD_TABLE(w);
|
||||
OP_LD_TABLE(wl);
|
||||
OP_LD_TABLE(wr);
|
||||
OP_ST_TABLE(w);
|
||||
OP_ST_TABLE(wl);
|
||||
OP_ST_TABLE(wr);
|
||||
OP_LD_TABLE(h);
|
||||
OP_LD_TABLE(hu);
|
||||
OP_ST_TABLE(h);
|
||||
OP_LD_TABLE(b);
|
||||
OP_LD_TABLE(bu);
|
||||
OP_ST_TABLE(b);
|
||||
OP_LD_TABLE(l);
|
||||
OP_ST_TABLE(c);
|
||||
OP_LD_TABLE(wc1);
|
||||
OP_ST_TABLE(wc1);
|
||||
OP_LD_TABLE(dc1);
|
||||
@ -895,6 +929,96 @@ OP_ST_TABLE(dc1);
|
||||
OP_LD_TABLE(uxc1);
|
||||
OP_ST_TABLE(uxc1);
|
||||
|
||||
#define OP_LD(insn,fname) \
|
||||
void inline op_ldst_##insn(DisasContext *ctx) \
|
||||
{ \
|
||||
tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx); \
|
||||
}
|
||||
OP_LD(lb,ld8s);
|
||||
OP_LD(lbu,ld8u);
|
||||
OP_LD(lh,ld16s);
|
||||
OP_LD(lhu,ld16u);
|
||||
OP_LD(lw,ld32s);
|
||||
#if defined(TARGET_MIPS64)
|
||||
OP_LD(lwu,ld32u);
|
||||
OP_LD(ld,ld64);
|
||||
#endif
|
||||
#undef OP_LD
|
||||
|
||||
#define OP_ST(insn,fname) \
|
||||
void inline op_ldst_##insn(DisasContext *ctx) \
|
||||
{ \
|
||||
tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx); \
|
||||
}
|
||||
OP_ST(sb,st8);
|
||||
OP_ST(sh,st16);
|
||||
OP_ST(sw,st32);
|
||||
#if defined(TARGET_MIPS64)
|
||||
OP_ST(sd,st64);
|
||||
#endif
|
||||
#undef OP_ST
|
||||
|
||||
#define OP_LD_ATOMIC(insn,fname) \
|
||||
void inline op_ldst_##insn(DisasContext *ctx) \
|
||||
{ \
|
||||
tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); \
|
||||
tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx); \
|
||||
tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUState, CP0_LLAddr)); \
|
||||
}
|
||||
OP_LD_ATOMIC(ll,ld32s);
|
||||
#if defined(TARGET_MIPS64)
|
||||
OP_LD_ATOMIC(lld,ld64);
|
||||
#endif
|
||||
#undef OP_LD_ATOMIC
|
||||
|
||||
#define OP_ST_ATOMIC(insn,fname,almask) \
|
||||
void inline op_ldst_##insn(DisasContext *ctx) \
|
||||
{ \
|
||||
int r_tmp = tcg_temp_new(TCG_TYPE_TL); \
|
||||
int l1 = gen_new_label(); \
|
||||
int l2 = gen_new_label(); \
|
||||
int l3 = gen_new_label(); \
|
||||
\
|
||||
tcg_gen_andi_tl(r_tmp, cpu_T[0], almask); \
|
||||
tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp, tcg_const_tl(0), l1); \
|
||||
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
|
||||
generate_tcg_exception(ctx, EXCP_AdES); \
|
||||
gen_set_label(l1); \
|
||||
tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], r_tmp, l2); \
|
||||
tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx); \
|
||||
tcg_gen_movi_tl(cpu_T[0], 1); \
|
||||
tcg_gen_br(l3); \
|
||||
gen_set_label(l2); \
|
||||
tcg_gen_movi_tl(cpu_T[0], 0); \
|
||||
gen_set_label(l3); \
|
||||
}
|
||||
OP_ST_ATOMIC(sc,st32,0x3);
|
||||
#if defined(TARGET_MIPS64)
|
||||
OP_ST_ATOMIC(scd,st64,0x7);
|
||||
#endif
|
||||
#undef OP_ST_ATOMIC
|
||||
|
||||
void inline op_ldst_lwc1(DisasContext *ctx)
|
||||
{
|
||||
op_ldst(lwc1);
|
||||
}
|
||||
|
||||
void inline op_ldst_ldc1(DisasContext *ctx)
|
||||
{
|
||||
op_ldst(ldc1);
|
||||
}
|
||||
|
||||
void inline op_ldst_swc1(DisasContext *ctx)
|
||||
{
|
||||
op_ldst(swc1);
|
||||
}
|
||||
|
||||
void inline op_ldst_sdc1(DisasContext *ctx)
|
||||
{
|
||||
op_ldst(sdc1);
|
||||
}
|
||||
|
||||
/* Load and store */
|
||||
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
|
||||
int base, int16_t offset)
|
||||
@ -915,29 +1039,29 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
|
||||
switch (opc) {
|
||||
#if defined(TARGET_MIPS64)
|
||||
case OPC_LWU:
|
||||
op_ldst(lwu);
|
||||
op_ldst_lwu(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lwu";
|
||||
break;
|
||||
case OPC_LD:
|
||||
op_ldst(ld);
|
||||
op_ldst_ld(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "ld";
|
||||
break;
|
||||
case OPC_LLD:
|
||||
op_ldst(lld);
|
||||
op_ldst_lld(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lld";
|
||||
break;
|
||||
case OPC_SD:
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
op_ldst(sd);
|
||||
op_ldst_sd(ctx);
|
||||
opn = "sd";
|
||||
break;
|
||||
case OPC_SCD:
|
||||
save_cpu_state(ctx, 1);
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
op_ldst(scd);
|
||||
op_ldst_scd(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "scd";
|
||||
break;
|
||||
@ -965,42 +1089,42 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
|
||||
break;
|
||||
#endif
|
||||
case OPC_LW:
|
||||
op_ldst(lw);
|
||||
op_ldst_lw(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lw";
|
||||
break;
|
||||
case OPC_SW:
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
op_ldst(sw);
|
||||
op_ldst_sw(ctx);
|
||||
opn = "sw";
|
||||
break;
|
||||
case OPC_LH:
|
||||
op_ldst(lh);
|
||||
op_ldst_lh(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lh";
|
||||
break;
|
||||
case OPC_SH:
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
op_ldst(sh);
|
||||
op_ldst_sh(ctx);
|
||||
opn = "sh";
|
||||
break;
|
||||
case OPC_LHU:
|
||||
op_ldst(lhu);
|
||||
op_ldst_lhu(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lhu";
|
||||
break;
|
||||
case OPC_LB:
|
||||
op_ldst(lb);
|
||||
op_ldst_lb(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lb";
|
||||
break;
|
||||
case OPC_SB:
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
op_ldst(sb);
|
||||
op_ldst_sb(ctx);
|
||||
opn = "sb";
|
||||
break;
|
||||
case OPC_LBU:
|
||||
op_ldst(lbu);
|
||||
op_ldst_lbu(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "lbu";
|
||||
break;
|
||||
@ -1027,14 +1151,14 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
|
||||
opn = "swr";
|
||||
break;
|
||||
case OPC_LL:
|
||||
op_ldst(ll);
|
||||
op_ldst_ll(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "ll";
|
||||
break;
|
||||
case OPC_SC:
|
||||
save_cpu_state(ctx, 1);
|
||||
GEN_LOAD_REG_T1(rt);
|
||||
op_ldst(sc);
|
||||
op_ldst_sc(ctx);
|
||||
GEN_STORE_T0_REG(rt);
|
||||
opn = "sc";
|
||||
break;
|
||||
@ -1065,23 +1189,23 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
|
||||
memory access. */
|
||||
switch (opc) {
|
||||
case OPC_LWC1:
|
||||
op_ldst(lwc1);
|
||||
op_ldst_lwc1(ctx);
|
||||
GEN_STORE_FTN_FREG(ft, WT0);
|
||||
opn = "lwc1";
|
||||
break;
|
||||
case OPC_SWC1:
|
||||
GEN_LOAD_FREG_FTN(WT0, ft);
|
||||
op_ldst(swc1);
|
||||
op_ldst_swc1(ctx);
|
||||
opn = "swc1";
|
||||
break;
|
||||
case OPC_LDC1:
|
||||
op_ldst(ldc1);
|
||||
op_ldst_ldc1(ctx);
|
||||
GEN_STORE_FTN_FREG(ft, DT0);
|
||||
opn = "ldc1";
|
||||
break;
|
||||
case OPC_SDC1:
|
||||
GEN_LOAD_FREG_FTN(DT0, ft);
|
||||
op_ldst(sdc1);
|
||||
op_ldst_sdc1(ctx);
|
||||
opn = "sdc1";
|
||||
break;
|
||||
default:
|
||||
@ -5852,14 +5976,14 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||
switch (opc) {
|
||||
case OPC_LWXC1:
|
||||
check_cop1x(ctx);
|
||||
op_ldst(lwc1);
|
||||
op_ldst_lwc1(ctx);
|
||||
GEN_STORE_FTN_FREG(fd, WT0);
|
||||
opn = "lwxc1";
|
||||
break;
|
||||
case OPC_LDXC1:
|
||||
check_cop1x(ctx);
|
||||
check_cp1_registers(ctx, fd);
|
||||
op_ldst(ldc1);
|
||||
op_ldst_ldc1(ctx);
|
||||
GEN_STORE_FTN_FREG(fd, DT0);
|
||||
opn = "ldxc1";
|
||||
break;
|
||||
@ -5872,7 +5996,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||
case OPC_SWXC1:
|
||||
check_cop1x(ctx);
|
||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||
op_ldst(swc1);
|
||||
op_ldst_swc1(ctx);
|
||||
opn = "swxc1";
|
||||
store = 1;
|
||||
break;
|
||||
@ -5880,7 +6004,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||
check_cop1x(ctx);
|
||||
check_cp1_registers(ctx, fs);
|
||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||
op_ldst(sdc1);
|
||||
op_ldst_sdc1(ctx);
|
||||
opn = "sdxc1";
|
||||
store = 1;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user