#include "disas.h"
#include "tcg.h"
#include "kvm.h"
+#include "qemu-barrier.h"
#if !defined(CONFIG_SOFTMMU)
#undef EAX
/* main execution loop */
+volatile sig_atomic_t exit_request;
+
int cpu_exec(CPUState *env1)
{
volatile host_reg_t saved_env_reg;
use it. */
QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
saved_env_reg = (host_reg_t) env;
- asm("");
+ barrier();
env = env1;
+ if (unlikely(exit_request)) {
+ env->exit_request = 1;
+ }
+
#if defined(TARGET_I386)
if (!kvm_enabled()) {
/* put eflags in CPU temporary format */
env->exception_index = EXCP_INTERRUPT;
cpu_loop_exit();
}
-#ifdef CONFIG_DEBUG_EXEC
+#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
/* restore flags in standard format */
#if defined(TARGET_I386)
env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
log_cpu_state(env, X86_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-#elif defined(TARGET_ARM)
- log_cpu_state(env, 0);
-#elif defined(TARGET_SPARC)
- log_cpu_state(env, 0);
-#elif defined(TARGET_PPC)
- log_cpu_state(env, 0);
#elif defined(TARGET_M68K)
cpu_m68k_flush_flags(env, env->cc_op);
env->cc_op = CC_OP_FLAGS;
env->sr = (env->sr & 0xffe0)
| env->cc_dest | (env->cc_x << 4);
log_cpu_state(env, 0);
-#elif defined(TARGET_MICROBLAZE)
- log_cpu_state(env, 0);
-#elif defined(TARGET_MIPS)
- log_cpu_state(env, 0);
-#elif defined(TARGET_SH4)
- log_cpu_state(env, 0);
-#elif defined(TARGET_ALPHA)
- log_cpu_state(env, 0);
-#elif defined(TARGET_CRIS)
- log_cpu_state(env, 0);
#else
-#error unsupported target CPU
+ log_cpu_state(env, 0);
#endif
}
-#endif
+#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
spin_lock(&tb_lock);
tb = tb_find_fast();
/* Note: we do it here to avoid a gcc bug on Mac OS X when
TB, but before it is linked into a potentially
infinite loop and becomes env->current_tb. Avoid
starting execution if there is a pending interrupt. */
- if (!unlikely (env->exit_request)) {
- env->current_tb = tb;
+ env->current_tb = tb;
+ barrier();
+ if (likely(!env->exit_request)) {
tc_ptr = tb->tc_ptr;
/* execute the generated code */
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
#define env cpu_single_env
#endif
next_tb = tcg_qemu_tb_exec(tc_ptr);
- env->current_tb = NULL;
if ((next_tb & 3) == 2) {
/* Instruction counter expired. */
int insns_left;
}
}
}
+ env->current_tb = NULL;
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
} /* for(;;) */
#endif
/* restore global registers */
- asm("");
+ barrier();
env = (void *) saved_env_reg;
/* fail safe : never use cpu_single_env outside cpu_exec() */
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
- int is_write;
+ uint16_t *pinsn;
+ int is_write = 0;
pc = uc->uc_mcontext.psw.addr;
- /* XXX: compute is_write */
- is_write = 0;
+
+ /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
+ of the normal 2 arguments. The 3rd argument contains the "int_code"
+ from the hardware which does in fact contain the is_write value.
+ The rt signal handler, as far as I can tell, does not give this value
+ at all. Not that we could get to it from here even if it were. */
+ /* ??? This is not even close to complete, since it ignores all
+ of the read-modify-write instructions. */
+ pinsn = (uint16_t *)pc;
+ switch (pinsn[0] >> 8) {
+ case 0x50: /* ST */
+ case 0x42: /* STC */
+ case 0x40: /* STH */
+ is_write = 1;
+ break;
+ case 0xc4: /* RIL format insns */
+ switch (pinsn[0] & 0xf) {
+ case 0xf: /* STRL */
+ case 0xb: /* STGRL */
+ case 0x7: /* STHRL */
+ is_write = 1;
+ }
+ break;
+ case 0xe3: /* RXY format insns */
+ switch (pinsn[2] & 0xff) {
+ case 0x50: /* STY */
+ case 0x24: /* STG */
+ case 0x72: /* STCY */
+ case 0x70: /* STHY */
+ case 0x8e: /* STPQ */
+ case 0x3f: /* STRVH */
+ case 0x3e: /* STRV */
+ case 0x2f: /* STRVG */
+ is_write = 1;
+ }
+ break;
+ }
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}