@@ -70,7 +70,7 @@ void superh_cpu_do_interrupt(CPUState *cs)
do_irq = do_irq && (cs->exception_index == -1);
if (env->sr & (1u << SR_BL)) {
- if (do_exp && cs->exception_index != 0x1e0) {
+ if (do_exp && cs->exception_index != SH4_EXCP_USER_BREAK) {
/* In theory a masked exception generates a reset exception,
which in turn jumps to the reset vector. However this only
works when using a bootloader. When using a kernel and an
@@ -97,45 +97,57 @@ void superh_cpu_do_interrupt(CPUState *cs)
if (qemu_loglevel_mask(CPU_LOG_INT)) {
const char *expname;
switch (cs->exception_index) {
- case 0x0e0:
+ case SH4_EXCP_RESET:
+ expname = "reset";
+ break;
+ case SH4_EXCP_MANUAL_RESET:
+ expname = "manual_reset";
+ break;
+ case SH4_EXCP_ADDR_ERROR:
expname = "addr_error";
break;
- case 0x040:
+ case SH4_EXCP_TLB_MISS:
expname = "tlb_miss";
break;
- case 0x0a0:
+ case SH4_EXCP_TLB_MULTIPLE:
+ expname = "tlb_multiple";
+ break;
+ case SH4_EXCP_TLB_VIOLATION:
expname = "tlb_violation";
break;
- case 0x180:
+ case SH4_EXCP_ILLEGAL_INSTRUCTION:
expname = "illegal_instruction";
break;
- case 0x1a0:
+ case SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION:
expname = "slot_illegal_instruction";
break;
- case 0x800:
+ case SH4_EXCP_FPU_DISABLE:
expname = "fpu_disable";
break;
- case 0x820:
+ case SH4_EXCP_SLOT_FPU_DISABLE:
expname = "slot_fpu";
break;
- case 0x100:
+ case SH4_EXCP_DATA_WRITE:
expname = "data_write";
break;
- case 0x060:
+ case SH4_EXCP_DTLB_MISS_WRITE:
expname = "dtlb_miss_write";
break;
- case 0x0c0:
+ case SH4_EXCP_DTLB_VIOLATION_WRITE:
expname = "dtlb_violation_write";
break;
- case 0x120:
+ case SH4_EXCP_FPU:
expname = "fpu_exception";
break;
- case 0x080:
+ case SH4_EXCP_INITIAL_PAGE_WRITE:
expname = "initial_page_write";
break;
- case 0x160:
+ case SH4_EXCP_TRAPA:
expname = "trapa";
break;
+ case SH4_EXCP_USER_BREAK:
+ expname = "user_break";
+ break;
default:
expname = do_irq ? "interrupt" : "???";
break;
@@ -161,18 +173,18 @@ void superh_cpu_do_interrupt(CPUState *cs)
if (do_exp) {
env->expevt = cs->exception_index;
switch (cs->exception_index) {
- case 0x000:
- case 0x020:
- case 0x140:
+ case SH4_EXCP_RESET:
+ case SH4_EXCP_MANUAL_RESET:
+ case SH4_EXCP_TLB_MULTIPLE:
env->sr &= ~(1u << SR_FD);
env->sr |= 0xf << 4; /* IMASK */
env->pc = 0xa0000000;
break;
- case 0x040:
- case 0x060:
+ case SH4_EXCP_TLB_MISS:
+ case SH4_EXCP_DTLB_MISS_WRITE:
env->pc = env->vbr + 0x400;
break;
- case 0x160:
+ case SH4_EXCP_TRAPA:
env->spc += 2; /* special case for TRAPA */
/* fall through */
default:
@@ -632,7 +644,7 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr,
CPUState *cs = env_cpu(s);
/* Multiple TLB Exception */
- cs->exception_index = 0x140;
+ cs->exception_index = SH4_EXCP_TLB_MULTIPLE;
s->tea = addr;
break;
}
@@ -828,37 +840,27 @@ bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
switch (ret) {
case MMU_ITLB_MISS:
case MMU_DTLB_MISS_READ:
- cs->exception_index = 0x040;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_TLB_MISS, retaddr);
case MMU_DTLB_MULTIPLE:
case MMU_ITLB_MULTIPLE:
- cs->exception_index = 0x140;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_TLB_MULTIPLE, retaddr);
case MMU_ITLB_VIOLATION:
- cs->exception_index = 0x0a0;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_TLB_VIOLATION, retaddr);
case MMU_DTLB_MISS_WRITE:
- cs->exception_index = 0x060;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_DTLB_MISS_WRITE, retaddr);
case MMU_DTLB_INITIAL_WRITE:
- cs->exception_index = 0x080;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_INITIAL_PAGE_WRITE, retaddr);
case MMU_DTLB_VIOLATION_READ:
- cs->exception_index = 0x0a0;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_TLB_VIOLATION, retaddr);
case MMU_DTLB_VIOLATION_WRITE:
- cs->exception_index = 0x0c0;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_DTLB_VIOLATION_WRITE, retaddr);
case MMU_IADDR_ERROR:
case MMU_DADDR_ERROR_READ:
- cs->exception_index = 0x0e0;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_ADDR_ERROR, retaddr);
case MMU_DADDR_ERROR_WRITE:
- cs->exception_index = 0x100;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_DATA_WRITE, retaddr);
default:
cpu_abort(cs, "Unhandled MMU fault");
}
- cpu_loop_exit_restore(cs, retaddr);
}
#endif /* !CONFIG_USER_ONLY */
@@ -1,8 +1,4 @@
DEF_HELPER_1(ldtlb, void, env)
-DEF_HELPER_1(raise_illegal_instruction, noreturn, env)
-DEF_HELPER_1(raise_slot_illegal_instruction, noreturn, env)
-DEF_HELPER_1(raise_fpu_disable, noreturn, env)
-DEF_HELPER_1(raise_slot_fpu_disable, noreturn, env)
DEF_HELPER_1(sleep, noreturn, env)
DEF_HELPER_2(trapa, noreturn, env, i32)
DEF_HELPER_1(exclusive, noreturn, env)
@@ -33,15 +33,12 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
switch (access_type) {
case MMU_INST_FETCH:
case MMU_DATA_LOAD:
- cs->exception_index = 0x0e0;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_ADDR_ERROR, retaddr);
case MMU_DATA_STORE:
- cs->exception_index = 0x100;
- break;
+ cpu_loop_exit_excp(cs, SH4_EXCP_DATA_WRITE, retaddr);
default:
g_assert_not_reached();
}
- cpu_loop_exit_restore(cs, retaddr);
}
#endif
@@ -55,49 +52,19 @@ void helper_ldtlb(CPUSH4State *env)
#endif
}
-static inline G_NORETURN
-void raise_exception(CPUSH4State *env, int index,
- uintptr_t retaddr)
-{
- CPUState *cs = env_cpu(env);
-
- cs->exception_index = index;
- cpu_loop_exit_restore(cs, retaddr);
-}
-
-void helper_raise_illegal_instruction(CPUSH4State *env)
-{
- raise_exception(env, 0x180, 0);
-}
-
-void helper_raise_slot_illegal_instruction(CPUSH4State *env)
-{
- raise_exception(env, 0x1a0, 0);
-}
-
-void helper_raise_fpu_disable(CPUSH4State *env)
-{
- raise_exception(env, 0x800, 0);
-}
-
-void helper_raise_slot_fpu_disable(CPUSH4State *env)
-{
- raise_exception(env, 0x820, 0);
-}
-
void helper_sleep(CPUSH4State *env)
{
CPUState *cs = env_cpu(env);
cs->halted = 1;
env->in_sleep = 1;
- raise_exception(env, EXCP_HLT, 0);
+ cpu_loop_exit_excp(cs, EXCP_HLT, 0);
}
void helper_trapa(CPUSH4State *env, uint32_t tra)
{
env->tra = tra << 2;
- raise_exception(env, 0x160, 0);
+ cpu_loop_exit_excp(env_cpu(env), SH4_EXCP_TRAPA, 0);
}
void helper_exclusive(CPUSH4State *env)
@@ -255,7 +222,7 @@ static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
if (cause & enable) {
- raise_exception(env, 0x120, retaddr);
+ cpu_loop_exit_excp(env_cpu(env), SH4_EXCP_FPU, retaddr);
}
}
}
@@ -1756,10 +1756,13 @@ static void _decode_opc(DisasContext * ctx)
if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
do_illegal_slot:
gen_save_cpu_state(ctx, true);
- gen_helper_raise_slot_illegal_instruction(tcg_env);
+ gen_helper_raise_excp(tcg_env,
+ tcg_constant_i32(
+ SH4_EXCP_SLOT_ILLEGAL_INSTRUCTION));
} else {
gen_save_cpu_state(ctx, true);
- gen_helper_raise_illegal_instruction(tcg_env);
+ gen_helper_raise_excp(tcg_env,
+ tcg_constant_i32(SH4_EXCP_ILLEGAL_INSTRUCTION));
}
ctx->base.is_jmp = DISAS_NORETURN;
return;
@@ -1767,9 +1770,10 @@ static void _decode_opc(DisasContext * ctx)
do_fpu_disabled:
gen_save_cpu_state(ctx, true);
if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
- gen_helper_raise_slot_fpu_disable(tcg_env);
+ gen_helper_raise_excp(tcg_env,
+ tcg_constant_i32(SH4_EXCP_SLOT_FPU_DISABLE));
} else {
- gen_helper_raise_fpu_disable(tcg_env);
+ gen_helper_raise_excp(tcg_env, tcg_constant_i32(SH4_EXCP_FPU_DISABLE));
}
ctx->base.is_jmp = DISAS_NORETURN;
}
Translate illegal and FPU-disable through raise_excp. Drop unused raise_* TCG helpers and the one-line raise_exception wrapper. Keep leftover sleep, trapa, and exclusive helpers. Exit unaligned and tlb_fill through cpu_loop_exit_excp. Log reset, manual reset, TLB multiple, and user break. Signed-off-by: Yonggang Luo <luoyonggang@gmail.com> --- target/sh4/helper.c | 82 +++++++++++++++++++++--------------------- target/sh4/helper.h | 4 --- target/sh4/op_helper.c | 43 +++------------------- target/sh4/translate.c | 12 ++++--- 4 files changed, 55 insertions(+), 86 deletions(-)