aboutsummaryrefslogtreecommitdiff
path: root/exec-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'exec-i386.c')
-rw-r--r--exec-i386.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/exec-i386.c b/exec-i386.c
index 7575123ec5..978b1da9d8 100644
--- a/exec-i386.c
+++ b/exec-i386.c
@@ -120,7 +120,7 @@ int cpu_x86_exec(CPUX86State *env1)
TranslationBlock *tb, **ptb;
uint8_t *tc_ptr, *cs_base, *pc;
unsigned int flags;
-
+
/* first we save global registers */
saved_T0 = T0;
saved_T1 = T1;
@@ -169,6 +169,7 @@ int cpu_x86_exec(CPUX86State *env1)
/* prepare setjmp context for exception handling */
if (setjmp(env->jmp_env) == 0) {
+ T0 = 0; /* force lookup of first TB */
for(;;) {
if (env->interrupt_request) {
raise_exception(EXCP_INTERRUPT);
@@ -209,30 +210,40 @@ int cpu_x86_exec(CPUX86State *env1)
flags |= (env->eflags & TF_MASK) << (GEN_FLAG_TF_SHIFT - 8);
cs_base = env->seg_cache[R_CS].base;
pc = cs_base + env->eip;
+ spin_lock(&tb_lock);
tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
flags);
if (!tb) {
/* if no translated code available, then translate it now */
- /* very inefficient but safe: we lock all the cpus
- when generating code */
- spin_lock(&tb_lock);
+ tb = tb_alloc((unsigned long)pc);
+ if (!tb) {
+ /* flush must be done */
+ tb_flush();
+ /* cannot fail at this point */
+ tb = tb_alloc((unsigned long)pc);
+ /* don't forget to invalidate previous TB info */
+ ptb = &tb_hash[tb_hash_func((unsigned long)pc)];
+ T0 = 0;
+ }
tc_ptr = code_gen_ptr;
+ tb->tc_ptr = tc_ptr;
ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
&code_gen_size, pc, cs_base, flags,
- &code_size);
+ &code_size, tb);
/* if invalid instruction, signal it */
if (ret != 0) {
+ /* NOTE: the tb is allocated but not linked, so we
+ can leave it */
spin_unlock(&tb_lock);
raise_exception(EXCP06_ILLOP);
}
- tb = tb_alloc((unsigned long)pc, code_size);
*ptb = tb;
+ tb->size = code_size;
tb->cs_base = (unsigned long)cs_base;
tb->flags = flags;
- tb->tc_ptr = tc_ptr;
tb->hash_next = NULL;
+ tb_link(tb);
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
- spin_unlock(&tb_lock);
}
#ifdef DEBUG_EXEC
if (loglevel) {
@@ -241,14 +252,21 @@ int cpu_x86_exec(CPUX86State *env1)
lookup_symbol((void *)tb->pc));
}
#endif
- /* execute the generated code */
+
+ /* see if we can patch the calling TB */
+ if (T0 != 0 && !(env->eflags & TF_MASK)) {
+ tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
+ }
tc_ptr = tb->tc_ptr;
+ spin_unlock(&tb_lock);
+
+ /* execute the generated code */
gen_func = (void *)tc_ptr;
#ifdef __sparc__
__asm__ __volatile__("call %0\n\t"
" mov %%o7,%%i0"
: /* no outputs */
- : "r" (gen_func)
+ : "r" (gen_func)
: "i0", "i1", "i2", "i3", "i4", "i5");
#else
gen_func();