diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-06-25 16:16:50 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-06-25 16:16:50 +0000 |
commit | ea041c0e3375801694610250a8cc3e1240e2ad87 (patch) | |
tree | d26a3de41befc816f5d25a45e599d10c4daabb86 /exec.c | |
parent | 83479e770d31e171232a82f4eee7dab06d3b219c (diff) |
more precise cpu_interrupt()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@276 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 67 |
1 files changed, 67 insertions, 0 deletions
@@ -26,7 +26,13 @@ #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; |