Index: /trunk/include/VBox/vmm/iem.h
===================================================================
--- /trunk/include/VBox/vmm/iem.h	(revision 36793)
+++ /trunk/include/VBox/vmm/iem.h	(revision 36794)
@@ -40,4 +40,12 @@
 VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu);
 
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+VMM_INT_DECL(void)   IEMNotifyMMIORead(PVM pVM, RTGCPHYS GCPhys, size_t cbValue);
+VMM_INT_DECL(void)   IEMNotifyMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
+VMM_INT_DECL(void)   IEMNotifyIOPortRead(PVM pVM, RTIOPORT Port, size_t cbValue);
+VMM_INT_DECL(void)   IEMNotifyIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
+VMM_INT_DECL(void)   IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue);
+VMM_INT_DECL(void)   IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue);
+#endif
 
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 36793)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 36794)
@@ -53,4 +53,5 @@
 #ifdef IEM_VERIFICATION_MODE
 # include <VBox/vmm/rem.h>
+# include <VBox/vmm/mm.h>
 #endif
 #include "IEMInternal.h"
@@ -187,4 +188,8 @@
 *   Defined Constants And Macros                                               *
 *******************************************************************************/
+/** Temporary hack to disable the double execution.  Will be removed in favor
+ * of a dedicated execution mode in EM. */
+//#define IEM_VERIFICATION_MODE_NO_REM
+
 /** Used to shut up GCC warnings about variables that 'may be used uninitialized'
  * due to GCC lacking knowledge about the value range of a switch. */
@@ -500,4 +505,9 @@
 static VBOXSTRICTRC     iemRaiseSelectorNotPresent(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess);
 static VBOXSTRICTRC     iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc);
+#if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM)
+static PIEMVERIFYEVTREC iemVerifyAllocRecord(PIEMCPU pIemCpu);
+static VBOXSTRICTRC     iemVerifyFakeIOPortRead(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
+static VBOXSTRICTRC     iemVerifyFakeIOPortWrite(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
+#endif
 
 
@@ -2078,5 +2088,5 @@
 static int iemMemPageMap(PIEMCPU pIemCpu, RTGCPHYS GCPhysMem, uint32_t fAccess, void **ppvMem)
 {
-#ifdef IEM_VERIFICATION_MODE
+#if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM)
     /* Force the alternative path so we can ignore writes. */
     if (fAccess & IEM_ACCESS_TYPE_WRITE)
@@ -2162,5 +2172,5 @@
      */
     int rc;
-#ifndef IEM_VERIFICATION_MODE /* No memory changes in verification mode. */
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM) /* No memory changes in verification mode. */
     if (!pIemCpu->aMemBbMappings[iMemMap].fUnassigned)
     {
@@ -2197,4 +2207,35 @@
         rc = VINF_SUCCESS;
 
+#if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM)
+    /*
+     * Record the write(s).
+     */
+    PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (pEvtRec)
+    {
+        pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_WRITE;
+        pEvtRec->u.RamWrite.GCPhys  = pIemCpu->aMemBbMappings[iMemMap].GCPhysFirst;
+        pEvtRec->u.RamWrite.cb      = pIemCpu->aMemBbMappings[iMemMap].cbFirst;
+        memcpy(pEvtRec->u.RamWrite.ab, &pIemCpu->aBounceBuffers[iMemMap].ab[0], pIemCpu->aMemBbMappings[iMemMap].cbFirst);
+        pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+        *pIemCpu->ppIemEvtRecNext = pEvtRec;
+    }
+    if (pIemCpu->aMemBbMappings[iMemMap].cbSecond)
+    {
+        pEvtRec = iemVerifyAllocRecord(pIemCpu);
+        if (pEvtRec)
+        {
+            pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_WRITE;
+            pEvtRec->u.RamWrite.GCPhys  = pIemCpu->aMemBbMappings[iMemMap].GCPhysSecond;
+            pEvtRec->u.RamWrite.cb      = pIemCpu->aMemBbMappings[iMemMap].cbSecond;
+            memcpy(pEvtRec->u.RamWrite.ab,
+                   &pIemCpu->aBounceBuffers[iMemMap].ab[pIemCpu->aMemBbMappings[iMemMap].cbFirst],
+                   pIemCpu->aMemBbMappings[iMemMap].cbSecond);
+            pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+            *pIemCpu->ppIemEvtRecNext = pEvtRec;
+        }
+    }
+#endif
+
     /*
      * Free the mapping entry.
@@ -2255,4 +2296,28 @@
                 return rc;
         }
+
+#if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM)
+        /*
+         * Record the reads.
+         */
+        PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu);
+        if (pEvtRec)
+        {
+            pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ;
+            pEvtRec->u.RamRead.GCPhys  = GCPhysFirst;
+            pEvtRec->u.RamRead.cb      = cbFirstPage;
+            pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+            *pIemCpu->ppIemEvtRecNext = pEvtRec;
+        }
+        pEvtRec = iemVerifyAllocRecord(pIemCpu);
+        if (pEvtRec)
+        {
+            pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ;
+            pEvtRec->u.RamRead.GCPhys  = GCPhysSecond;
+            pEvtRec->u.RamRead.cb      = cbSecondPage;
+            pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+            *pIemCpu->ppIemEvtRecNext = pEvtRec;
+        }
+#endif
     }
 #ifdef VBOX_STRICT
@@ -2318,4 +2383,19 @@
                 return rc;
         }
+
+#if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM)
+        /*
+         * Record the read.
+         */
+        PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu);
+        if (pEvtRec)
+        {
+            pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ;
+            pEvtRec->u.RamRead.GCPhys  = GCPhysFirst;
+            pEvtRec->u.RamRead.cb      = cbMem;
+            pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+            *pIemCpu->ppIemEvtRecNext = pEvtRec;
+        }
+#endif
     }
 #ifdef VBOX_STRICT
@@ -2362,5 +2442,5 @@
  *                              memory.
  * @param   cbMem               The number of bytes to map.  This is usually 1,
- *                              2, 4, 6, 8, 12 or 16.  When used by string
+ *                              2, 4, 6, 8, 12, 16 or 32.  When used by string
  *                              operations it can be up to a page.
  * @param   iSegReg             The index of the segment register to use for
@@ -2380,5 +2460,5 @@
      * Check the input and figure out which mapping entry to use.
      */
-    Assert(cbMem <= 16);
+    Assert(cbMem <= 32);
     Assert(~(fAccess & ~(IEM_ACCESS_TYPE_MASK | IEM_ACCESS_WHAT_MASK)));
 
@@ -3796,4 +3876,5 @@
      * Commit the flags.
      */
+    Assert(fEflNew & RT_BIT_32(1));
     pCtx->eflags.u = fEflNew;
     iemRegAddToRip(pIemCpu, cbInstr);
@@ -4357,5 +4438,5 @@
                        | X86_EFL_RF /*| X86_EFL_VM*/ | X86_EFL_AC /*|X86_EFL_VIF*/ /*|X86_EFL_VIP*/
                        | X86_EFL_ID;
-            uNewFlags |= pCtx->eflags.u & (X86_EFL_VM | X86_EFL_VIF | X86_EFL_VIP);
+            uNewFlags |= pCtx->eflags.u & (X86_EFL_VM | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_1);
         }
         else
@@ -4369,5 +4450,5 @@
             uNewFlags &= X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF
                        | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT;
-            uNewFlags |= pCtx->eflags.u & UINT16_C(0xffff0000);
+            uNewFlags |= pCtx->eflags.u & (UINT16_C(0xffff0000) | X86_EFL_1);
             /** @todo The intel pseudo code does not indicate what happens to
              *        reserved flags. We just ignore them. */
@@ -4413,4 +4494,5 @@
         pCtx->csHid.u64Base = (uint32_t)uNewCs << 4;
         /** @todo do we load attribs and limit as well? */
+        Assert(uNewFlags & X86_EFL_1);
         pCtx->eflags.u      = uNewFlags;
 
@@ -4492,5 +4574,7 @@
 
         *pSel = uSel;   /* Not RPL, remember :-) */
-        if (pIemCpu->enmCpuMode == IEMMODE_64BIT)
+        if (   pIemCpu->enmCpuMode == IEMMODE_64BIT
+            && iSegReg != X86_SREG_FS
+            && iSegReg != X86_SREG_GS)
         {
             /** @todo figure out what this actually does, it works. Needs
@@ -4634,4 +4718,44 @@
 
 /**
+ * Implements lgs, lfs, les, lds & lss.
+ */
+IEM_CIMPL_DEF_5(iemCImpl_load_SReg_Greg,
+                uint16_t, uSel,
+                uint64_t, offSeg,
+                uint8_t,  iSegReg,
+                uint8_t,  iGReg,
+                IEMMODE,  enmEffOpSize)
+{
+    PCPUMCTX        pCtx = pIemCpu->CTX_SUFF(pCtx);
+    VBOXSTRICTRC    rcStrict;
+
+    /*
+     * Use iemCImpl_LoadSReg to do the tricky segment register loading.
+     */
+    /** @todo verify and test that mov, pop and lXs works the segment
+     *        register loading in the exact same way. */
+    rcStrict = IEM_CIMPL_CALL_2(iemCImpl_LoadSReg, iSegReg, uSel);
+    if (rcStrict == VINF_SUCCESS)
+    {
+        switch (enmEffOpSize)
+        {
+            case IEMMODE_16BIT:
+                *(uint16_t *)iemGRegRef(pIemCpu, iGReg) = offSeg;
+                break;
+            case IEMMODE_32BIT:
+                *(uint64_t *)iemGRegRef(pIemCpu, iGReg) = offSeg;
+                break;
+            case IEMMODE_64BIT:
+                *(uint64_t *)iemGRegRef(pIemCpu, iGReg) = offSeg;
+                break;
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
+
+    return rcStrict;
+}
+
+
+/**
  * Implements 'pop SReg'.
  *
@@ -4710,5 +4834,5 @@
     if (rcStrict == VINF_SUCCESS)
     {
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
         rcStrict = CPUMSetGuestGDTR(IEMCPU_TO_VMCPU(pIemCpu), GCPtrBase, cbLimit);
 #else
@@ -4745,5 +4869,5 @@
     if (rcStrict == VINF_SUCCESS)
     {
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
         rcStrict = CPUMSetGuestIDTR(IEMCPU_TO_VMCPU(pIemCpu), GCPtrBase, cbLimit);
 #else
@@ -4781,5 +4905,5 @@
         case 4: crX = pCtx->cr4; break;
         case 8:
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             AssertFailedReturn(VERR_NOT_IMPLEMENTED); /** @todo implement CR8 reading and writing. */
 #else
@@ -4888,5 +5012,5 @@
              * Change CR0.
              */
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             rc = CPUMSetGuestCR0(pVCpu, NewCrX);
             AssertRCSuccessReturn(rc, RT_FAILURE_NP(rc) ? rc : VERR_INTERNAL_ERROR_3);
@@ -4908,5 +5032,5 @@
                     NewEFER &= ~MSR_K6_EFER_LME;
 
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
                 CPUMSetGuestEFER(pVCpu, NewEFER);
 #else
@@ -4916,5 +5040,5 @@
             }
 
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             /*
              * Inform PGM.
@@ -4978,5 +5102,5 @@
 
             /* Make the change. */
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             rc = CPUMSetGuestCR3(pVCpu, NewCrX);
             AssertRCSuccessReturn(rc, rc);
@@ -4985,5 +5109,5 @@
 #endif
 
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             /* Inform PGM. */
             if (pCtx->cr0 & X86_CR0_PG)
@@ -5037,5 +5161,5 @@
              * Change it.
              */
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             rc = CPUMSetGuestCR4(pVCpu, NewCrX);
             AssertRCSuccessReturn(rc, rc);
@@ -5048,5 +5172,5 @@
              * Notify SELM and PGM.
              */
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             /* SELM - VME may change things wrt to the TSS shadowing. */
             if ((NewCrX ^ OldCrX) & X86_CR4_VME)
@@ -5073,5 +5197,5 @@
          */
         case 8:
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             AssertFailedReturn(VERR_NOT_IMPLEMENTED); /** @todo implement CR8 reading and writing. */
 #else
@@ -5114,10 +5238,8 @@
      */
     uint32_t u32Value;
-#ifndef IEM_VERIFICATION_MODE
+#if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
     rcStrict = IOMIOPortRead(IEMCPU_TO_VM(pIemCpu), u16Port, &u32Value, cbReg);
 #else
-    u32Value = 0xffffffff;
-    rcStrict = VINF_SUCCESS;
-    pIemCpu->cIOReads++;
+    rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, cbReg);
 #endif
     if (IOM_SUCCESS(rcStrict))
@@ -5181,10 +5303,9 @@
         default: AssertFailedReturn(VERR_INTERNAL_ERROR_3);
     }
-#ifndef IEM_VERIFICATION_MODE
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
     VBOXSTRICTRC rc = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), u16Port, u32Value, cbReg);
-#else
-    VBOXSTRICTRC rc = VINF_SUCCESS;
-    pIemCpu->cIOWrites++;
-#endif
+# else
+    VBOXSTRICTRC rc = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, cbReg);
+# endif
     if (IOM_SUCCESS(rc))
     {
@@ -5369,5 +5490,6 @@
     uint32_t a_Name; \
     uint32_t *a_pName = &a_Name
-#define IEM_MC_COMMIT_EFLAGS(a_EFlags)                  (pIemCpu)->CTX_SUFF(pCtx)->eflags.u = (a_EFlags)
+#define IEM_MC_COMMIT_EFLAGS(a_EFlags) \
+   do { (pIemCpu)->CTX_SUFF(pCtx)->eflags.u = (a_EFlags); Assert((pIemCpu)->CTX_SUFF(pCtx)->eflags.u & X86_EFL_1); } while (0)
 
 #define IEM_MC_ASSIGN(a_VarOrArg, a_CVariableOrConst)   (a_VarOrArg) = (a_CVariableOrConst)
@@ -5565,4 +5687,17 @@
 
 /**
+ * Defers the rest of the instruction emulation to a C implementation routine
+ * and returns, taking two arguments in addition to the standard ones.
+ *
+ * @param   a_pfnCImpl      The pointer to the C routine.
+ * @param   a0              The first extra argument.
+ * @param   a1              The second extra argument.
+ * @param   a2              The third extra argument.
+ * @param   a3              The fourth extra argument.
+ * @param   a4              The fifth extra argument.
+ */
+#define IEM_MC_CALL_CIMPL_5(a_pfnCImpl, a0, a1, a2, a3, a4) return (a_pfnCImpl)(pIemCpu, pIemCpu->offOpcode, a0, a1, a2, a3, a4)
+
+/**
  * Defers the entire instruction emulation to a C implementation routine and
  * returns, only taking the standard parameters.
@@ -5629,4 +5764,5 @@
             && !(pIemCpu->CTX_SUFF(pCtx)->eflags.u & a_fBit)) {
 #define IEM_MC_IF_LOCAL_IS_Z(a_Local)                   if ((a_Local) == 0) {
+#define IEM_MC_IF_GREG_BIT_SET(a_iGReg, a_iBitNo)       if (*(uint64_t *)iemGRegRef(pIemCpu, (a_iGReg)) & RT_BIT_64(a_iBitNo)) {
 #define IEM_MC_ELSE()                                   } else {
 #define IEM_MC_ENDIF()                                  } do {} while (0)
@@ -5998,4 +6134,7 @@
 static void iemExecVerificationModeSetup(PIEMCPU pIemCpu)
 {
+    PCPUMCTX pOrgCtx = pIemCpu->CTX_SUFF(pCtx);
+
+# ifndef IEM_VERIFICATION_MODE_NO_REM
     /*
      * Switch state.
@@ -6003,7 +6142,7 @@
     static CPUMCTX  s_DebugCtx; /* Ugly! */
 
-    PCPUMCTX pOrgCtx = pIemCpu->CTX_SUFF(pCtx);
     s_DebugCtx = *pOrgCtx;
     pIemCpu->CTX_SUFF(pCtx) = &s_DebugCtx;
+# endif
 
     /*
@@ -6027,5 +6166,277 @@
     pIemCpu->fMulDivHack = false;
     pIemCpu->fShlHack    = false;
-}
+
+    /*
+     * Free all verification records.
+     */
+    PIEMVERIFYEVTREC pEvtRec = pIemCpu->pIemEvtRecHead;
+    pIemCpu->pIemEvtRecHead = NULL;
+    pIemCpu->ppIemEvtRecNext = &pIemCpu->pIemEvtRecHead;
+    do
+    {
+        while (pEvtRec)
+        {
+            PIEMVERIFYEVTREC pNext = pEvtRec->pNext;
+            pEvtRec->pNext = pIemCpu->pFreeEvtRec;
+            pIemCpu->pFreeEvtRec = pEvtRec;
+            pEvtRec = pNext;
+        }
+        pEvtRec = pIemCpu->pOtherEvtRecHead;
+        pIemCpu->pOtherEvtRecHead = NULL;
+        pIemCpu->ppOtherEvtRecNext = &pIemCpu->pOtherEvtRecHead;
+    } while (pEvtRec);
+}
+
+/**
+ * Allocate an event record.
+ * @returns Poitner to a record.
+ */
+static PIEMVERIFYEVTREC iemVerifyAllocRecord(PIEMCPU pIemCpu)
+{
+    PIEMVERIFYEVTREC pEvtRec = pIemCpu->pFreeEvtRec;
+    if (pEvtRec)
+        pIemCpu->pFreeEvtRec = pEvtRec->pNext;
+    else
+    {
+        if (!pIemCpu->ppIemEvtRecNext)
+            return NULL; /* Too early (fake PCIBIOS), ignore notification. */
+
+        pEvtRec = (PIEMVERIFYEVTREC)MMR3HeapAlloc(IEMCPU_TO_VM(pIemCpu), MM_TAG_EM /* lazy bird*/, sizeof(*pEvtRec));
+        if (!pEvtRec)
+            return NULL;
+    }
+    pEvtRec->enmEvent = IEMVERIFYEVENT_INVALID;
+    pEvtRec->pNext    = NULL;
+    return pEvtRec;
+}
+
+
+/**
+ * IOMMMIORead notification.
+ */
+VMM_INT_DECL(void)   IEMNotifyMMIORead(PVM pVM, RTGCPHYS GCPhys, size_t cbValue)
+{
+# ifndef IEM_VERIFICATION_MODE_NO_REM
+    PVMCPU              pVCpu = VMMGetCpu(pVM);
+    if (!pVCpu)
+        return;
+    PIEMCPU             pIemCpu = &pVCpu->iem.s;
+    PIEMVERIFYEVTREC    pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (!pEvtRec)
+        return;
+    pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_READ;
+    pEvtRec->u.RamRead.GCPhys  = GCPhys;
+    pEvtRec->u.RamRead.cb      = cbValue;
+    pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext;
+    *pIemCpu->ppOtherEvtRecNext = pEvtRec;
+# endif
+}
+
+
+/**
+ * IOMMMIOWrite notification.
+ */
+VMM_INT_DECL(void)   IEMNotifyMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
+{
+# ifndef IEM_VERIFICATION_MODE_NO_REM
+    PVMCPU              pVCpu = VMMGetCpu(pVM);
+    if (!pVCpu)
+        return;
+    PIEMCPU             pIemCpu = &pVCpu->iem.s;
+    PIEMVERIFYEVTREC    pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (!pEvtRec)
+        return;
+    pEvtRec->enmEvent = IEMVERIFYEVENT_RAM_WRITE;
+    pEvtRec->u.RamWrite.GCPhys   = GCPhys;
+    pEvtRec->u.RamWrite.cb       = cbValue;
+    pEvtRec->u.RamWrite.ab[0]    = RT_BYTE1(u32Value);
+    pEvtRec->u.RamWrite.ab[1]    = RT_BYTE2(u32Value);
+    pEvtRec->u.RamWrite.ab[2]    = RT_BYTE3(u32Value);
+    pEvtRec->u.RamWrite.ab[3]    = RT_BYTE4(u32Value);
+    pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext;
+    *pIemCpu->ppOtherEvtRecNext = pEvtRec;
+# endif
+}
+
+
+/**
+ * IOMIOPortRead notification.
+ */
+VMM_INT_DECL(void)   IEMNotifyIOPortRead(PVM pVM, RTIOPORT Port, size_t cbValue)
+{
+# ifndef IEM_VERIFICATION_MODE_NO_REM
+    PVMCPU              pVCpu = VMMGetCpu(pVM);
+    if (!pVCpu)
+        return;
+    PIEMCPU             pIemCpu = &pVCpu->iem.s;
+    PIEMVERIFYEVTREC    pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (!pEvtRec)
+        return;
+    pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_READ;
+    pEvtRec->u.IOPortRead.Port    = Port;
+    pEvtRec->u.IOPortRead.cbValue = cbValue;
+    pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext;
+    *pIemCpu->ppOtherEvtRecNext = pEvtRec;
+# endif
+}
+
+/**
+ * IOMIOPortWrite notification.
+ */
+VMM_INT_DECL(void)   IEMNotifyIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
+{
+# ifndef IEM_VERIFICATION_MODE_NO_REM
+    PVMCPU              pVCpu = VMMGetCpu(pVM);
+    if (!pVCpu)
+        return;
+    PIEMCPU             pIemCpu = &pVCpu->iem.s;
+    PIEMVERIFYEVTREC    pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (!pEvtRec)
+        return;
+    pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_WRITE;
+    pEvtRec->u.IOPortWrite.Port     = Port;
+    pEvtRec->u.IOPortWrite.cbValue  = cbValue;
+    pEvtRec->u.IOPortWrite.u32Value = u32Value;
+    pEvtRec->pNext = *pIemCpu->ppOtherEvtRecNext;
+    *pIemCpu->ppOtherEvtRecNext = pEvtRec;
+# endif
+}
+
+
+VMM_INT_DECL(void)   IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue)
+{
+    AssertFailed();
+}
+
+
+VMM_INT_DECL(void)   IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue)
+{
+    AssertFailed();
+}
+
+
+/**
+ * Fakes and records an I/O port read.
+ *
+ * @returns VINF_SUCCESS.
+ * @param   pIemCpu             The IEM per CPU data.
+ * @param   Port                The I/O port.
+ * @param   pu32Value           Where to store the fake value.
+ * @param   cbValue             The size of the access.
+ */
+static VBOXSTRICTRC iemVerifyFakeIOPortRead(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)
+{
+    PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (pEvtRec)
+    {
+        pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_READ;
+        pEvtRec->u.IOPortRead.Port    = Port;
+        pEvtRec->u.IOPortRead.cbValue = cbValue;
+        pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+        *pIemCpu->ppIemEvtRecNext = pEvtRec;
+    }
+    pIemCpu->cIOReads++;
+    *pu32Value = 0xffffffff;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Fakes and records an I/O port write.
+ *
+ * @returns VINF_SUCCESS.
+ * @param   pIemCpu             The IEM per CPU data.
+ * @param   Port                The I/O port.
+ * @param   u32Value            The value being written.
+ * @param   cbValue             The size of the access.
+ */
+static VBOXSTRICTRC iemVerifyFakeIOPortWrite(PIEMCPU pIemCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
+{
+    PIEMVERIFYEVTREC pEvtRec = iemVerifyAllocRecord(pIemCpu);
+    if (pEvtRec)
+    {
+        pEvtRec->enmEvent = IEMVERIFYEVENT_IOPORT_WRITE;
+        pEvtRec->u.IOPortWrite.Port     = Port;
+        pEvtRec->u.IOPortWrite.cbValue  = cbValue;
+        pEvtRec->u.IOPortWrite.u32Value = u32Value;
+        pEvtRec->pNext = *pIemCpu->ppIemEvtRecNext;
+        *pIemCpu->ppIemEvtRecNext = pEvtRec;
+    }
+    pIemCpu->cIOWrites++;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Used by iemVerifyAssertRecord and iemVerifyAssertRecords to add a record
+ * dump to the assertion info.
+ *
+ * @param   pEvtRec         The record to dump.
+ */
+static void iemVerifyAssertAddRecordDump(PIEMVERIFYEVTREC pEvtRec)
+{
+    switch (pEvtRec->enmEvent)
+    {
+        case IEMVERIFYEVENT_IOPORT_READ:
+            RTAssertMsg2Add("I/O PORT READ from %#6x, %d bytes\n",
+                            pEvtRec->u.IOPortWrite.Port,
+                            pEvtRec->u.IOPortWrite.cbValue);
+            break;
+        case IEMVERIFYEVENT_IOPORT_WRITE:
+            RTAssertMsg2Add("I/O PORT WRITE  to %#6x, %d bytes, value %#x\n",
+                            pEvtRec->u.IOPortWrite.Port,
+                            pEvtRec->u.IOPortWrite.cbValue,
+                            pEvtRec->u.IOPortWrite.u32Value);
+            break;
+        case IEMVERIFYEVENT_RAM_READ:
+            RTAssertMsg2Add("RAM READ  at %RGp, %#4zx bytes\n",
+                            pEvtRec->u.RamRead.GCPhys,
+                            pEvtRec->u.RamRead.cb);
+            break;
+        case IEMVERIFYEVENT_RAM_WRITE:
+            RTAssertMsg2Add("RAM WRITE at %RGp, %#4zx bytes: %.*RHxs\n",
+                            pEvtRec->u.RamWrite.GCPhys,
+                            pEvtRec->u.RamWrite.cb,
+                            (int)pEvtRec->u.RamWrite.cb,
+                            pEvtRec->u.RamWrite.ab);
+            break;
+        default:
+            AssertMsgFailed(("Invalid event type %d\n", pEvtRec->enmEvent));
+            break;
+    }
+}
+
+
+/**
+ * Raises an assertion on the specified record, showing the given message with
+ * a record dump attached.
+ *
+ * @param   pEvtRec1        The first record.
+ * @param   pEvtRec2        The second record.
+ * @param   pszMsg          The message explaining why we're asserting.
+ */
+static void iemVerifyAssertRecords(PIEMVERIFYEVTREC pEvtRec1, PIEMVERIFYEVTREC pEvtRec2, const char *pszMsg)
+{
+    RTAssertMsg1(pszMsg, __LINE__, __FILE__, __PRETTY_FUNCTION__);
+    iemVerifyAssertAddRecordDump(pEvtRec1);
+    iemVerifyAssertAddRecordDump(pEvtRec2);
+    RTAssertPanic();
+}
+
+
+/**
+ * Raises an assertion on the specified record, showing the given message with
+ * a record dump attached.
+ *
+ * @param   pEvtRec1        The first record.
+ * @param   pszMsg          The message explaining why we're asserting.
+ */
+static void iemVerifyAssertRecord(PIEMVERIFYEVTREC pEvtRec, const char *pszMsg)
+{
+    RTAssertMsg1(pszMsg, __LINE__, __FILE__, __PRETTY_FUNCTION__);
+    iemVerifyAssertAddRecordDump(pEvtRec);
+    RTAssertPanic();
+}
+
 
 /**
@@ -6034,4 +6445,8 @@
 static void iemExecVerificationModeCheck(PIEMCPU pIemCpu)
 {
+# if defined(IEM_VERIFICATION_MODE) && !defined(IEM_VERIFICATION_MODE_NO_REM)
+    /*
+     * Switch back the state.
+     */
     PCPUMCTX    pOrgCtx   = CPUMQueryGuestCtxPtr(IEMCPU_TO_VMCPU(pIemCpu));
     PCPUMCTX    pDebugCtx = pIemCpu->CTX_SUFF(pCtx);
@@ -6039,13 +6454,32 @@
     pIemCpu->CTX_SUFF(pCtx) = pOrgCtx;
 
+    /*
+     * Execute the instruction in REM.
+     */
     int rc = REMR3EmulateInstruction(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu));
     AssertRC(rc);
-
+#if 0
+    if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
+    {
+        while (    pOrgCtx->rip == pDebugCtx->rip - pIemCpu->offOpcode
+               &&  pOrgCtx->rcx != pDebugCtx->rcx
+               &&  pOrgCtx->rsi != pDebugCtx->rsi
+               &&  pOrgCtx->rdi != pDebugCtx->rdi)
+        {
+            rc = REMR3EmulateInstruction(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu));
+            AssertRC(rc);
+        }
+    }
+#endif
+
+    /*
+     * Compare the register states.
+     */
+    unsigned cDiffs = 0;
     if (memcmp(pOrgCtx, pDebugCtx, sizeof(*pDebugCtx)))
     {
         Log(("REM and IEM ends up with different registers!\n"));
-        unsigned cDiffs = 0;
-
-# define CHECK_FIELD(a_Field) \
+
+#  define CHECK_FIELD(a_Field) \
         do \
         { \
@@ -6064,5 +6498,5 @@
         } while (0)
 
-# define CHECK_BIT_FIELD(a_Field) \
+#  define CHECK_BIT_FIELD(a_Field) \
         do \
         { \
@@ -6087,5 +6521,5 @@
         uint32_t fFlagsMask = UINT32_MAX;
         if (pIemCpu->fMulDivHack)
-            fFlagsMask &= ~(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
+            fFlagsMask &= ~(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF);
         if (pIemCpu->fShlHack)
             fFlagsMask &= ~(X86_EFL_OF);
@@ -6094,5 +6528,5 @@
             RTAssertMsg2Weak("  rflags differs - iem=%08llx rem=%08llx\n", pDebugCtx->rflags.u, pOrgCtx->rflags.u);
             CHECK_BIT_FIELD(rflags.Bits.u1CF);
-            /*CHECK_BIT_FIELD(rflags.Bits.u1Reserved0); */ /** @todo why does REM set this? */
+            CHECK_BIT_FIELD(rflags.Bits.u1Reserved0);
             CHECK_BIT_FIELD(rflags.Bits.u1PF);
             CHECK_BIT_FIELD(rflags.Bits.u1Reserved1);
@@ -6190,7 +6624,81 @@
         if (cDiffs != 0)
             AssertFailed();
-# undef CHECK_FIELD
+#  undef CHECK_FIELD
+#  undef CHECK_BIT_FIELD
+    }
+
+    /*
+     * If the register state compared fine, check the verification event
+     * records.
+     */
+    if (cDiffs == 0)
+    {
+        /*
+         * Compare verficiation event records.
+         *  - I/O port accesses should be a 1:1 match.
+         */
+        PIEMVERIFYEVTREC pIemRec   = pIemCpu->pIemEvtRecHead;
+        PIEMVERIFYEVTREC pOtherRec = pIemCpu->pOtherEvtRecHead;
+        while (pIemRec && pOtherRec)
+        {
+            /* Since we might miss RAM writes and reads, ignore extra ones
+               made by IEM.  */
+            while (   IEMVERIFYEVENT_IS_RAM(pIemRec->enmEvent)
+                   && !IEMVERIFYEVENT_IS_RAM(pOtherRec->enmEvent)
+                   && pIemRec->pNext)
+                pIemRec = pIemRec->pNext;
+
+            /* Do the compare. */
+            if (pIemRec->enmEvent != pOtherRec->enmEvent)
+            {
+                iemVerifyAssertRecords(pIemRec, pOtherRec, "Type mismatches");
+                break;
+            }
+            bool fEquals;
+            switch (pIemRec->enmEvent)
+            {
+                case IEMVERIFYEVENT_IOPORT_READ:
+                    fEquals = pIemRec->u.IOPortRead.Port        == pOtherRec->u.IOPortRead.Port
+                           && pIemRec->u.IOPortRead.cbValue     == pOtherRec->u.IOPortRead.cbValue;
+                    break;
+                case IEMVERIFYEVENT_IOPORT_WRITE:
+                    fEquals = pIemRec->u.IOPortWrite.Port       == pOtherRec->u.IOPortWrite.Port
+                           && pIemRec->u.IOPortWrite.cbValue    == pOtherRec->u.IOPortWrite.cbValue
+                           && pIemRec->u.IOPortWrite.u32Value   == pOtherRec->u.IOPortWrite.u32Value;
+                    break;
+                case IEMVERIFYEVENT_RAM_READ:
+                    fEquals = pIemRec->u.RamRead.GCPhys         == pOtherRec->u.RamRead.GCPhys
+                           && pIemRec->u.RamRead.cb             == pOtherRec->u.RamRead.cb;
+                    break;
+                case IEMVERIFYEVENT_RAM_WRITE:
+                    fEquals = pIemRec->u.RamWrite.GCPhys        == pOtherRec->u.RamWrite.GCPhys
+                           && pIemRec->u.RamWrite.cb            == pOtherRec->u.RamWrite.cb
+                           && !memcmp(pIemRec->u.RamWrite.ab, pOtherRec->u.RamWrite.ab, pIemRec->u.RamWrite.cb);
+                    break;
+                default:
+                    fEquals = false;
+                    break;
+            }
+            if (!fEquals)
+            {
+                iemVerifyAssertRecords(pIemRec, pOtherRec, "Mismatch");
+                break;
+            }
+
+            /* advance */
+            pIemRec   = pIemRec->pNext;
+            pOtherRec = pOtherRec->pNext;
+        }
+
+        /* Ignore extra writes and reads. */
+        while (pIemRec && IEMVERIFYEVENT_IS_RAM(pIemRec->enmEvent))
+            pIemRec = pIemRec->pNext;
+        if (pIemRec != NULL)
+            iemVerifyAssertRecord(pIemRec, "Extra IEM record!");
+        else if (pOtherRec != NULL)
+            iemVerifyAssertRecord(pIemRec, "Extra Other record!");
     }
     pIemCpu->CTX_SUFF(pCtx) = pOrgCtx;
+# endif
 }
 
@@ -6261,4 +6769,5 @@
                 pIemCpu->cInstructions++;
         }
+        EMSetInhibitInterruptsPC(pVCpu, UINT64_C(0x7777555533331111));
     }
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 36793)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 36794)
@@ -297,4 +297,118 @@
 
 
+/**
+ * Implements 'REP LODS'.
+ */
+IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_lods_,OP_rAX,_m,ADDR_SIZE), int8_t, iEffSeg)
+{
+    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
+
+    /*
+     * Setup.
+     */
+    ADDR_TYPE       uCounterReg = pCtx->ADDR_rCX;
+    if (uCounterReg == 0)
+        return VINF_SUCCESS;
+
+    PCCPUMSELREGHID pSrcHid = iemSRegGetHid(pIemCpu, iEffSeg);
+    VBOXSTRICTRC rcStrict = iemMemSegCheckReadAccessEx(pIemCpu, pSrcHid, iEffSeg);
+    if (rcStrict != VINF_SUCCESS)
+        return rcStrict;
+
+    int8_t const    cbIncr      = pCtx->eflags.Bits.u1DF ? -(OP_SIZE / 8) : (OP_SIZE / 8);
+    OP_TYPE         uValueReg   = pCtx->OP_rAX;
+    ADDR_TYPE       uAddrReg    = pCtx->ADDR_rSI;
+
+    /*
+     * The loop.
+     */
+    do
+    {
+        /*
+         * Do segmentation and virtual page stuff.
+         */
+#if ADDR_SIZE != 64
+        ADDR2_TYPE  uVirtAddr = (uint32_t)pSrcHid->u64Base + uAddrReg;
+#else
+        uint64_t    uVirtAddr = uAddrReg;
+#endif
+        uint32_t    cLeftPage = (PAGE_SIZE - (uVirtAddr & PAGE_OFFSET_MASK)) / (OP_SIZE / 8);
+        if (cLeftPage > uCounterReg)
+            cLeftPage = uCounterReg;
+        if (   cLeftPage > 0 /* can be null if unaligned, do one fallback round. */
+            && cbIncr > 0    /** @todo Implement reverse direction string ops. */
+#if ADDR_SIZE != 64
+            && uAddrReg < pSrcHid->u32Limit
+            && uAddrReg + (cLeftPage * (OP_SIZE / 8)) <= pSrcHid->u32Limit
+#endif
+           )
+        {
+            RTGCPHYS GCPhysMem;
+            rcStrict = iemMemPageTranslateAndCheckAccess(pIemCpu, uVirtAddr, IEM_ACCESS_DATA_R, &GCPhysMem);
+            if (rcStrict != VINF_SUCCESS)
+                break;
+
+            /*
+             * If we can map the page without trouble, we can get away with
+             * just reading the last value on the page.
+             */
+            OP_TYPE const *puMem;
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem);
+            if (rcStrict == VINF_SUCCESS)
+            {
+                /* Only get the last byte, the rest doesn't matter in direct access mode. */
+                uValueReg = puMem[cLeftPage - 1];
+
+                /* Update the regs. */
+                uCounterReg -= cLeftPage;
+                uAddrReg    += cLeftPage * cbIncr;
+
+                /* If unaligned, we drop thru and do the page crossing access
+                   below. Otherwise, do the next page. */
+                if (!(uVirtAddr & (OP_SIZE - 1)))
+                    continue;
+                if (uCounterReg == 0)
+                    break;
+                cLeftPage = 0;
+            }
+        }
+
+        /*
+         * Fallback - slow processing till the end of the current page.
+         * In the cross page boundrary case we will end up here with cLeftPage
+         * as 0, we execute one loop then.
+         */
+        do
+        {
+            OP_TYPE uTmpValue;
+            rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uTmpValue, iEffSeg, uAddrReg);
+            if (rcStrict != VINF_SUCCESS)
+                break;
+            uValueReg = uTmpValue;
+            uAddrReg += cbIncr;
+            uCounterReg--;
+            cLeftPage--;
+        } while ((int32_t)cLeftPage > 0);
+        if (rcStrict != VINF_SUCCESS)
+            break;
+    } while (uCounterReg != 0);
+
+    /*
+     * Update the registers.
+     */
+    pCtx->ADDR_rCX = uCounterReg;
+    pCtx->ADDR_rDI = uAddrReg;
+#if OP_SIZE == 32
+    pCtx->rax     = uValueReg;
+#else
+    pCtx->OP_rAX  = uValueReg;
+#endif
+    if (rcStrict == VINF_SUCCESS)
+        iemRegAddToRip(pIemCpu, cbInstr);
+
+    return rcStrict;
+}
+
+
 #if OP_SIZE != 64
 
@@ -323,5 +437,9 @@
 
     uint32_t        u32Value;
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
     rcStrict = IOMIOPortRead(pVM, pCtx->dx, &u32Value, OP_SIZE / 8);
+# else
+    iemVerifyFakeIOPortRead(pIemCpu, pCtx->dx, &u32Value, OP_SIZE / 8);
+# endif
     if (IOM_SUCCESS(rcStrict))
     {
@@ -344,4 +462,5 @@
     return rcStrict;
 }
+
 
 /**
@@ -417,5 +536,9 @@
                 {
                     uint32_t u32Value;
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
                     rcStrict = IOMIOPortRead(pVM, u16Port, &u32Value, OP_SIZE / 8);
+# else
+                    rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, OP_SIZE / 8);
+# endif
                     if (!IOM_SUCCESS(rcStrict))
                         break;
@@ -461,5 +584,9 @@
 
             uint32_t u32Value;
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             rcStrict = IOMIOPortRead(pVM, u16Port, &u32Value, OP_SIZE / 8);
+# else
+            rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, OP_SIZE / 8);
+# endif
             if (!IOM_SUCCESS(rcStrict))
                 break;
@@ -496,5 +623,5 @@
  * Implements 'OUTS' (no rep)
  */
-IEM_CIMPL_DEF_0(RT_CONCAT4(iemCImpl_outs_op,OP_SIZE,_addr,ADDR_SIZE))
+IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg)
 {
     PVM             pVM  = IEMCPU_TO_VM(pIemCpu);
@@ -512,14 +639,18 @@
 
     OP_TYPE uValue;
-    rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, X86_SREG_ES, pCtx->ADDR_rDI);
+    rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, iEffSeg, pCtx->ADDR_rSI);
     if (rcStrict == VINF_SUCCESS)
     {
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
         rcStrict = IOMIOPortWrite(pVM, pCtx->dx, uValue, OP_SIZE / 8);
+# else
+        rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, pCtx->dx, uValue, OP_SIZE / 8);
+# endif
         if (IOM_SUCCESS(rcStrict))
         {
             if (!pCtx->eflags.Bits.u1DF)
-                pCtx->ADDR_rDI += OP_SIZE / 8;
+                pCtx->ADDR_rSI += OP_SIZE / 8;
             else
-                pCtx->ADDR_rDI -= OP_SIZE / 8;
+                pCtx->ADDR_rSI -= OP_SIZE / 8;
             iemRegAddToRip(pIemCpu, cbInstr);
             /** @todo massage IOM status codes. */
@@ -529,8 +660,9 @@
 }
 
+
 /**
  * Implements 'REP OUTS'.
  */
-IEM_CIMPL_DEF_0(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE))
+IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg)
 {
     PVM         pVM  = IEMCPU_TO_VM(pIemCpu);
@@ -549,10 +681,11 @@
         return VINF_SUCCESS;
 
-    rcStrict = iemMemSegCheckReadAccessEx(pIemCpu, &pCtx->esHid, X86_SREG_ES);
+    PCCPUMSELREGHID pHid = iemSRegGetHid(pIemCpu, iEffSeg);
+    rcStrict = iemMemSegCheckReadAccessEx(pIemCpu, pHid, iEffSeg);
     if (rcStrict != VINF_SUCCESS)
         return rcStrict;
 
     int8_t const    cbIncr      = pCtx->eflags.Bits.u1DF ? -(OP_SIZE / 8) : (OP_SIZE / 8);
-    ADDR_TYPE       uAddrReg    = pCtx->ADDR_rDI;
+    ADDR_TYPE       uAddrReg    = pCtx->ADDR_rSI;
 
     /*
@@ -565,5 +698,5 @@
          */
 #if ADDR_SIZE != 64
-        ADDR2_TYPE  uVirtAddr = (uint32_t)pCtx->esHid.u64Base + uAddrReg;
+        ADDR2_TYPE  uVirtAddr = (uint32_t)pHid->u64Base + uAddrReg;
 #else
         uint64_t    uVirtAddr = uAddrReg;
@@ -575,6 +708,6 @@
             && cbIncr > 0    /** @todo Implement reverse direction string ops. */
 #if ADDR_SIZE != 64
-            && uAddrReg < pCtx->esHid.u32Limit
-            && uAddrReg + (cLeftPage * (OP_SIZE / 8)) <= pCtx->esHid.u32Limit
+            && uAddrReg < pHid->u32Limit
+            && uAddrReg + (cLeftPage * (OP_SIZE / 8)) <= pHid->u32Limit
 #endif
            )
@@ -601,5 +734,9 @@
                 {
                     uint32_t u32Value = *puMem++;
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
                     rcStrict = IOMIOPortWrite(pVM, u16Port, u32Value, OP_SIZE / 8);
+# else
+                    rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, OP_SIZE / 8);
+# endif
                     if (!IOM_SUCCESS(rcStrict))
                         break;
@@ -639,9 +776,13 @@
         {
             OP_TYPE uValue;
-            rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, X86_SREG_ES, uAddrReg);
-            if (rcStrict != VINF_SUCCESS)
-                break;
-
+            rcStrict = RT_CONCAT(iemMemFetchDataU,OP_SIZE)(pIemCpu, &uValue, iEffSeg, uAddrReg);
+            if (rcStrict != VINF_SUCCESS)
+                break;
+
+# if !defined(IEM_VERIFICATION_MODE) || defined(IEM_VERIFICATION_MODE_NO_REM)
             rcStrict = IOMIOPortWrite(pVM, u16Port, uValue, OP_SIZE / 8);
+# else
+            rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, uValue, OP_SIZE / 8);
+# endif
             if (!IOM_SUCCESS(rcStrict))
                 break;
@@ -664,5 +805,5 @@
      */
     pCtx->ADDR_rCX = uCounterReg;
-    pCtx->ADDR_rDI = uAddrReg;
+    pCtx->ADDR_rSI = uAddrReg;
     if (rcStrict == VINF_SUCCESS)
         iemRegAddToRip(pIemCpu, cbInstr);
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 36793)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 36794)
@@ -1710,12 +1710,94 @@
 /** Opcode 0x0f 0xb1. */
 FNIEMOP_STUB(iemOp_cmpxchg_Ev_Gv);
+
+
+FNIEMOP_DEF_1(iemOpCommonLoadSRegAndGreg, uint8_t, iSegReg)
+{
+    uint8_t bRm; IEM_OPCODE_GET_NEXT_BYTE(pIemCpu, &bRm);
+    IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo should probably not be raised until we've fetched all the opcode bytes? */
+
+    /* The source cannot be a register. */
+    if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
+        return IEMOP_RAISE_INVALID_LOCK_PREFIX();
+    uint8_t const iGReg = ((bRm >> X86_MODRM_REG_SHIFT) & bRm & X86_MODRM_REG_SMASK) | pIemCpu->uRexReg;
+
+    switch (pIemCpu->enmEffOpSize)
+    {
+        case IEMMODE_16BIT:
+            IEM_MC_BEGIN(5, 1);
+            IEM_MC_ARG(uint16_t,        uSel,                                    0);
+            IEM_MC_ARG(uint16_t,        offSeg,                                  1);
+            IEM_MC_ARG_CONST(uint8_t,   iSegRegArg,/*=*/iSegReg,                 2);
+            IEM_MC_ARG_CONST(uint8_t,   iGRegArg,  /*=*/iGReg,                   3);
+            IEM_MC_ARG_CONST(IEMMODE,   enmEffOpSize,/*=*/pIemCpu->enmEffOpSize, 4);
+            IEM_MC_LOCAL(RTGCPTR,       GCPtrEff);
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm);
+            IEM_MC_FETCH_MEM_U16(offSeg, pIemCpu->iEffSeg, GCPtrEff);
+            IEM_MC_FETCH_MEM_U16(uSel,   pIemCpu->iEffSeg, GCPtrEff + 2);
+            IEM_MC_CALL_CIMPL_5(iemCImpl_load_SReg_Greg, uSel, offSeg, iSegRegArg, iGRegArg, enmEffOpSize);
+            IEM_MC_END();
+            return VINF_SUCCESS;
+
+        case IEMMODE_32BIT:
+            IEM_MC_BEGIN(5, 1);
+            IEM_MC_ARG(uint16_t,        uSel,                                    0);
+            IEM_MC_ARG(uint32_t,        offSeg,                                  1);
+            IEM_MC_ARG_CONST(uint8_t,   iSegRegArg,/*=*/iSegReg,                 2);
+            IEM_MC_ARG_CONST(uint8_t,   iGRegArg,  /*=*/iGReg,                   3);
+            IEM_MC_ARG_CONST(IEMMODE,   enmEffOpSize,/*=*/pIemCpu->enmEffOpSize, 4);
+            IEM_MC_LOCAL(RTGCPTR,       GCPtrEff);
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm);
+            IEM_MC_FETCH_MEM_U32(offSeg, pIemCpu->iEffSeg, GCPtrEff);
+            IEM_MC_FETCH_MEM_U16(uSel,   pIemCpu->iEffSeg, GCPtrEff + 4);
+            IEM_MC_CALL_CIMPL_5(iemCImpl_load_SReg_Greg, uSel, offSeg, iSegRegArg, iGRegArg, enmEffOpSize);
+            IEM_MC_END();
+            return VINF_SUCCESS;
+
+        case IEMMODE_64BIT:
+            IEM_MC_BEGIN(5, 1);
+            IEM_MC_ARG(uint16_t,        uSel,                                    0);
+            IEM_MC_ARG(uint64_t,        offSeg,                                  1);
+            IEM_MC_ARG_CONST(uint8_t,   iSegRegArg,/*=*/iSegReg,                 2);
+            IEM_MC_ARG_CONST(uint8_t,   iGRegArg,  /*=*/iGReg,                   3);
+            IEM_MC_ARG_CONST(IEMMODE,   enmEffOpSize,/*=*/pIemCpu->enmEffOpSize, 4);
+            IEM_MC_LOCAL(RTGCPTR,       GCPtrEff);
+            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEff, bRm);
+            IEM_MC_FETCH_MEM_U64(offSeg, pIemCpu->iEffSeg, GCPtrEff);
+            IEM_MC_FETCH_MEM_U16(uSel,   pIemCpu->iEffSeg, GCPtrEff + 8);
+            IEM_MC_CALL_CIMPL_5(iemCImpl_load_SReg_Greg, uSel, offSeg, iSegRegArg, iGRegArg, enmEffOpSize);
+            IEM_MC_END();
+            return VINF_SUCCESS;
+
+        IEM_NOT_REACHED_DEFAULT_CASE_RET();
+    }
+}
+
+
 /** Opcode 0x0f 0xb2. */
-FNIEMOP_STUB(iemOp_lss_Gv_Mp);
+FNIEMOP_DEF(iemOp_lss_Gv_Mp)
+{
+    IEMOP_MNEMONIC("lss Gv,Mp");
+    return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_SS);
+}
+
+
 /** Opcode 0x0f 0xb3. */
 FNIEMOP_STUB(iemOp_btr_Ev_Gv);
+
+
 /** Opcode 0x0f 0xb4. */
-FNIEMOP_STUB(iemOp_lfs_Gv_Mp);
+FNIEMOP_DEF(iemOp_lfs_Gv_Mp)
+{
+    IEMOP_MNEMONIC("lfs Gv,Mp");
+    return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_FS);
+}
+
+
 /** Opcode 0x0f 0xb5. */
-FNIEMOP_STUB(iemOp_lgs_Gv_Mp);
+FNIEMOP_DEF(iemOp_lgs_Gv_Mp)
+{
+    IEMOP_MNEMONIC("lgs Gv,Mp");
+    return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_GS);
+}
 
 
@@ -3817,7 +3899,7 @@
         switch (pIemCpu->enmEffAddrMode)
         {
-            case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op8_addr16);
-            case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op8_addr32);
-            case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op8_addr64);
+            case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op8_addr16, pIemCpu->iEffSeg);
+            case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op8_addr32, pIemCpu->iEffSeg);
+            case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op8_addr64, pIemCpu->iEffSeg);
             IEM_NOT_REACHED_DEFAULT_CASE_RET();
         }
@@ -3828,7 +3910,7 @@
         switch (pIemCpu->enmEffAddrMode)
         {
-            case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op8_addr16);
-            case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op8_addr32);
-            case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op8_addr64);
+            case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op8_addr16, pIemCpu->iEffSeg);
+            case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op8_addr32, pIemCpu->iEffSeg);
+            case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op8_addr64, pIemCpu->iEffSeg);
             IEM_NOT_REACHED_DEFAULT_CASE_RET();
         }
@@ -3849,7 +3931,7 @@
                 switch (pIemCpu->enmEffAddrMode)
                 {
-                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op16_addr16);
-                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op16_addr32);
-                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op16_addr64);
+                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op16_addr16, pIemCpu->iEffSeg);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op16_addr32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op16_addr64, pIemCpu->iEffSeg);
                     IEM_NOT_REACHED_DEFAULT_CASE_RET();
                 }
@@ -3859,7 +3941,7 @@
                 switch (pIemCpu->enmEffAddrMode)
                 {
-                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op32_addr16);
-                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op32_addr32);
-                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_rep_outs_op32_addr64);
+                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op32_addr16, pIemCpu->iEffSeg);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op32_addr32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_rep_outs_op32_addr64, pIemCpu->iEffSeg);
                     IEM_NOT_REACHED_DEFAULT_CASE_RET();
                 }
@@ -3876,7 +3958,7 @@
                 switch (pIemCpu->enmEffAddrMode)
                 {
-                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op16_addr16);
-                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op16_addr32);
-                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op16_addr64);
+                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op16_addr16, pIemCpu->iEffSeg);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op16_addr32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op16_addr64, pIemCpu->iEffSeg);
                     IEM_NOT_REACHED_DEFAULT_CASE_RET();
                 }
@@ -3886,7 +3968,7 @@
                 switch (pIemCpu->enmEffAddrMode)
                 {
-                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op32_addr16);
-                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op32_addr32);
-                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_outs_op32_addr64);
+                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op32_addr16, pIemCpu->iEffSeg);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op32_addr32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_outs_op32_addr64, pIemCpu->iEffSeg);
                     IEM_NOT_REACHED_DEFAULT_CASE_RET();
                 }
@@ -5194,6 +5276,53 @@
 /** Opcode 0x98. */
 FNIEMOP_STUB(iemOp_cbw);
+
+
 /** Opcode 0x99. */
-FNIEMOP_STUB(iemOp_cwd);
+FNIEMOP_DEF(iemOp_cwd)
+{
+    IEMOP_HLP_NO_LOCK_PREFIX();
+    switch (pIemCpu->enmEffOpSize)
+    {
+        case IEMMODE_16BIT:
+            IEMOP_MNEMONIC("cwd");
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 15) {
+                IEM_MC_STORE_GREG_U16(X86_GREG_xDX, UINT16_C(0xffff));
+            } IEM_MC_ELSE() {
+                IEM_MC_STORE_GREG_U16(X86_GREG_xDX, 0);
+            } IEM_MC_ENDIF();
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+            return VINF_SUCCESS;
+
+        case IEMMODE_32BIT:
+            IEMOP_MNEMONIC("cwq");
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 31) {
+                IEM_MC_STORE_GREG_U32(X86_GREG_xDX, UINT32_C(0xffffffff));
+            } IEM_MC_ELSE() {
+                IEM_MC_STORE_GREG_U32(X86_GREG_xDX, 0);
+            } IEM_MC_ENDIF();
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+            return VINF_SUCCESS;
+
+        case IEMMODE_64BIT:
+            IEMOP_MNEMONIC("cqo");
+            IEM_MC_BEGIN(0, 1);
+            IEM_MC_IF_GREG_BIT_SET(X86_GREG_xAX, 63) {
+                IEM_MC_STORE_GREG_U64(X86_GREG_xDX, UINT64_C(0xffffffffffffffff));
+            } IEM_MC_ELSE() {
+                IEM_MC_STORE_GREG_U64(X86_GREG_xDX, 0);
+            } IEM_MC_ENDIF();
+            IEM_MC_ADVANCE_RIP();
+            IEM_MC_END();
+            return VINF_SUCCESS;
+
+        IEM_NOT_REACHED_DEFAULT_CASE_RET();
+    }
+}
+
+
 /** Opcode 0x9a. */
 FNIEMOP_STUB(iemOp_call_Ap);
@@ -5689,8 +5818,140 @@
 #undef IEM_STOS_CASE
 
+/** Macro used by iemOp_lodsb_AL_Xb and iemOp_lodswd_eAX_Xv */
+#define IEM_LODS_CASE(ValBits, AddrBits) \
+        IEM_MC_BEGIN(0, 2); \
+        IEM_MC_LOCAL(uint##ValBits##_t, uValue); \
+        IEM_MC_LOCAL(uint##AddrBits##_t, uAddr); \
+        IEM_MC_FETCH_GREG_U##AddrBits(uAddr, X86_GREG_xSI); \
+        IEM_MC_FETCH_MEM_U##ValBits(uValue, pIemCpu->iEffSeg, uAddr); \
+        IEM_MC_STORE_GREG_U##ValBits(X86_GREG_xAX, uValue); \
+        IEM_MC_IF_EFL_BIT_SET(X86_EFL_DF) { \
+            IEM_MC_SUB_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
+        } IEM_MC_ELSE() { \
+            IEM_MC_ADD_GREG_U##AddrBits(X86_GREG_xSI, ValBits / 8); \
+        } IEM_MC_ENDIF(); \
+        IEM_MC_ADVANCE_RIP(); \
+        IEM_MC_END();
+
 /** Opcode 0xac. */
-FNIEMOP_STUB(iemOp_lodsb_AL_Xb);
+FNIEMOP_DEF(iemOp_lodsb_AL_Xb)
+{
+    IEMOP_HLP_NO_LOCK_PREFIX();
+
+    /*
+     * Use the C implementation if a repeate prefix is encountered.
+     */
+    if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
+    {
+        IEMOP_MNEMONIC("rep lodsb al,Xb");
+        switch (pIemCpu->enmEffAddrMode)
+        {
+            case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_al_m16, pIemCpu->iEffSeg);
+            case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_al_m32, pIemCpu->iEffSeg);
+            case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_al_m64, pIemCpu->iEffSeg);
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
+    IEMOP_MNEMONIC("lodsb al,Xb");
+
+    /*
+     * Sharing case implementation with stos[wdq] below.
+     */
+    switch (pIemCpu->enmEffAddrMode)
+    {
+        case IEMMODE_16BIT: IEM_LODS_CASE(8, 16); break;
+        case IEMMODE_32BIT: IEM_LODS_CASE(8, 32); break;
+        case IEMMODE_64BIT: IEM_LODS_CASE(8, 64); break;
+        IEM_NOT_REACHED_DEFAULT_CASE_RET();
+    }
+    return VINF_SUCCESS;
+}
+
+
 /** Opcode 0xad. */
-FNIEMOP_STUB(iemOp_lodswd_eAX_Xv);
+FNIEMOP_DEF(iemOp_lodswd_eAX_Xv)
+{
+    IEMOP_HLP_NO_LOCK_PREFIX();
+
+    /*
+     * Use the C implementation if a repeate prefix is encountered.
+     */
+    if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
+    {
+        IEMOP_MNEMONIC("rep lods rAX,Xv");
+        switch (pIemCpu->enmEffOpSize)
+        {
+            case IEMMODE_16BIT:
+                switch (pIemCpu->enmEffAddrMode)
+                {
+                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_ax_m16, pIemCpu->iEffSeg);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_ax_m32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_ax_m64, pIemCpu->iEffSeg);
+                    IEM_NOT_REACHED_DEFAULT_CASE_RET();
+                }
+                break;
+            case IEMMODE_32BIT:
+                switch (pIemCpu->enmEffAddrMode)
+                {
+                    case IEMMODE_16BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_eax_m16, pIemCpu->iEffSeg);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_eax_m32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_eax_m64, pIemCpu->iEffSeg);
+                    IEM_NOT_REACHED_DEFAULT_CASE_RET();
+                }
+            case IEMMODE_64BIT:
+                switch (pIemCpu->enmEffAddrMode)
+                {
+                    case IEMMODE_16BIT: AssertFailedReturn(VERR_INTERNAL_ERROR_3);
+                    case IEMMODE_32BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_rax_m32, pIemCpu->iEffSeg);
+                    case IEMMODE_64BIT: return IEM_MC_DEFER_TO_CIMPL_1(iemCImpl_lods_rax_m64, pIemCpu->iEffSeg);
+                    IEM_NOT_REACHED_DEFAULT_CASE_RET();
+                }
+            IEM_NOT_REACHED_DEFAULT_CASE_RET();
+        }
+    }
+    IEMOP_MNEMONIC("lods rAX,Xv");
+
+    /*
+     * Annoying double switch here.
+     * Using ugly macro for implementing the cases, sharing it with lodsb.
+     */
+    switch (pIemCpu->enmEffOpSize)
+    {
+        case IEMMODE_16BIT:
+            switch (pIemCpu->enmEffAddrMode)
+            {
+                case IEMMODE_16BIT: IEM_LODS_CASE(16, 16); break;
+                case IEMMODE_32BIT: IEM_LODS_CASE(16, 32); break;
+                case IEMMODE_64BIT: IEM_LODS_CASE(16, 64); break;
+                IEM_NOT_REACHED_DEFAULT_CASE_RET();
+            }
+            break;
+
+        case IEMMODE_32BIT:
+            switch (pIemCpu->enmEffAddrMode)
+            {
+                case IEMMODE_16BIT: IEM_LODS_CASE(32, 16); break;
+                case IEMMODE_32BIT: IEM_LODS_CASE(32, 32); break;
+                case IEMMODE_64BIT: IEM_LODS_CASE(32, 64); break;
+                IEM_NOT_REACHED_DEFAULT_CASE_RET();
+            }
+            break;
+
+        case IEMMODE_64BIT:
+            switch (pIemCpu->enmEffAddrMode)
+            {
+                case IEMMODE_16BIT: AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* cannot be encoded */ break;
+                case IEMMODE_32BIT: IEM_LODS_CASE(64, 32); break;
+                case IEMMODE_64BIT: IEM_LODS_CASE(64, 64); break;
+                IEM_NOT_REACHED_DEFAULT_CASE_RET();
+            }
+            break;
+        IEM_NOT_REACHED_DEFAULT_CASE_RET();
+    }
+    return VINF_SUCCESS;
+}
+
+#undef IEM_LODS_CASE
+
 /** Opcode 0xae. */
 FNIEMOP_STUB(iemOp_scasb_AL_Xb);
@@ -6117,7 +6378,17 @@
 
 /** Opcode 0xc4. */
-FNIEMOP_STUB(iemOp_les_Gv_Mp);
+FNIEMOP_DEF(iemOp_les_Gv_Mp)
+{
+    IEMOP_MNEMONIC("les Gv,Mp");
+    return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_ES);
+}
+
+
 /** Opcode 0xc5. */
-FNIEMOP_STUB(iemOp_lds_Gv_Mp);
+FNIEMOP_DEF(iemOp_lds_Gv_Mp)
+{
+    IEMOP_MNEMONIC("lds Gv,Mp");
+    return FNIEMOP_CALL_1(iemOpCommonLoadSRegAndGreg, X86_SREG_DS);
+}
 
 
@@ -6874,7 +7145,7 @@
             IEM_MC_BEGIN(0,0);
             IEM_MC_IF_CX_IS_NZ() {
+                IEM_MC_ADVANCE_RIP();
+            } IEM_MC_ELSE() {
                 IEM_MC_REL_JMP_S8(i8Imm);
-            } IEM_MC_ELSE() {
-                IEM_MC_ADVANCE_RIP();
             } IEM_MC_ENDIF();
             IEM_MC_END();
@@ -6884,7 +7155,7 @@
             IEM_MC_BEGIN(0,0);
             IEM_MC_IF_ECX_IS_NZ() {
+                IEM_MC_ADVANCE_RIP();
+            } IEM_MC_ELSE() {
                 IEM_MC_REL_JMP_S8(i8Imm);
-            } IEM_MC_ELSE() {
-                IEM_MC_ADVANCE_RIP();
             } IEM_MC_ENDIF();
             IEM_MC_END();
@@ -6894,7 +7165,7 @@
             IEM_MC_BEGIN(0,0);
             IEM_MC_IF_RCX_IS_NZ() {
+                IEM_MC_ADVANCE_RIP();
+            } IEM_MC_ELSE() {
                 IEM_MC_REL_JMP_S8(i8Imm);
-            } IEM_MC_ELSE() {
-                IEM_MC_ADVANCE_RIP();
             } IEM_MC_ENDIF();
             IEM_MC_END();
Index: /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 36793)
+++ /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 36794)
@@ -22,4 +22,7 @@
 #include <VBox/vmm/iom.h>
 #include <VBox/vmm/mm.h>
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+# include <VBox/vmm/iem.h>
+#endif
 #include <VBox/param.h>
 #include "IOMInternal.h"
@@ -265,4 +268,7 @@
 #endif
     AssertRC(rc2);
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+    IEMNotifyIOPortRead(pVM, Port, cbValue);
+#endif
 
 #ifdef VBOX_WITH_STATISTICS
@@ -455,4 +461,7 @@
 #endif
     AssertRC(rc2);
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+    IEMNotifyIOPortReadString(pVM, Port, *pGCPtrDst, *pcTransfers, cb);
+#endif
 
 #ifdef LOG_ENABLED
@@ -623,4 +632,7 @@
 #endif
     AssertRC(rc2);
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+    IEMNotifyIOPortWrite(pVM, Port, u32Value, cbValue);
+#endif
 
 /** @todo bird: When I get time, I'll remove the RC/R0 trees and link the RC/R0
@@ -789,4 +801,7 @@
 #endif
     AssertRC(rc2);
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+    IEMNotifyIOPortWriteString(pVM, Port, *pGCPtrSrc, *pcTransfers, cb);
+#endif
 
 #ifdef LOG_ENABLED
Index: /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 36793)
+++ /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 36794)
@@ -29,4 +29,7 @@
 #include <VBox/vmm/pgm.h>
 #include <VBox/vmm/trpm.h>
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+# include <VBox/vmm/iem.h>
+#endif
 #include "IOMInternal.h"
 #include <VBox/vmm/vm.h>
@@ -1374,4 +1377,7 @@
 #endif
     AssertRC(rc);
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+    IEMNotifyMMIORead(pVM, GCPhys, cbValue);
+#endif
 
     /*
@@ -1500,4 +1506,7 @@
 #endif
     AssertRC(rc);
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+    IEMNotifyMMIOWrite(pVM, GCPhys, u32Value, cbValue);
+#endif
 
     /*
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 36793)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 36794)
@@ -60,4 +60,69 @@
 AssertCompileSize(IEMMODEX, 4);
 
+
+#ifdef IEM_VERIFICATION_MODE
+
+/**
+ * Verification event type.
+ */
+typedef enum IEMVERIFYEVENT
+{
+    IEMVERIFYEVENT_INVALID = 0,
+    IEMVERIFYEVENT_IOPORT_READ,
+    IEMVERIFYEVENT_IOPORT_WRITE,
+    IEMVERIFYEVENT_RAM_WRITE,
+    IEMVERIFYEVENT_RAM_READ
+} IEMVERIFYEVENT;
+
+/** Checks if the event type is a RAM read or write. */
+# define IEMVERIFYEVENT_IS_RAM(a_enmType)    ((a_enmType) == IEMVERIFYEVENT_RAM_WRITE || (a_enmType) == IEMVERIFYEVENT_RAM_READ)
+
+/**
+ * Verification event record.
+ */
+typedef struct IEMVERIFYEVTREC
+{
+    /** Pointer to the next record in the list. */
+    struct IEMVERIFYEVTREC *pNext;
+    /** The event type. */
+    IEMVERIFYEVENT          enmEvent;
+    /** The event data. */
+    union
+    {
+        /** IEMVERIFYEVENT_IOPORT_READ */
+        struct
+        {
+            RTIOPORT    Port;
+            uint32_t    cbValue;
+        } IOPortRead;
+
+        /** IEMVERIFYEVENT_IOPORT_WRITE */
+        struct
+        {
+            RTIOPORT    Port;
+            uint32_t    cbValue;
+            uint32_t    u32Value;
+        } IOPortWrite;
+
+        /** IEMVERIFYEVENT_RAM_READ */
+        struct
+        {
+            RTGCPHYS    GCPhys;
+            uint32_t    cb;
+        } RamRead;
+
+        /** IEMVERIFYEVENT_RAM_WRITE */
+        struct
+        {
+            RTGCPHYS    GCPhys;
+            uint32_t    cb;
+            uint8_t     ab[32];
+        } RamWrite;
+    } u;
+} IEMVERIFYEVTREC;
+/** Pointer to an IEM event verification records. */
+typedef IEMVERIFYEVTREC *PIEMVERIFYEVTREC;
+
+#endif /* IEM_VERIFICATION_MODE */
 
 
@@ -188,7 +253,19 @@
     struct
     {
-        uint8_t             ab[/*PAGE_SIZE*/16];
+        uint8_t             ab[64];
     } aBounceBuffers[3];
 
+#ifdef IEM_VERIFICATION_MODE
+    /** The event verification records for what IEM did (LIFO). */
+    R3PTRTYPE(PIEMVERIFYEVTREC)     pIemEvtRecHead;
+    /** Insertion point for pIemEvtRecHead. */
+    R3PTRTYPE(PIEMVERIFYEVTREC *)   ppIemEvtRecNext;
+    /** The event verification records for what the other party did (FIFO). */
+    R3PTRTYPE(PIEMVERIFYEVTREC)     pOtherEvtRecHead;
+    /** Insertion point for pOtherEvtRecHead. */
+    R3PTRTYPE(PIEMVERIFYEVTREC *)   ppOtherEvtRecNext;
+    /** List of free event records. */
+    R3PTRTYPE(PIEMVERIFYEVTREC)     pFreeEvtRec;
+#endif
 } IEMCPU;
 /** Pointer to the per-CPU IEM state. */
@@ -630,5 +707,110 @@
  * @param   a2                  The name of the 3rd argument.
  */
-# define IEM_CIMPL_CALL_3(a_fn, a0, a1, a2) a_fn(pIemCpu, cbInstr, (a0), (a1))
+# define IEM_CIMPL_CALL_3(a_fn, a0, a1, a2) a_fn(pIemCpu, cbInstr, (a0), (a1), (a2))
+
+
+/**
+ * For typedef'ing or declaring a C instruction implementation function taking
+ * four extra arguments.
+ *
+ * @param   a_Name              The name of the type.
+ * @param   a_Type0             The type of the 1st argument
+ * @param   a_Arg0              The name of the 1st argument.
+ * @param   a_Type1             The type of the 2nd argument.
+ * @param   a_Arg1              The name of the 2nd argument.
+ * @param   a_Type2             The type of the 3rd argument.
+ * @param   a_Arg2              The name of the 3rd argument.
+ * @param   a_Type3             The type of the 4th argument.
+ * @param   a_Arg3              The name of the 4th argument.
+ */
+# define IEM_CIMPL_DECL_TYPE_4(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, a_Arg3) \
+    IEM_DECL_IMPL_TYPE(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, a_Type3 a_Arg3))
+/**
+ * For defining a C instruction implementation function taking four extra
+ * arguments.
+ *
+ * @param   a_Name              The name of the function.
+ * @param   a_Type0             The type of the 1st argument
+ * @param   a_Arg0              The name of the 1st argument.
+ * @param   a_Type1             The type of the 2nd argument.
+ * @param   a_Arg1              The name of the 2nd argument.
+ * @param   a_Type2             The type of the 3rd argument.
+ * @param   a_Arg2              The name of the 3rd argument.
+ * @param   a_Type3             The type of the 4th argument.
+ * @param   a_Arg3              The name of the 4th argument.
+ */
+# define IEM_CIMPL_DEF_4(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, aArg3) \
+    IEM_DECL_IMPL_DEF(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, a_Type3 a_Arg3))
+/**
+ * For calling a C instruction implementation function taking four extra
+ * arguments.
+ *
+ * This special call macro adds default arguments to the call and allow us to
+ * change these later.
+ *
+ * @param   a_fn                The name of the function.
+ * @param   a0                  The name of the 1st argument.
+ * @param   a1                  The name of the 2nd argument.
+ * @param   a2                  The name of the 3rd argument.
+ * @param   a3                  The name of the 4th argument.
+ */
+# define IEM_CIMPL_CALL_4(a_fn, a0, a1, a2, a3) a_fn(pIemCpu, cbInstr, (a0), (a1), (a2), (a3))
+
+
+/**
+ * For typedef'ing or declaring a C instruction implementation function taking
+ * five extra arguments.
+ *
+ * @param   a_Name              The name of the type.
+ * @param   a_Type0             The type of the 1st argument
+ * @param   a_Arg0              The name of the 1st argument.
+ * @param   a_Type1             The type of the 2nd argument.
+ * @param   a_Arg1              The name of the 2nd argument.
+ * @param   a_Type2             The type of the 3rd argument.
+ * @param   a_Arg2              The name of the 3rd argument.
+ * @param   a_Type3             The type of the 4th argument.
+ * @param   a_Arg3              The name of the 4th argument.
+ * @param   a_Type4             The type of the 5th argument.
+ * @param   a_Arg4              The name of the 5th argument.
+ */
+# define IEM_CIMPL_DECL_TYPE_5(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, a_Arg3, a_Type4, a_Arg4) \
+    IEM_DECL_IMPL_TYPE(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, \
+                                               a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, \
+                                               a_Type3 a_Arg3, a_Type4 a_Arg4))
+/**
+ * For defining a C instruction implementation function taking five extra
+ * arguments.
+ *
+ * @param   a_Name              The name of the function.
+ * @param   a_Type0             The type of the 1st argument
+ * @param   a_Arg0              The name of the 1st argument.
+ * @param   a_Type1             The type of the 2nd argument.
+ * @param   a_Arg1              The name of the 2nd argument.
+ * @param   a_Type2             The type of the 3rd argument.
+ * @param   a_Arg2              The name of the 3rd argument.
+ * @param   a_Type3             The type of the 4th argument.
+ * @param   a_Arg3              The name of the 4th argument.
+ * @param   a_Type4             The type of the 5th argument.
+ * @param   a_Arg4              The name of the 5th argument.
+ */
+# define IEM_CIMPL_DEF_5(a_Name, a_Type0, a_Arg0, a_Type1, a_Arg1, a_Type2, a_Arg2, a_Type3, a_Arg3, a_Type4, a_Arg4) \
+    IEM_DECL_IMPL_DEF(VBOXSTRICTRC, a_Name, (PIEMCPU pIemCpu, uint8_t cbInstr, \
+                                             a_Type0 a_Arg0, a_Type1 a_Arg1, a_Type2 a_Arg2, \
+                                             a_Type3 a_Arg3, a_Type4 a_Arg4))
+/**
+ * For calling a C instruction implementation function taking five extra
+ * arguments.
+ *
+ * This special call macro adds default arguments to the call and allow us to
+ * change these later.
+ *
+ * @param   a_fn                The name of the function.
+ * @param   a0                  The name of the 1st argument.
+ * @param   a1                  The name of the 2nd argument.
+ * @param   a2                  The name of the 3rd argument.
+ * @param   a3                  The name of the 4th argument.
+ * @param   a4                  The name of the 5th argument.
+ */
+# define IEM_CIMPL_CALL_5(a_fn, a0, a1, a2, a3, a4) a_fn(pIemCpu, cbInstr, (a0), (a1), (a2), (a3), (a4))
 
 /** @}  */
Index: /trunk/src/recompiler/VBoxRecompiler.c
===================================================================
--- /trunk/src/recompiler/VBoxRecompiler.c	(revision 36793)
+++ /trunk/src/recompiler/VBoxRecompiler.c	(revision 36794)
@@ -1407,4 +1407,8 @@
     uint32_t u32CR0;
 
+#ifdef IEM_VERIFICATION_MODE
+    return false;
+#endif
+
     /* Update counter. */
     env->pVM->rem.s.cCanExecuteRaw++;
@@ -4171,4 +4175,5 @@
 REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu)
 {
+#ifndef IEM_VERIFICATION_MODE
     LogFlow(("REMR3NotifyInterruptSet: fInRem=%d interrupts %s\n", pVM->rem.s.fInREM,
              (pVM->rem.s.Env.eflags & IF_MASK) && !(pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK) ? "enabled" : "disabled"));
@@ -4178,4 +4183,5 @@
                        CPU_INTERRUPT_EXTERNAL_HARD);
     }
+#endif
 }
 
@@ -4208,4 +4214,5 @@
 REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst)
 {
+#ifndef IEM_VERIFICATION_MODE
 #ifndef DEBUG_bird
     LogFlow(("REMR3NotifyTimerPending: fInRem=%d\n", pVM->rem.s.fInREM));
@@ -4224,4 +4231,5 @@
     else
         LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: !fInREM; cpu state=%d\n", VMCPU_GET_STATE(pVCpuDst)));
+#endif
 }
 
@@ -4235,4 +4243,5 @@
 REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM)
 {
+#ifndef IEM_VERIFICATION_MODE
     LogFlow(("REMR3NotifyDmaPending: fInRem=%d\n", pVM->rem.s.fInREM));
     if (pVM->rem.s.fInREM)
@@ -4241,4 +4250,5 @@
                        CPU_INTERRUPT_EXTERNAL_DMA);
     }
+#endif
 }
 
@@ -4252,4 +4262,5 @@
 REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM)
 {
+#ifndef IEM_VERIFICATION_MODE
     LogFlow(("REMR3NotifyQueuePending: fInRem=%d\n", pVM->rem.s.fInREM));
     if (pVM->rem.s.fInREM)
@@ -4258,4 +4269,5 @@
                        CPU_INTERRUPT_EXTERNAL_EXIT);
     }
+#endif
 }
 
@@ -4269,4 +4281,5 @@
 REMR3DECL(void) REMR3NotifyFF(PVM pVM)
 {
+#ifndef IEM_VERIFICATION_MODE
     LogFlow(("REMR3NotifyFF: fInRem=%d\n", pVM->rem.s.fInREM));
     if (pVM->rem.s.fInREM)
@@ -4275,4 +4288,5 @@
                        CPU_INTERRUPT_EXTERNAL_EXIT);
     }
+#endif
 }
 
