aboutsummaryrefslogtreecommitdiff
path: root/target-sh4
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-06-18 19:12:54 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-06-18 19:12:54 +0000
commit9c2a9ea1b1fe221566ca6c3f873da1454cadd263 (patch)
treeb0384568db3ada60f572ef5750a8d316d0f266d1 /target-sh4
parent397e923f7f78e99bc547b0a730c225d78dfe878b (diff)
SH bugfixes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1991 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sh4')
-rw-r--r--target-sh4/cpu.h4
-rw-r--r--target-sh4/exec.h2
-rw-r--r--target-sh4/op.c13
-rw-r--r--target-sh4/translate.c32
4 files changed, 24 insertions, 27 deletions
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index c71af74373..ef818fdf25 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -45,7 +45,9 @@
#define FPSCR_PR (1 << 19)
#define FPSCR_DN (1 << 18)
-#define DELAY_SLOT (1 << 0)
+#define DELAY_SLOT (1 << 0) /* Must be the same as SR_T. */
+/* This flag is set if the next insn is a delay slot for a conditional jump.
+ The dynamic value of the DELAY_SLOT determines whether the jup is taken. */
#define DELAY_SLOT_CONDITIONAL (1 << 1)
/* Those are used in contexts only */
#define BRANCH (1 << 2)
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
index b828206121..3563300307 100644
--- a/target-sh4/exec.h
+++ b/target-sh4/exec.h
@@ -26,7 +26,7 @@
register struct CPUSH4State *env asm(AREG0);
register uint32_t T0 asm(AREG1);
register uint32_t T1 asm(AREG2);
-register uint32_t T2 asm(AREG3);
+//register uint32_t T2 asm(AREG3);
#define FT0 (env->ft0)
#define FT1 (env->ft1)
diff --git a/target-sh4/op.c b/target-sh4/op.c
index 64f952fc54..d3b68bc665 100644
--- a/target-sh4/op.c
+++ b/target-sh4/op.c
@@ -109,17 +109,15 @@ void OPPROTO op_not_T0(void)
void OPPROTO op_bf_s(void)
{
- T2 = ~env->sr;
env->delayed_pc = PARAM1;
- set_flag(DELAY_SLOT_CONDITIONAL);
+ set_flag(DELAY_SLOT_CONDITIONAL | ((~env->sr) & SR_T));
RETURN();
}
void OPPROTO op_bt_s(void)
{
- T2 = env->sr;
env->delayed_pc = PARAM1;
- set_flag(DELAY_SLOT_CONDITIONAL);
+ set_flag(DELAY_SLOT_CONDITIONAL | (env->sr & SR_T));
RETURN();
}
@@ -888,9 +886,12 @@ void OPPROTO op_jT(void)
RETURN();
}
-void OPPROTO op_jTT2(void)
+void OPPROTO op_jdelayed(void)
{
- if (T2 & SR_T)
+ uint32_t flags;
+ flags = env->flags;
+ env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
+ if (flags & DELAY_SLOT)
GOTO_LABEL_PARAM(1);
RETURN();
}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 0dca45ee9c..358f975e0c 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -124,7 +124,11 @@ void cpu_dump_state(CPUState * env, FILE * f,
void cpu_sh4_reset(CPUSH4State * env)
{
+#if defined(CONFIG_USER_ONLY)
+ env->sr = 0x00000000;
+#else
env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
+#endif
env->vbr = 0;
env->pc = 0xA0000000;
env->fpscr = 0x00040001;
@@ -209,10 +213,10 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
int l1;
l1 = gen_new_label();
- gen_op_jTT2(l1);
- gen_goto_tb(ctx, 0, ctx->pc);
+ gen_op_jdelayed(l1);
+ gen_goto_tb(ctx, 1, ctx->pc);
gen_set_label(l1);
- gen_goto_tb(ctx, 1, ctx->delayed_pc);
+ gen_jump(ctx);
}
#define B3_0 (ctx->opcode & 0xf)
@@ -1160,25 +1164,15 @@ int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
#endif
}
- switch (old_flags & (DELAY_SLOT_CONDITIONAL | DELAY_SLOT)) {
- case DELAY_SLOT_CONDITIONAL:
- gen_op_clr_delay_slot_conditional();
+ if (old_flags & DELAY_SLOT_CONDITIONAL) {
gen_delayed_conditional_jump(&ctx);
- break;
- case DELAY_SLOT:
+ } else if (old_flags & DELAY_SLOT) {
gen_op_clr_delay_slot();
gen_jump(&ctx);
- break;
- case 0:
- if (ctx.flags & BRANCH_EXCEPTION) {
- gen_jump_exception(&ctx);
- } else if ((ctx.flags & (BRANCH | BRANCH_CONDITIONAL)) == 0) {
- gen_goto_tb(&ctx, 0, ctx.pc);
- }
- break;
- default:
- /* Both cannot be set at the same time */
- assert(0);
+ } else if (ctx.flags & BRANCH_EXCEPTION) {
+ gen_jump_exception(&ctx);
+ } else if ((ctx.flags & (BRANCH | BRANCH_CONDITIONAL)) == 0) {
+ gen_goto_tb(&ctx, 0, ctx.pc);
}
if (env->singlestep_enabled) {