summaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-06 21:40:48 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-06 21:40:48 +0000
commitaaa9128a024df25dcd80c62b01fa72a4c0988b07 (patch)
tree7bc38f09782ece4e346420f9afa63100bc1d0de9 /target-mips
parent36271893ab4426ec7a0c73a9e843f1798e400fda (diff)
downloadqemu-aaa9128a024df25dcd80c62b01fa72a4c0988b07.tar.gz
Convert some MIPS load/store instructions to TCG.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4369 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/op.c24
-rw-r--r--target-mips/op_template.c34
-rw-r--r--target-mips/translate.c226
3 files changed, 175 insertions, 109 deletions
diff --git a/target-mips/op.c b/target-mips/op.c
index 00b779967e..07e057b744 100644
--- a/target-mips/op.c
+++ b/target-mips/op.c
@@ -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"
diff --git a/target-mips/op_template.c b/target-mips/op_template.c
index e2802a3cc5..dd4cef0068 100644
--- a/target-mips/op_template.c
+++ b/target-mips/op_template.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
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2ddb0fdf67..c81151d68c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -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;