#include "qemu/atomic.h"
#include "sysemu/qtest.h"
-//#define CONFIG_DEBUG_EXEC
-
bool qemu_cpu_has_work(CPUState *cpu)
{
return cpu_has_work(cpu);
int cpu_exec(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
+#if !(defined(CONFIG_USER_ONLY) && \
+ (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+#endif
int ret, interrupt_request;
TranslationBlock *tb;
uint8_t *tc_ptr;
cpu_single_env = env;
+ /* As long as cpu_single_env is null, up to the assignment just above,
+ * requests by other threads to exit the execution loop are expected to
+ * be issued using the exit_request global. We must make sure that our
+ * evaluation of the global value is performed past the cpu_single_env
+ * value transition point, which requires a memory barrier as well as
+ * an instruction scheduling constraint on modern architectures. */
+ smp_mb();
+
if (unlikely(exit_request)) {
cpu->exit_request = 1;
}
#elif defined(TARGET_LM32)
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MOXIE)
#elif defined(TARGET_OPENRISC)
#elif defined(TARGET_SH4)
#elif defined(TARGET_CRIS)
which will be handled outside the cpu execution
loop */
#if defined(TARGET_I386)
- do_interrupt(env);
+ cc->do_interrupt(cpu);
#endif
ret = env->exception_index;
break;
#else
- do_interrupt(env);
+ cc->do_interrupt(cpu);
env->exception_index = -1;
#endif
}
if ((interrupt_request & CPU_INTERRUPT_HARD)
&& (env->ie & IE_IE)) {
env->exception_index = EXCP_IRQ;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_MICROBLAZE)
&& !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
&& !(env->iflags & (D_FLAG | IMM_FLAG))) {
env->exception_index = EXCP_IRQ;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_MIPS)
/* Raise it */
env->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_OPENRISC)
}
if (idx >= 0) {
env->exception_index = idx;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
}
cpu_pil_allowed(env, pil)) ||
type != TT_EXTINT) {
env->exception_index = env->interrupt_index;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
}
if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->uncached_cpsr & CPSR_F)) {
env->exception_index = EXCP_FIQ;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
/* ARMv7-M interrupt return works by loading a magic value
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
|| !(env->uncached_cpsr & CPSR_I))) {
env->exception_index = EXCP_IRQ;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_UNICORE32)
if (interrupt_request & CPU_INTERRUPT_HARD
&& !(env->uncached_asr & ASR_I)) {
env->exception_index = UC32_EXCP_INTR;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_SH4)
if (interrupt_request & CPU_INTERRUPT_HARD) {
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_ALPHA)
if (idx >= 0) {
env->exception_index = idx;
env->error_code = 0;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
}
&& (env->pregs[PR_CCS] & I_FLAG)
&& !env->locked_irq) {
env->exception_index = EXCP_IRQ;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
if (interrupt_request & CPU_INTERRUPT_NMI) {
}
if ((env->pregs[PR_CCS] & m_flag_archval)) {
env->exception_index = EXCP_NMI;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
}
#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(env->psw.mask & PSW_MASK_EXT)) {
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#elif defined(TARGET_XTENSA)
if (interrupt_request & CPU_INTERRUPT_HARD) {
env->exception_index = EXC_IRQ;
- do_interrupt(env);
+ cc->do_interrupt(cpu);
next_tb = 0;
}
#endif
env->exception_index = EXCP_INTERRUPT;
cpu_loop_exit(env);
}
-#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
+#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
/* restore flags in standard format */
#if defined(TARGET_I386)
- env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
- | (DF & DF_MASK);
log_cpu_state(env, CPU_DUMP_CCOP);
- env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_M68K)
cpu_m68k_flush_flags(env, env->cc_op);
env->cc_op = CC_OP_FLAGS;
log_cpu_state(env, 0);
#endif
}
-#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
+#endif /* DEBUG_DISAS */
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
tb = tb_find_fast(env);
/* Note: we do it here to avoid a gcc bug on Mac OS X when
next_tb = 0;
tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
}
-#ifdef CONFIG_DEBUG_EXEC
- qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
- tb->tc_ptr, tb->pc,
- lookup_symbol(tb->pc));
-#endif
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
+ qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",
+ tb->tc_ptr, tb->pc, lookup_symbol(tb->pc));
+ }
/* see if we can patch the calling TB. When the TB
spans two pages, we cannot safely do a direct
jump. */
| env->cc_dest | (env->cc_x << 4);
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MOXIE)
#elif defined(TARGET_OPENRISC)
#elif defined(TARGET_SH4)
#elif defined(TARGET_ALPHA)