Index: /trunk/include/VBox/vmm/em.h
===================================================================
--- /trunk/include/VBox/vmm/em.h	(revision 40355)
+++ /trunk/include/VBox/vmm/em.h	(revision 40356)
@@ -176,5 +176,7 @@
 VMMDECL(int)            EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
 VMMDECL(int)            EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
-VMMDECL(bool)           EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(bool)      EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(int)       EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx);
+VMM_INT_DECL(int)       EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx);
 
 /** @name Assembly routines
Index: /trunk/src/VBox/VMM/Makefile.kmk
===================================================================
--- /trunk/src/VBox/VMM/Makefile.kmk	(revision 40355)
+++ /trunk/src/VBox/VMM/Makefile.kmk	(revision 40356)
@@ -32,4 +32,7 @@
 ifdef VBOX_WITH_RAW_MODE
  VMM_COMMON_DEFS += VBOX_WITH_RAW_MODE
+endif
+ifdef VBOX_WITH_IEM
+ VMM_COMMON_DEFS += VBOX_WITH_IEM
 endif
 ifdef VBOX_WITH_REM
Index: /trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 40355)
+++ /trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 40356)
@@ -2578,4 +2578,47 @@
 }
 
+
+/**
+ * Prepare an MWAIT - essentials of the MONITOR instruction.
+ *
+ * @returns VINF_SUCCESS
+ * @param   pVCpu               The current CPU.
+ * @param   rax                 The content of RAX.
+ * @param   rcx                 The content of RCX.
+ * @param   rdx                 The content of RDX.
+ */
+VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx)
+{
+    pVCpu->em.s.MWait.uMonitorRAX = rax;
+    pVCpu->em.s.MWait.uMonitorRCX = rcx;
+    pVCpu->em.s.MWait.uMonitorRDX = rdx;
+    pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE;
+    /** @todo Complete MONITOR implementation.  */
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Performs an MWAIT.
+ *
+ * @returns VINF_SUCCESS
+ * @param   pVCpu               The current CPU.
+ * @param   rax                 The content of RAX.
+ * @param   rcx                 The content of RCX.
+ */
+VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx)
+{
+    pVCpu->em.s.MWait.uMWaitRAX = rax;
+    pVCpu->em.s.MWait.uMWaitRCX = rcx;
+    pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_ACTIVE;
+    if (rcx)
+        pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_BREAKIRQIF0;
+    else
+        pVCpu->em.s.MWait.fWait &= ~EMMWAIT_FLAG_BREAKIRQIF0;
+    /** @todo not completely correct?? */
+    return VINF_EM_HALT;
+}
+
+
 /**
  * MONITOR Emulation.
@@ -2601,8 +2644,5 @@
         return VERR_EM_INTERPRETER; /* not supported */
 
-    pVCpu->em.s.mwait.uMonitorEAX = pRegFrame->rax;
-    pVCpu->em.s.mwait.uMonitorECX = pRegFrame->rcx;
-    pVCpu->em.s.mwait.uMonitorEDX = pRegFrame->rdx;
-    pVCpu->em.s.mwait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE;
+    EMMonitorWaitPrepare(pVCpu, pRegFrame->rax, pRegFrame->rcx, pRegFrame->rdx);
     return VINF_SUCCESS;
 }
@@ -2643,22 +2683,11 @@
     }
 
-    if (pRegFrame->ecx)
-    {
-        if (!(u32MWaitFeatures & X86_CPUID_MWAIT_ECX_BREAKIRQIF0))
-        {
-            Log(("EMInterpretMWait: unsupported X86_CPUID_MWAIT_ECX_BREAKIRQIF0 -> recompiler\n"));
-            return VERR_EM_INTERPRETER; /* illegal value. */
-        }
-
-        pVCpu->em.s.mwait.fWait = EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0;
-    }
-    else
-        pVCpu->em.s.mwait.fWait = EMMWAIT_FLAG_ACTIVE;
-
-    pVCpu->em.s.mwait.uMWaitEAX = pRegFrame->rax;
-    pVCpu->em.s.mwait.uMWaitECX = pRegFrame->rcx;
-
-    /** @todo not completely correct */
-    return VINF_EM_HALT;
+    if (pRegFrame->ecx && !(u32MWaitFeatures & X86_CPUID_MWAIT_ECX_BREAKIRQIF0))
+    {
+        Log(("EMInterpretMWait: unsupported X86_CPUID_MWAIT_ECX_BREAKIRQIF0 -> recompiler\n"));
+        return VERR_EM_INTERPRETER; /* illegal value. */
+    }
+
+    return EMMonitorWaitPerform(pVCpu, pRegFrame->rax, pRegFrame->rcx);
 }
 
@@ -3219,17 +3248,21 @@
 
 /**
- * Determine if we should continue after encountering a hlt or mwait instruction
+ * Determine if we should continue after encountering a hlt or mwait
+ * instruction.
+ *
+ * Clears MWAIT flags if returning @c true.
  *
  * @returns boolean
  * @param   pVCpu           The VMCPU to operate on.
- * @param   pCtx            Current CPU context
- */
-VMMDECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
-{
-    if (    pCtx->eflags.Bits.u1IF
-        ||  ((pVCpu->em.s.mwait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)))
-    {
-        pVCpu->em.s.mwait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
-        return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC));
+ * @param   pCtx            Current CPU context.
+ */
+VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
+{
+    if (   pCtx->eflags.Bits.u1IF
+        || (   (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
+            ==                            (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) )
+    {
+        pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
+        return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC));
     }
 
Index: /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 40355)
+++ /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 40356)
@@ -2355,5 +2355,5 @@
 
     case SVM_EXIT_HLT:
-        /** Check if external interrupts are pending; if so, don't switch back. */
+        /* Check if external interrupts are pending; if so, don't switch back. */
         STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitHlt);
         pCtx->rip++;    /* skip hlt */
@@ -2374,5 +2374,5 @@
             pCtx->rip += 3;     /* Note: hardcoded opcode size assumption! */
 
-            /** Check if external interrupts are pending; if so, don't switch back. */
+            /* Check if external interrupts are pending; if so, don't switch back. */
             if (    rc == VINF_SUCCESS
                 ||  (   rc == VINF_EM_HALT
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 40355)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 40356)
@@ -4111,5 +4111,5 @@
 
     case VMX_EXIT_HLT:                  /* 12 Guest software attempted to execute HLT. */
-        /** Check if external interrupts are pending; if so, don't switch back. */
+        /* Check if external interrupts are pending; if so, don't switch back. */
         STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitHlt);
         pCtx->rip++;    /* skip hlt */
@@ -4130,5 +4130,5 @@
             pCtx->rip += cbInstr;
 
-            /** Check if external interrupts are pending; if so, don't switch back. */
+            /* Check if external interrupts are pending; if so, don't switch back. */
             if (    rc == VINF_SUCCESS
                 ||  (   rc == VINF_EM_HALT
Index: /trunk/src/VBox/VMM/VMMR3/EM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 40355)
+++ /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 40356)
@@ -510,15 +510,15 @@
 
         /* Save mwait state. */
-        rc = SSMR3PutU32(pSSM, pVCpu->em.s.mwait.fWait);
+        rc = SSMR3PutU32(pSSM, pVCpu->em.s.MWait.fWait);
         AssertRCReturn(rc, rc);
-        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMWaitEAX);
+        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMWaitRAX);
         AssertRCReturn(rc, rc);
-        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMWaitECX);
+        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMWaitRCX);
         AssertRCReturn(rc, rc);
-        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorEAX);
+        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRAX);
         AssertRCReturn(rc, rc);
-        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorECX);
+        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRCX);
         AssertRCReturn(rc, rc);
-        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorEDX);
+        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRDX);
         AssertRCReturn(rc, rc);
     }
@@ -574,15 +574,15 @@
         {
             /* Load mwait state. */
-            rc = SSMR3GetU32(pSSM, &pVCpu->em.s.mwait.fWait);
+            rc = SSMR3GetU32(pSSM, &pVCpu->em.s.MWait.fWait);
             AssertRCReturn(rc, rc);
-            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMWaitEAX);
+            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMWaitRAX);
             AssertRCReturn(rc, rc);
-            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMWaitECX);
+            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMWaitRCX);
             AssertRCReturn(rc, rc);
-            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorEAX);
+            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRAX);
             AssertRCReturn(rc, rc);
-            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorECX);
+            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRCX);
             AssertRCReturn(rc, rc);
-            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorEDX);
+            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRDX);
             AssertRCReturn(rc, rc);
         }
@@ -1896,4 +1896,5 @@
              */
             Log2(("EMR3ExecuteVM: rc=%Rrc\n", rc));
+            EMSTATE const enmOldState = pVCpu->em.s.enmState;
             switch (rc)
             {
@@ -2104,4 +2105,25 @@
             }
 
+            /*
+             * Act on state transition.
+             */
+            EMSTATE const enmNewState = pVCpu->em.s.enmState;
+            if (enmOldState != enmNewState)
+            {
+                /* Clear MWait flags. */
+                if (   enmOldState == EMSTATE_HALTED
+                    && (pVCpu->em.s.MWait.fWait & EMMWAIT_FLAG_ACTIVE)
+                    && (   enmNewState == EMSTATE_RAW
+                        || enmNewState == EMSTATE_HWACC
+                        || enmNewState == EMSTATE_REM
+                        || enmNewState == EMSTATE_DEBUG_GUEST_RAW
+                        || enmNewState == EMSTATE_DEBUG_GUEST_HWACC
+                        || enmNewState == EMSTATE_DEBUG_GUEST_REM) )
+                {
+                    LogFlow(("EMR3ExecuteVM: Clearing MWAIT\n"));
+                    pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
+                }
+            }
+
             STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x); /* (skip this in release) */
             STAM_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
@@ -2159,9 +2181,16 @@
                 {
                     STAM_REL_PROFILE_START(&pVCpu->em.s.StatHalted, y);
-                    if (pVCpu->em.s.mwait.fWait & EMMWAIT_FLAG_ACTIVE)
+                    /* MWAIT has a special extension where it's woken up when
+                       an interrupt is pending even when IF=0. */
+                    if (   (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
+                        ==                            (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
                     {
-                        /* mwait has a special extension where it's woken up when an interrupt is pending even when IF=0. */
-                        rc = VMR3WaitHalted(pVM, pVCpu, !(pVCpu->em.s.mwait.fWait & EMMWAIT_FLAG_BREAKIRQIF0) && !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF));
-                        pVCpu->em.s.mwait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
+                        rc = VMR3WaitHalted(pVM, pVCpu, false /*fIgnoreInterrupts*/);
+                        if (   rc == VINF_SUCCESS
+                            && VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
+                        {
+                            Log(("EMR3ExecuteVM: Triggering reschedule on pending IRQ after MWAIT\n"));
+                            rc = VINF_EM_RESCHEDULE;
+                        }
                     }
                     else
@@ -2178,5 +2207,5 @@
                     TMR3NotifySuspend(pVM, pVCpu);
                     STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
-                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
+                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
                     return VINF_EM_SUSPEND;
 
@@ -2207,5 +2236,5 @@
                         pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
                         VMMR3FatalDump(pVM, pVCpu, rc);
-                        Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
+                        Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
                         return rc;
                     }
@@ -2225,5 +2254,5 @@
                     emR3Debug(pVM, pVCpu, rc);
                     STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
-                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
+                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
                     return rc;
                 }
@@ -2239,5 +2268,5 @@
                     TMR3NotifySuspend(pVM, pVCpu);
                     STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
-                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
+                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
                     return VERR_EM_INTERNAL_ERROR;
             }
Index: /trunk/src/VBox/VMM/VMMR3/EMRaw.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EMRaw.cpp	(revision 40355)
+++ /trunk/src/VBox/VMM/VMMR3/EMRaw.cpp	(revision 40356)
@@ -364,38 +364,4 @@
     }
 
-#if 0
-    /* Try our own instruction emulator before falling back to the recompiler. */
-    DISCPUSTATE Cpu;
-    rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "GEN EMU");
-    if (RT_SUCCESS(rc))
-    {
-        uint32_t size;
-
-        switch (Cpu.pCurInstr->opcode)
-        {
-        /* @todo we can do more now */
-        case OP_MOV:
-        case OP_AND:
-        case OP_OR:
-        case OP_XOR:
-        case OP_POP:
-        case OP_INC:
-        case OP_DEC:
-        case OP_XCHG:
-            STAM_PROFILE_START(&pVCpu->em.s.StatMiscEmu, a);
-            rc = EMInterpretInstructionCPU(pVM, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
-            if (RT_SUCCESS(rc))
-            {
-                pCtx->rip += Cpu.opsize;
-                STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
-                return rc;
-            }
-            if (rc != VERR_EM_INTERPRETER)
-                AssertMsgFailedReturn(("rc=%Rrc\n", rc), rc);
-            STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
-            break;
-        }
-    }
-#endif /* 0 */
     STAM_PROFILE_START(&pVCpu->em.s.StatREMEmu, a);
     Log(("EMINS: %04x:%RGv RSP=%RGv\n", pCtx->cs, (RTGCPTR)pCtx->rip, (RTGCPTR)pCtx->rsp));
Index: /trunk/src/VBox/VMM/include/EMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/EMInternal.h	(revision 40355)
+++ /trunk/src/VBox/VMM/include/EMInternal.h	(revision 40356)
@@ -44,13 +44,14 @@
 
 
-/**
- * MWait state flags.
- */
-/* MWait activated. */
+/** @name MWait state flags.
+ * @{
+ */
+/** MWait activated. */
 #define EMMWAIT_FLAG_ACTIVE             RT_BIT(0)
-/* MWait will continue when an interrupt is pending even when IF=0. */
+/** MWait will continue when an interrupt is pending even when IF=0. */
 #define EMMWAIT_FLAG_BREAKIRQIF0        RT_BIT(1)
-/* Monitor instruction was executed previously. */
+/** Monitor instruction was executed previously. */
 #define EMMWAIT_FLAG_MONITOR_ACTIVE     RT_BIT(2)
+/** @} */
 
 /** EM time slice in ms; used for capping execution time. */
@@ -333,5 +334,5 @@
     EMSTATE volatile        enmState;
 
-    /** Previous Execution Manager State. */
+    /** The state prior to the suspending of the VM. */
     EMSTATE                 enmPrevState;
 
@@ -364,15 +365,15 @@
     uint64_t                u64Alignment;
 
-    /* MWait halt state. */
+    /** MWait halt state. */
     struct
     {
-        uint32_t            fWait;          /* type of mwait; see EMMWAIT_FLAG_* */
-        uint32_t            a32Padding[1];
-        RTGCPTR             uMWaitEAX;      /* mwait hints */
-        RTGCPTR             uMWaitECX;      /* mwait extensions */
-        RTGCPTR             uMonitorEAX;    /* monitored address. */
-        RTGCPTR             uMonitorECX;    /* monitor extension. */
-        RTGCPTR             uMonitorEDX;    /* monitor hint. */
-    } mwait;
+        uint32_t            fWait;          /** Type of mwait; see EMMWAIT_FLAG_*. */
+        uint32_t            u32Padding;
+        RTGCPTR             uMWaitRAX;      /** MWAIT hints. */
+        RTGCPTR             uMWaitRCX;      /** MWAIT extensions. */
+        RTGCPTR             uMonitorRAX;    /** Monitored address. */
+        RTGCPTR             uMonitorRCX;    /** Monitor extension. */
+        RTGCPTR             uMonitorRDX;    /** Monitor hint. */
+    } MWait;
 
     union
