diff options
Diffstat (limited to 'target-sh4')
-rw-r--r-- | target-sh4/cpu.h | 3 | ||||
-rw-r--r-- | target-sh4/helper.h | 2 | ||||
-rw-r--r-- | target-sh4/op_helper.c | 12 | ||||
-rw-r--r-- | target-sh4/translate.c | 30 |
4 files changed, 42 insertions, 5 deletions
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 23ecded55f..02ee24198b 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -279,7 +279,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, *flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME)) /* Bits 0- 3 */ | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */ - | (env->sr & (SR_MD | SR_RB)); /* Bits 29-30 */ + | (env->sr & (SR_MD | SR_RB)) /* Bits 29-30 */ + | (env->sr & SR_FD); /* Bit 15 */ } #endif /* _CPU_SH4_H */ diff --git a/target-sh4/helper.h b/target-sh4/helper.h index e8fd050efe..631e7e1968 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -3,6 +3,8 @@ DEF_HELPER_0(ldtlb, void) DEF_HELPER_0(raise_illegal_instruction, void) DEF_HELPER_0(raise_slot_illegal_instruction, void) +DEF_HELPER_0(raise_fpu_disable, void) +DEF_HELPER_0(raise_slot_fpu_disable, void) DEF_HELPER_0(debug, void) DEF_HELPER_1(sleep, void, i32) DEF_HELPER_1(trapa, void, i32) diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index f3e73004a7..63522194f7 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -89,6 +89,18 @@ void helper_raise_slot_illegal_instruction(void) cpu_loop_exit(); } +void helper_raise_fpu_disable(void) +{ + env->exception_index = 0x800; + cpu_loop_exit(); +} + +void helper_raise_slot_fpu_disable(void) +{ + env->exception_index = 0x820; + cpu_loop_exit(); +} + void helper_debug(void) { env->exception_index = EXCP_DEBUG; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 505b19690f..50b82e080c 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -447,17 +447,35 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */ #define CHECK_NOT_DELAY_SLOT \ - if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ - {gen_helper_raise_slot_illegal_instruction(); ctx->bstate = BS_EXCP; \ - return;} + if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ + { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \ + gen_helper_raise_slot_illegal_instruction(); \ + ctx->bstate = BS_EXCP; \ + return; \ + } #define CHECK_PRIVILEGED \ if (IS_USER(ctx)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ gen_helper_raise_illegal_instruction(); \ ctx->bstate = BS_EXCP; \ return; \ } +#define CHECK_FPU_ENABLED \ + if (ctx->flags & SR_FD) { \ + if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \ + gen_helper_raise_slot_fpu_disable(); \ + } else { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ + gen_helper_raise_fpu_disable(); \ + } \ + ctx->bstate = BS_EXCP; \ + return; \ + } + static void _decode_opc(DisasContext * ctx) { #if 0 @@ -1454,12 +1472,14 @@ static void _decode_opc(DisasContext * ctx) LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) - LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {}) + LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) case 0x406a: /* lds Rm,FPSCR */ + CHECK_FPU_ENABLED gen_helper_ld_fpscr(REG(B11_8)); ctx->bstate = BS_STOP; return; case 0x4066: /* lds.l @Rm+,FPSCR */ + CHECK_FPU_ENABLED { TCGv addr = tcg_temp_new(); tcg_gen_qemu_ld32s(addr, REG(B11_8), ctx->memidx); @@ -1470,9 +1490,11 @@ static void _decode_opc(DisasContext * ctx) } return; case 0x006a: /* sts FPSCR,Rn */ + CHECK_FPU_ENABLED tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); return; case 0x4062: /* sts FPSCR,@-Rn */ + CHECK_FPU_ENABLED { TCGv addr, val; val = tcg_temp_new(); |