diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2012-09-16 13:12:21 +0200 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2012-09-21 19:53:16 +0200 |
commit | 1012740098d0307ce5d957ebbe9a7f020da7f574 (patch) | |
tree | f7be3fd3b6e8572b871bb6adf4e424b0b4bbe32c /target-sh4/translate.c | |
parent | ed22e6f30e7f8c723f9b1be30869b9c0368e3e4e (diff) | |
download | qemu-1012740098d0307ce5d957ebbe9a7f020da7f574.tar.gz qemu-1012740098d0307ce5d957ebbe9a7f020da7f574.tar.bz2 qemu-1012740098d0307ce5d957ebbe9a7f020da7f574.zip |
target-sh4: rework exceptions handling
Since commit fd4bab102 PC is restored in case of exception through code
retranslation. While it is clearly the thing to do in case it is not
not known if an helper is going to trigger an exception or not
(e.g. for load/store, FPU, etc.), it just make things slower when the
exception is already known at translation time.
Partially revert this commit and save PC in the TCG code. Set bstate to
BS_BRANCH to not generate TCG exit code. Micro-optimize the sleep
helper. Make all the exception helpers to call raise_exception and mark
it as noreturn.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-sh4/translate.c')
-rw-r--r-- | target-sh4/translate.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/target-sh4/translate.c b/target-sh4/translate.c index cdc4e3bc5f..6305db80f7 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -427,30 +427,33 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) #define CHECK_NOT_DELAY_SLOT \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ gen_helper_raise_slot_illegal_instruction(cpu_env); \ - ctx->bstate = BS_EXCP; \ + ctx->bstate = BS_BRANCH; \ return; \ } #define CHECK_PRIVILEGED \ if (IS_USER(ctx)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ gen_helper_raise_slot_illegal_instruction(cpu_env); \ } else { \ gen_helper_raise_illegal_instruction(cpu_env); \ } \ - ctx->bstate = BS_EXCP; \ + ctx->bstate = BS_BRANCH; \ return; \ } #define CHECK_FPU_ENABLED \ if (ctx->flags & SR_FD) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ gen_helper_raise_slot_fpu_disable(cpu_env); \ } else { \ gen_helper_raise_fpu_disable(cpu_env); \ } \ - ctx->bstate = BS_EXCP; \ + ctx->bstate = BS_BRANCH; \ return; \ } @@ -541,7 +544,8 @@ static void _decode_opc(DisasContext * ctx) return; case 0x001b: /* sleep */ CHECK_PRIVILEGED - gen_helper_sleep(cpu_env, tcg_const_i32(ctx->pc + 2)); + tcg_gen_movi_i32(cpu_pc, ctx->pc + 2); + gen_helper_sleep(cpu_env); return; } @@ -1411,6 +1415,7 @@ static void _decode_opc(DisasContext * ctx) { TCGv imm; CHECK_NOT_DELAY_SLOT + tcg_gen_movi_i32(cpu_pc, ctx->pc); imm = tcg_const_i32(B7_0); gen_helper_trapa(cpu_env, imm); tcg_temp_free(imm); @@ -1909,12 +1914,13 @@ static void _decode_opc(DisasContext * ctx) ctx->opcode, ctx->pc); fflush(stderr); #endif + tcg_gen_movi_i32(cpu_pc, ctx->pc); if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { gen_helper_raise_slot_illegal_instruction(cpu_env); } else { gen_helper_raise_illegal_instruction(cpu_env); } - ctx->bstate = BS_EXCP; + ctx->bstate = BS_BRANCH; } static void decode_opc(DisasContext * ctx) @@ -1992,7 +1998,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, /* We have hit a breakpoint - make sure PC is up-to-date */ tcg_gen_movi_i32(cpu_pc, ctx.pc); gen_helper_debug(cpu_env); - ctx.bstate = BS_EXCP; + ctx.bstate = BS_BRANCH; break; } } |