aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-28 17:03:28 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-28 17:03:28 +0000
commit9b9e4393dd08481530f8d6389ed0ac64405aa4fa (patch)
treea221c5135f3c27133b028cdad6669866bf0a33d0
parent4020f27707e748a2da58de72461dc1befd6bc9c5 (diff)
MIPS64 addressing fixes, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2888 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--target-mips/op.c16
-rw-r--r--target-mips/op_template.c16
-rw-r--r--target-mips/translate.c58
3 files changed, 81 insertions, 9 deletions
diff --git a/target-mips/op.c b/target-mips/op.c
index 8f67041ca2..f4598fb46c 100644
--- a/target-mips/op.c
+++ b/target-mips/op.c
@@ -976,6 +976,14 @@ void op_save_btarget (void)
RETURN();
}
+#ifdef TARGET_MIPS64
+void op_save_btarget64 (void)
+{
+ env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
+ RETURN();
+}
+#endif
+
/* Conditional branch */
void op_set_bcond (void)
{
@@ -2409,6 +2417,14 @@ void op_save_pc (void)
RETURN();
}
+#ifdef TARGET_MIPS64
+void op_save_pc64 (void)
+{
+ env->PC = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
+ RETURN();
+}
+#endif
+
void op_interrupt_restart (void)
{
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
diff --git a/target-mips/op_template.c b/target-mips/op_template.c
index 04677cd840..8236acc18e 100644
--- a/target-mips/op_template.c
+++ b/target-mips/op_template.c
@@ -68,4 +68,20 @@ SET_RESET(T1, _T1)
SET_RESET(T2, _T2)
#undef SET_RESET
+
+#ifdef TARGET_MIPS64
+#define SET64(treg, tregname) \
+ void glue(op_set64, tregname)(void) \
+ { \
+ treg = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2; \
+ RETURN(); \
+ }
+
+SET64(T0, _T0)
+SET64(T1, _T1)
+SET64(T2, _T2)
+
+#undef SET64
+
+#endif
#endif
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4da5b7b854..ffa5c4bc9f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -569,6 +569,18 @@ do { \
} \
} while (0)
+#ifdef 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) { \
@@ -577,6 +589,7 @@ do { \
glue(gen_op_set_, Tn)(Imm); \
} \
} while (0)
+#endif
#define GEN_STORE_TN_REG(Rn, Tn) \
do { \
@@ -595,6 +608,32 @@ do { \
glue(gen_op_store_fpr_, FTn)(Fn); \
} while (0)
+static inline void gen_save_pc(target_ulong pc)
+{
+#ifdef TARGET_MIPS64
+ if (pc == (int32_t)pc) {
+ gen_op_save_pc(pc);
+ } else {
+ gen_op_save_pc64(pc >> 32, (uint32_t)pc);
+ }
+#else
+ gen_op_save_pc(pc);
+#endif
+}
+
+static inline void gen_save_btarget(target_ulong btarget)
+{
+#ifdef TARGET_MIPS64
+ if (btarget == (int32_t)btarget) {
+ gen_op_save_btarget(btarget);
+ } else {
+ gen_op_save_btarget64(btarget >> 32, (uint32_t)btarget);
+ }
+#else
+ gen_op_save_btarget(btarget);
+#endif
+}
+
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
{
#if defined MIPS_DEBUG_DISAS
@@ -604,7 +643,7 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
}
#endif
if (do_save_pc && ctx->pc != ctx->saved_pc) {
- gen_op_save_pc(ctx->pc);
+ gen_save_pc(ctx->pc);
ctx->saved_pc = ctx->pc;
}
if (ctx->hflags != ctx->saved_hflags) {
@@ -621,7 +660,7 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
/* bcond was already saved by the BL insn */
/* fall through */
case MIPS_HFLAG_B:
- gen_op_save_btarget(ctx->btarget);
+ gen_save_btarget(ctx->btarget);
break;
}
}
@@ -946,7 +985,7 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
GEN_LOAD_IMM_TN(T1, uimm);
break;
case OPC_LUI:
- GEN_LOAD_IMM_TN(T0, uimm << 16);
+ GEN_LOAD_IMM_TN(T0, imm << 16);
break;
case OPC_SLL:
case OPC_SRA:
@@ -1491,10 +1530,10 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
gen_op_goto_tb0(TBPARAM(tb));
else
gen_op_goto_tb1(TBPARAM(tb));
- gen_op_save_pc(dest);
+ gen_save_pc(dest);
gen_op_set_T0((long)tb + n);
} else {
- gen_op_save_pc(dest);
+ gen_save_pc(dest);
gen_op_reset_T0();
}
gen_op_exit_tb();
@@ -1556,7 +1595,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
case OPC_J:
case OPC_JAL:
/* Jump to immediate */
- btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset;
+ btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
break;
case OPC_JR:
case OPC_JALR:
@@ -1602,12 +1641,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
MIPS_DEBUG("bnever (NOP)");
return;
case OPC_BLTZAL: /* 0 < 0 */
- gen_op_set_T0(ctx->pc + 8);
+ GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
gen_op_store_T0_gpr(31);
MIPS_DEBUG("bnever and link");
return;
case OPC_BLTZALL: /* 0 < 0 likely */
- gen_op_set_T0(ctx->pc + 8);
+ GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
gen_op_store_T0_gpr(31);
/* Skip the instruction in the delay slot */
MIPS_DEBUG("bnever, link and skip");
@@ -1732,9 +1771,10 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
}
MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
blink, ctx->hflags, btarget);
+
ctx->btarget = btarget;
if (blink > 0) {
- gen_op_set_T0(ctx->pc + 8);
+ GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
gen_op_store_T0_gpr(blink);
}
}