]> git.proxmox.com Git - qemu.git/commitdiff
target-sh4: rework exceptions handling
authorAurelien Jarno <aurelien@aurel32.net>
Sun, 16 Sep 2012 11:12:21 +0000 (13:12 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Fri, 21 Sep 2012 17:53:16 +0000 (19:53 +0200)
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>
target-sh4/helper.h
target-sh4/op_helper.c
target-sh4/translate.c

index a00b7dd1e731f126f34121283e83b455d9fd3971..6c1a47da9f70e77dec4455bd073835d04d6f45a4 100644 (file)
@@ -1,13 +1,13 @@
 #include "def-helper.h"
 
 DEF_HELPER_1(ldtlb, void, env)
-DEF_HELPER_1(raise_illegal_instruction, void, env)
-DEF_HELPER_1(raise_slot_illegal_instruction, void, env)
-DEF_HELPER_1(raise_fpu_disable, void, env)
-DEF_HELPER_1(raise_slot_fpu_disable, void, env)
-DEF_HELPER_1(debug, void, env)
-DEF_HELPER_2(sleep, void, env, i32)
-DEF_HELPER_2(trapa, void, env, i32)
+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(debug, noreturn, env)
+DEF_HELPER_1(sleep, noreturn, env)
+DEF_HELPER_2(trapa, noreturn, env, i32)
 
 DEF_HELPER_3(movcal, void, env, i32, i32)
 DEF_HELPER_1(discard_movcal_backup, void, env)
index 4f1f754680b2eea2d6b10fbd15509dbf6eea7711..60ec4cbc4d002eb5e79cc543dac6bae00386e8aa 100644 (file)
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "helper.h"
 
-static void cpu_restore_state_from_retaddr(CPUSH4State *env, uintptr_t retaddr)
+static inline void cpu_restore_state_from_retaddr(CPUSH4State *env,
+                                                  uintptr_t retaddr)
 {
     TranslationBlock *tb;
 
@@ -77,8 +78,8 @@ void helper_ldtlb(CPUSH4State *env)
 #endif
 }
 
-static inline void raise_exception(CPUSH4State *env, int index,
-                                   uintptr_t retaddr)
+static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index,
+                                                 uintptr_t retaddr)
 {
     env->exception_index = index;
     cpu_restore_state_from_retaddr(env, retaddr);
@@ -87,43 +88,40 @@ static inline void raise_exception(CPUSH4State *env, int index,
 
 void helper_raise_illegal_instruction(CPUSH4State *env)
 {
-    raise_exception(env, 0x180, GETPC());
+    raise_exception(env, 0x180, 0);
 }
 
 void helper_raise_slot_illegal_instruction(CPUSH4State *env)
 {
-    raise_exception(env, 0x1a0, GETPC());
+    raise_exception(env, 0x1a0, 0);
 }
 
 void helper_raise_fpu_disable(CPUSH4State *env)
 {
-    raise_exception(env, 0x800, GETPC());
+    raise_exception(env, 0x800, 0);
 }
 
 void helper_raise_slot_fpu_disable(CPUSH4State *env)
 {
-    raise_exception(env, 0x820, GETPC());
+    raise_exception(env, 0x820, 0);
 }
 
 void helper_debug(CPUSH4State *env)
 {
-    env->exception_index = EXCP_DEBUG;
-    cpu_loop_exit(env);
+    raise_exception(env, EXCP_DEBUG, 0);
 }
 
-void helper_sleep(CPUSH4State *env, uint32_t next_pc)
+void helper_sleep(CPUSH4State *env)
 {
     env->halted = 1;
     env->in_sleep = 1;
-    env->exception_index = EXCP_HLT;
-    env->pc = next_pc;
-    cpu_loop_exit(env);
+    raise_exception(env, EXCP_HLT, 0);
 }
 
 void helper_trapa(CPUSH4State *env, uint32_t tra)
 {
     env->tra = tra << 2;
-    raise_exception(env, 0x160, GETPC());
+    raise_exception(env, 0x160, 0);
 }
 
 void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value)
@@ -385,9 +383,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) {
-            cpu_restore_state_from_retaddr(env, retaddr);
-            env->exception_index = 0x120;
-            cpu_loop_exit(env);
+            raise_exception(env, 0x120, retaddr);
         }
     }
 }
index cdc4e3bc5f4cc03b083fda51b1815a6fc8450680..6305db80f7e5a947a418ce0305f7429c19f7f620 100644 (file)
@@ -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;
                }
            }