OSDN Git Service

more precise cpu_interrupt()
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 25 Jun 2003 16:16:50 +0000 (16:16 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 25 Jun 2003 16:16:50 +0000 (16:16 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@276 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-i386.h
exec.c

index abbb037..6c7afbf 100644 (file)
@@ -251,7 +251,7 @@ typedef struct CPUX86State {
     int error_code;
     int exception_is_int;
     int exception_next_eip;
-
+    struct TranslationBlock *current_tb; /* currently executing TB */
     uint32_t cr[5]; /* NOTE: cr1 is unused */
     uint32_t dr[8]; /* debug registers */
     int interrupt_request; /* if true, will exit from cpu_exec() ASAP */
@@ -259,7 +259,7 @@ typedef struct CPUX86State {
        request interrupt number */
     int hard_interrupt_request; 
     int user_mode_only; /* user mode only simulation */
-
+    
     /* user data */
     void *opaque;
 } CPUX86State;
@@ -295,7 +295,6 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
 
 /* MMU defines */
 void cpu_x86_init_mmu(CPUX86State *env);
-extern CPUX86State *global_env;
 extern int phys_ram_size;
 extern int phys_ram_fd;
 extern uint8_t *phys_ram_base;
diff --git a/exec.c b/exec.c
index 636fe25..4de0c60 100644 (file)
--- a/exec.c
+++ b/exec.c
 #include <inttypes.h>
 #include <sys/mman.h>
 
+#include "config.h"
+#ifdef TARGET_I386
 #include "cpu-i386.h"
+#endif
+#ifdef TARGET_ARM
+#include "cpu-arm.h"
+#endif
 #include "exec.h"
 
 //#define DEBUG_TB_INVALIDATE
@@ -564,6 +570,67 @@ TranslationBlock *tb_find_pc(unsigned long tc_ptr)
     return &tbs[m_max];
 }
 
+static void tb_reset_jump_recursive(TranslationBlock *tb);
+
+static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
+{
+    TranslationBlock *tb1, *tb_next, **ptb;
+    unsigned int n1;
+
+    tb1 = tb->jmp_next[n];
+    if (tb1 != NULL) {
+        /* find head of list */
+        for(;;) {
+            n1 = (long)tb1 & 3;
+            tb1 = (TranslationBlock *)((long)tb1 & ~3);
+            if (n1 == 2)
+                break;
+            tb1 = tb1->jmp_next[n1];
+        }
+        /* we are now sure now that tb jumps to tb1 */
+        tb_next = tb1;
+
+        /* remove tb from the jmp_first list */
+        ptb = &tb_next->jmp_first;
+        for(;;) {
+            tb1 = *ptb;
+            n1 = (long)tb1 & 3;
+            tb1 = (TranslationBlock *)((long)tb1 & ~3);
+            if (n1 == n && tb1 == tb)
+                break;
+            ptb = &tb1->jmp_next[n1];
+        }
+        *ptb = tb->jmp_next[n];
+        tb->jmp_next[n] = NULL;
+        
+        /* suppress the jump to next tb in generated code */
+        tb_reset_jump(tb, n);
+
+        /* suppress jumps in the tb on which we could have jump */
+        tb_reset_jump_recursive(tb_next);
+    }
+}
+
+static void tb_reset_jump_recursive(TranslationBlock *tb)
+{
+    tb_reset_jump_recursive2(tb, 0);
+    tb_reset_jump_recursive2(tb, 1);
+}
+
+void cpu_interrupt(CPUState *env)
+{
+    TranslationBlock *tb;
+
+    env->interrupt_request = 1;
+    /* if the cpu is currently executing code, we must unlink it and
+       all the potentially executing TB */
+    tb = env->current_tb;
+    if (tb) {
+        tb_reset_jump_recursive(tb);
+    }
+}
+
+
 void cpu_abort(CPUState *env, const char *fmt, ...)
 {
     va_list ap;