]> git.proxmox.com Git - mirror_qemu.git/blobdiff - cpu-exec.c
target-arm: A64: Add saturating accumulate ops (USQADD/SUQADD)
[mirror_qemu.git] / cpu-exec.c
index c9e1a8208b2ebecfc8f9d8d33dd24f767a8bf29b..0914d3c85c5e48e337ade48483c293287faec399 100644 (file)
 #include "qemu/atomic.h"
 #include "sysemu/qtest.h"
 
-//#define CONFIG_DEBUG_EXEC
-
-bool qemu_cpu_has_work(CPUState *cpu)
-{
-    return cpu_has_work(cpu);
-}
-
-void cpu_loop_exit(CPUArchState *env)
+void cpu_loop_exit(CPUState *cpu)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->current_tb = NULL;
-    siglongjmp(env->jmp_env, 1);
+    siglongjmp(cpu->jmp_env, 1);
 }
 
 /* exit the current TB from a signal handler. The host registers are
    restored in a state compatible with the CPU emulator
  */
 #if defined(CONFIG_SOFTMMU)
-void cpu_resume_from_signal(CPUArchState *env, void *puc)
+void cpu_resume_from_signal(CPUState *cpu, void *puc)
 {
     /* XXX: restore cpu registers saved in host registers */
 
-    env->exception_index = -1;
-    siglongjmp(env->jmp_env, 1);
+    cpu->exception_index = -1;
+    siglongjmp(cpu->jmp_env, 1);
 }
 #endif
 
@@ -55,14 +46,38 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc)
 static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
 {
     CPUArchState *env = cpu->env_ptr;
-    tcg_target_ulong next_tb = tcg_qemu_tb_exec(env, tb_ptr);
+    uintptr_t next_tb;
+
+#if defined(DEBUG_DISAS)
+    if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
+#if defined(TARGET_I386)
+        log_cpu_state(cpu, CPU_DUMP_CCOP);
+#elif defined(TARGET_M68K)
+        /* ??? Should not modify env state for dumping.  */
+        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(cpu, 0);
+#else
+        log_cpu_state(cpu, 0);
+#endif
+    }
+#endif /* DEBUG_DISAS */
+
+    next_tb = tcg_qemu_tb_exec(env, tb_ptr);
     if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
         /* We didn't start executing this TB (eg because the instruction
          * counter hit zero); we must restore the guest PC to the address
          * of the start of the TB.
          */
+        CPUClass *cc = CPU_GET_CLASS(cpu);
         TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
-        cpu_pc_from_tb(env, tb);
+        if (cc->synchronize_from_tb) {
+            cc->synchronize_from_tb(cpu, tb);
+        } else {
+            assert(cc->set_pc);
+            cc->set_pc(cpu, tb->pc);
+        }
     }
     if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
         /* We were asked to stop executing TBs (probably a pending
@@ -86,7 +101,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
     if (max_cycles > CF_COUNT_MASK)
         max_cycles = CF_COUNT_MASK;
 
-    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
+    tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
                      max_cycles);
     cpu->current_tb = tb;
     /* execute the generated code */
@@ -101,6 +116,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
                                       target_ulong cs_base,
                                       uint64_t flags)
 {
+    CPUState *cpu = ENV_GET_CPU(env);
     TranslationBlock *tb, **ptb1;
     unsigned int h;
     tb_page_addr_t phys_pc, phys_page1;
@@ -138,7 +154,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
     }
  not_found:
    /* if no translated code available, then translate it now */
-    tb = tb_gen_code(env, pc, cs_base, flags, 0);
+    tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
 
  found:
     /* Move the last found TB to the head of the list */
@@ -148,12 +164,13 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
         tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
     }
     /* we add the TB in the virtual pc hash table */
-    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
+    cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
     return tb;
 }
 
 static inline TranslationBlock *tb_find_fast(CPUArchState *env)
 {
+    CPUState *cpu = ENV_GET_CPU(env);
     TranslationBlock *tb;
     target_ulong cs_base, pc;
     int flags;
@@ -162,7 +179,7 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env)
        always be the same before a given translated block
        is executed. */
     cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
-    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
+    tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                  tb->flags != flags)) {
         tb = tb_find_slow(env, pc, cs_base, flags);
@@ -179,10 +196,11 @@ void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
 
 static void cpu_handle_debug_exception(CPUArchState *env)
 {
+    CPUState *cpu = ENV_GET_CPU(env);
     CPUWatchpoint *wp;
 
-    if (!env->watchpoint_hit) {
-        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
+    if (!cpu->watchpoint_hit) {
+        QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
             wp->flags &= ~BP_WATCHPOINT_HIT;
         }
     }
@@ -198,10 +216,17 @@ volatile sig_atomic_t exit_request;
 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
+#ifdef TARGET_I386
+    X86CPU *x86_cpu = X86_CPU(cpu);
+#endif
     int ret, interrupt_request;
     TranslationBlock *tb;
     uint8_t *tc_ptr;
-    tcg_target_ulong next_tb;
+    uintptr_t next_tb;
 
     if (cpu->halted) {
         if (!cpu_has_work(cpu)) {
@@ -211,7 +236,15 @@ int cpu_exec(CPUArchState *env)
         cpu->halted = 0;
     }
 
-    cpu_single_env = env;
+    current_cpu = cpu;
+
+    /* As long as current_cpu 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 current_cpu
+     * 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;
@@ -220,7 +253,7 @@ int cpu_exec(CPUArchState *env)
 #if defined(TARGET_I386)
     /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    DF = 1 - (2 * ((env->eflags >> 10) & 1));
+    env->df = 1 - (2 * ((env->eflags >> 10) & 1));
     CC_OP = CC_OP_EFLAGS;
     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 #elif defined(TARGET_SPARC)
@@ -236,6 +269,7 @@ int cpu_exec(CPUArchState *env)
 #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)
@@ -245,16 +279,16 @@ int cpu_exec(CPUArchState *env)
 #else
 #error unsupported target CPU
 #endif
-    env->exception_index = -1;
+    cpu->exception_index = -1;
 
     /* prepare setjmp context for exception handling */
     for(;;) {
-        if (sigsetjmp(env->jmp_env, 0) == 0) {
+        if (sigsetjmp(cpu->jmp_env, 0) == 0) {
             /* if an exception is pending, we execute it here */
-            if (env->exception_index >= 0) {
-                if (env->exception_index >= EXCP_INTERRUPT) {
+            if (cpu->exception_index >= 0) {
+                if (cpu->exception_index >= EXCP_INTERRUPT) {
                     /* exit request from the cpu execution loop */
-                    ret = env->exception_index;
+                    ret = cpu->exception_index;
                     if (ret == EXCP_DEBUG) {
                         cpu_handle_debug_exception(env);
                     }
@@ -265,13 +299,13 @@ int cpu_exec(CPUArchState *env)
                        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;
+                    ret = cpu->exception_index;
                     break;
 #else
-                    do_interrupt(env);
-                    env->exception_index = -1;
+                    cc->do_interrupt(cpu);
+                    cpu->exception_index = -1;
 #endif
                 }
             }
@@ -280,14 +314,14 @@ int cpu_exec(CPUArchState *env)
             for(;;) {
                 interrupt_request = cpu->interrupt_request;
                 if (unlikely(interrupt_request)) {
-                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
+                    if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
                         /* Mask out external interrupts for this step. */
                         interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
                     }
                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
                         cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
-                        env->exception_index = EXCP_DEBUG;
-                        cpu_loop_exit(env);
+                        cpu->exception_index = EXCP_DEBUG;
+                        cpu_loop_exit(cpu);
                     }
 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
@@ -295,32 +329,32 @@ int cpu_exec(CPUArchState *env)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                         cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
                         cpu->halted = 1;
-                        env->exception_index = EXCP_HLT;
-                        cpu_loop_exit(env);
+                        cpu->exception_index = EXCP_HLT;
+                        cpu_loop_exit(cpu);
                     }
 #endif
 #if defined(TARGET_I386)
 #if !defined(CONFIG_USER_ONLY)
                     if (interrupt_request & CPU_INTERRUPT_POLL) {
                         cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
-                        apic_poll_irq(env->apic_state);
+                        apic_poll_irq(x86_cpu->apic_state);
                     }
 #endif
                     if (interrupt_request & CPU_INTERRUPT_INIT) {
                             cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
                                                           0);
-                            do_cpu_init(x86_env_get_cpu(env));
-                            env->exception_index = EXCP_HALTED;
-                            cpu_loop_exit(env);
+                            do_cpu_init(x86_cpu);
+                            cpu->exception_index = EXCP_HALTED;
+                            cpu_loop_exit(cpu);
                     } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
-                            do_cpu_sipi(x86_env_get_cpu(env));
+                            do_cpu_sipi(x86_cpu);
                     } else if (env->hflags2 & HF2_GIF_MASK) {
                         if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                             !(env->hflags & HF_SMM_MASK)) {
                             cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
                                                           0);
                             cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
-                            do_smm_enter(env);
+                            do_smm_enter(x86_cpu);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                    !(env->hflags2 & HF2_NMI_MASK)) {
@@ -357,7 +391,10 @@ int cpu_exec(CPUArchState *env)
                             /* FIXME: this should respect TPR */
                             cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
                                                           0);
-                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+                            intno = ldl_phys(cpu->as,
+                                             env->vm_vmcb
+                                             + offsetof(struct vmcb,
+                                                        control.int_vector));
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
                             cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
@@ -379,8 +416,8 @@ int cpu_exec(CPUArchState *env)
 #elif defined(TARGET_LM32)
                     if ((interrupt_request & CPU_INTERRUPT_HARD)
                         && (env->ie & IE_IE)) {
-                        env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cpu->exception_index = EXCP_IRQ;
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_MICROBLAZE)
@@ -388,17 +425,17 @@ int cpu_exec(CPUArchState *env)
                         && (env->sregs[SR_MSR] & MSR_IE)
                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
                         && !(env->iflags & (D_FLAG | IMM_FLAG))) {
-                        env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cpu->exception_index = EXCP_IRQ;
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_MIPS)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         cpu_mips_hw_interrupts_pending(env)) {
                         /* Raise it */
-                        env->exception_index = EXCP_EXT_INTERRUPT;
+                        cpu->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_OPENRISC)
@@ -413,8 +450,8 @@ int cpu_exec(CPUArchState *env)
                             idx = EXCP_TICK;
                         }
                         if (idx >= 0) {
-                            env->exception_index = idx;
-                            do_interrupt(env);
+                            cpu->exception_index = idx;
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -428,17 +465,17 @@ int cpu_exec(CPUArchState *env)
                             if (((type == TT_EXTINT) &&
                                   cpu_pil_allowed(env, pil)) ||
                                   type != TT_EXTINT) {
-                                env->exception_index = env->interrupt_index;
-                                do_interrupt(env);
+                                cpu->exception_index = env->interrupt_index;
+                                cc->do_interrupt(cpu);
                                 next_tb = 0;
                             }
                         }
                     }
 #elif defined(TARGET_ARM)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
-                        && !(env->uncached_cpsr & CPSR_F)) {
-                        env->exception_index = EXCP_FIQ;
-                        do_interrupt(env);
+                        && !(env->daif & PSTATE_F)) {
+                        cpu->exception_index = EXCP_FIQ;
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
                     /* ARMv7-M interrupt return works by loading a magic value
@@ -452,21 +489,21 @@ int cpu_exec(CPUArchState *env)
                        pc contains a magic address.  */
                     if (interrupt_request & CPU_INTERRUPT_HARD
                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
-                            || !(env->uncached_cpsr & CPSR_I))) {
-                        env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                            || !(env->daif & PSTATE_I))) {
+                        cpu->exception_index = EXCP_IRQ;
+                        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);
+                        cpu->exception_index = UC32_EXCP_INTR;
+                        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)
@@ -495,9 +532,9 @@ int cpu_exec(CPUArchState *env)
                             }
                         }
                         if (idx >= 0) {
-                            env->exception_index = idx;
+                            cpu->exception_index = idx;
                             env->error_code = 0;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -505,8 +542,8 @@ int cpu_exec(CPUArchState *env)
                     if (interrupt_request & CPU_INTERRUPT_HARD
                         && (env->pregs[PR_CCS] & I_FLAG)
                         && !env->locked_irq) {
-                        env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cpu->exception_index = EXCP_IRQ;
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
                     if (interrupt_request & CPU_INTERRUPT_NMI) {
@@ -517,8 +554,8 @@ int cpu_exec(CPUArchState *env)
                             m_flag_archval = M_FLAG_V32;
                         }
                         if ((env->pregs[PR_CCS] & m_flag_archval)) {
-                            env->exception_index = EXCP_NMI;
-                            do_interrupt(env);
+                            cpu->exception_index = EXCP_NMI;
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -531,20 +568,20 @@ int cpu_exec(CPUArchState *env)
                            hardware doesn't rely on this, so we
                            provide/save the vector when the interrupt is
                            first signalled.  */
-                        env->exception_index = env->pending_vector;
+                        cpu->exception_index = env->pending_vector;
                         do_interrupt_m68k_hardirq(env);
                         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);
+                        cpu->exception_index = EXC_IRQ;
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #endif
@@ -559,28 +596,9 @@ int cpu_exec(CPUArchState *env)
                 }
                 if (unlikely(cpu->exit_request)) {
                     cpu->exit_request = 0;
-                    env->exception_index = EXCP_INTERRUPT;
-                    cpu_loop_exit(env);
+                    cpu->exception_index = EXCP_INTERRUPT;
+                    cpu_loop_exit(cpu);
                 }
-#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 | 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;
-                    env->sr = (env->sr & 0xffe0)
-                              | env->cc_dest | (env->cc_x << 4);
-                    log_cpu_state(env, 0);
-#else
-                    log_cpu_state(env, 0);
-#endif
-                }
-#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
                 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
@@ -592,11 +610,10 @@ int cpu_exec(CPUArchState *env)
                     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. */
@@ -633,25 +650,25 @@ int cpu_exec(CPUArchState *env)
                         /* Instruction counter expired.  */
                         int insns_left;
                         tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
-                        insns_left = env->icount_decr.u32;
-                        if (env->icount_extra && insns_left >= 0) {
+                        insns_left = cpu->icount_decr.u32;
+                        if (cpu->icount_extra && insns_left >= 0) {
                             /* Refill decrementer and continue execution.  */
-                            env->icount_extra += insns_left;
-                            if (env->icount_extra > 0xffff) {
+                            cpu->icount_extra += insns_left;
+                            if (cpu->icount_extra > 0xffff) {
                                 insns_left = 0xffff;
                             } else {
-                                insns_left = env->icount_extra;
+                                insns_left = cpu->icount_extra;
                             }
-                            env->icount_extra -= insns_left;
-                            env->icount_decr.u16.low = insns_left;
+                            cpu->icount_extra -= insns_left;
+                            cpu->icount_decr.u16.low = insns_left;
                         } else {
                             if (insns_left > 0) {
                                 /* Execute remaining instructions.  */
                                 cpu_exec_nocache(env, insns_left, tb);
                             }
-                            env->exception_index = EXCP_INTERRUPT;
+                            cpu->exception_index = EXCP_INTERRUPT;
                             next_tb = 0;
-                            cpu_loop_exit(env);
+                            cpu_loop_exit(cpu);
                         }
                         break;
                     }
@@ -666,7 +683,15 @@ int cpu_exec(CPUArchState *env)
         } else {
             /* Reload env after longjmp - the compiler may have smashed all
              * local variables as longjmp is marked 'noreturn'. */
-            env = cpu_single_env;
+            cpu = current_cpu;
+            env = cpu->env_ptr;
+#if !(defined(CONFIG_USER_ONLY) && \
+      (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+            cc = CPU_GET_CLASS(cpu);
+#endif
+#ifdef TARGET_I386
+            x86_cpu = X86_CPU(cpu);
+#endif
         }
     } /* for(;;) */
 
@@ -674,7 +699,7 @@ int cpu_exec(CPUArchState *env)
 #if defined(TARGET_I386)
     /* restore flags in standard format */
     env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
-        | (DF & DF_MASK);
+        | (env->df & DF_MASK);
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_UNICORE32)
@@ -688,6 +713,7 @@ int cpu_exec(CPUArchState *env)
               | 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)
@@ -699,7 +725,7 @@ int cpu_exec(CPUArchState *env)
 #error unsupported target CPU
 #endif
 
-    /* fail safe : never use cpu_single_env outside cpu_exec() */
-    cpu_single_env = NULL;
+    /* fail safe : never use current_cpu outside cpu_exec() */
+    current_cpu = NULL;
     return ret;
 }