aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-25 16:16:50 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-25 16:16:50 +0000
commitea041c0e3375801694610250a8cc3e1240e2ad87 (patch)
treed26a3de41befc816f5d25a45e599d10c4daabb86 /exec.c
parent83479e770d31e171232a82f4eee7dab06d3b219c (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.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/exec.c b/exec.c
index 636fe25b80..4de0c60f1a 100644
--- a/exec.c
+++ b/exec.c
@@ -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;