Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 60414)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 60415)
@@ -2306,4 +2306,9 @@
 
     uint32_t fEfl = IEMMISC_GET_EFL(pIemCpu, pCtx);
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+    AssertCompile(IEMTARGETCPU_8086 <= IEMTARGETCPU_186 && IEMTARGETCPU_V20 <= IEMTARGETCPU_186 && IEMTARGETCPU_286 > IEMTARGETCPU_186);
+    if (pIemCpu->uTargetCpu <= IEMTARGETCPU_186)
+        fEfl |= UINT16_C(0xf000);
+#endif
     pu16Frame[2] = (uint16_t)fEfl;
     pu16Frame[1] = (uint16_t)pCtx->cs.Sel;
@@ -8614,4 +8619,5 @@
     } while (0)
 #define IEM_MC_SUB_GREG_U64(a_iGReg, a_u64Value)        *(uint64_t *)iemGRegRef(pIemCpu, (a_iGReg)) -= (a_u64Value)
+#define IEM_MC_SUB_LOCAL_U16(a_u16Value, a_u16Const)   do { (a_u16Value) -= a_u16Const; } while (0)
 
 #define IEM_MC_ADD_GREG_U8_TO_LOCAL(a_u8Value, a_iGReg)    do { (a_u8Value)  += iemGRegFetchU8( pIemCpu, (a_iGReg)); } while (0)
@@ -8633,4 +8639,5 @@
 
 #define IEM_MC_OR_LOCAL_U8(a_u8Local, a_u8Mask)         do { (a_u8Local)  |= (a_u8Mask);  } while (0)
+#define IEM_MC_OR_LOCAL_U16(a_u16Local, a_u16Mask)      do { (a_u16Local) |= (a_u16Mask); } while (0)
 #define IEM_MC_OR_LOCAL_U32(a_u32Local, a_u32Mask)      do { (a_u32Local) |= (a_u32Mask); } while (0)
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 60414)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 60415)
@@ -553,5 +553,5 @@
 
     /*
-     * Ok, clear RF and VM and push the flags.
+     * Ok, clear RF and VM, adjust for ancient CPUs, and push the flags.
      */
     fEfl &= ~(X86_EFL_RF | X86_EFL_VM);
@@ -561,4 +561,9 @@
     {
         case IEMMODE_16BIT:
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+            AssertCompile(IEMTARGETCPU_8086 <= IEMTARGETCPU_186 && IEMTARGETCPU_V20 <= IEMTARGETCPU_186 && IEMTARGETCPU_286 > IEMTARGETCPU_186);
+            if (pIemCpu->uTargetCpu <= IEMTARGETCPU_186)
+                fEfl |= UINT16_C(0xf000);
+#endif
             rcStrict = iemMemStackPushU16(pIemCpu, (uint16_t)fEfl);
             break;
@@ -669,4 +674,21 @@
                     return rcStrict;
                 fEflNew = u16Value | (fEflOld & UINT32_C(0xffff0000));
+
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+                /*
+                 * Ancient CPU adjustments:
+                 *  - 8086, 80186, V20/30:
+                 *    Fixed bits 15:12 bits are not kept correctly internally, mostly for
+                 *    practical reasons (masking below).  We add them when pushing flags.
+                 *  - 80286:
+                 *    The NT and IOPL flags cannot be popped from real mode and are
+                 *    therefore always zero (since a 286 can never exit from PM and
+                 *    their initial value is zero).  This changed on a 386 and can
+                 *    therefore be used to detect 286 or 386 CPU in real mode.
+                 */
+                if (   pIemCpu->uTargetCpu == IEMTARGETCPU_286
+                    && !(pCtx->cr0 & X86_CR0_PE) )
+                    fEflNew &= ~(X86_EFL_NT | X86_EFL_IOPL);
+#endif
                 break;
             }
@@ -2765,4 +2787,9 @@
         /** @todo The intel pseudo code does not indicate what happens to
          *        reserved flags. We just ignore them. */
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+        /* Ancient CPU adjustments: See iemCImpl_popf. */
+        if (pIemCpu->uTargetCpu == IEMTARGETCPU_286)
+            uNewFlags &= ~(X86_EFL_NT | X86_EFL_IOPL);
+#endif
     }
     /** @todo Check how this is supposed to work if sp=0xfffe. */
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 60414)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 60415)
@@ -976,4 +976,8 @@
                 IEM_MC_LOCAL(uint16_t, u16Tmp);
                 IEM_MC_FETCH_CR0_U16(u16Tmp);
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+                if (pIemCpu->uTargetCpu == IEMTARGETCPU_286)
+                    IEM_MC_OR_LOCAL_U16(u16Tmp, 0xfff0); /* Reserved bits observed all set on real hw. */
+#endif
                 IEM_MC_STORE_GREG_U16((bRm & X86_MODRM_RM_MASK) | pIemCpu->uRexB, u16Tmp);
                 IEM_MC_ADVANCE_RIP();
@@ -7990,4 +7994,16 @@
 {
     IEMOP_MNEMONIC("push rSP");
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+    if (pIemCpu->uTargetCpu == IEMTARGETCPU_8086)
+    {
+        IEM_MC_BEGIN(0, 1);
+        IEM_MC_LOCAL(uint16_t, u16Value);
+        IEM_MC_FETCH_GREG_U16(u16Value, X86_GREG_xSP);
+        IEM_MC_SUB_LOCAL_U16(u16Value, 2);
+        IEM_MC_PUSH_U16(u16Value);
+        IEM_MC_ADVANCE_RIP();
+        IEM_MC_END();
+    }
+#endif
     return FNIEMOP_CALL_1(iemOpCommonPushGReg, X86_GREG_xSP);
 }
Index: /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 60414)
+++ /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 60415)
@@ -72,11 +72,23 @@
          * Host and guest CPU information.
          */
-#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
-        pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT;
-#endif
         if (idCpu == 0)
         {
             pVCpu->iem.s.enmCpuVendor             = CPUMGetGuestCpuVendor(pVM);
             pVCpu->iem.s.enmHostCpuVendor         = CPUMGetHostCpuVendor(pVM);
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+            switch (pVM->cpum.ro.GuestFeatures.enmMicroarch)
+            {
+                case kCpumMicroarch_Intel_8086:     pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_8086; break;
+                case kCpumMicroarch_Intel_80186:    pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_186; break;
+                case kCpumMicroarch_Intel_80286:    pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_286; break;
+                case kCpumMicroarch_Intel_80386:    pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_386; break;
+                case kCpumMicroarch_Intel_80486:    pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_486; break;
+                case kCpumMicroarch_Intel_P5:       pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PENTIUM; break;
+                case kCpumMicroarch_Intel_P6:       pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PPRO; break;
+                case kCpumMicroarch_NEC_V20:        pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
+                case kCpumMicroarch_NEC_V30:        pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
+                default:                            pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT; break;
+            }
+#endif
         }
         else
@@ -84,4 +96,7 @@
             pVCpu->iem.s.enmCpuVendor             = pVM->aCpus[0].iem.s.enmCpuVendor;
             pVCpu->iem.s.enmHostCpuVendor         = pVM->aCpus[0].iem.s.enmHostCpuVendor;
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+            pVCpu->iem.s.uTargetCpu               = pVM->aCpus[0].iem.s.uTargetCpu;
+#endif
         }
 
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 60414)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 60415)
@@ -51,12 +51,13 @@
 
 /** @def IEM_CFG_TARGET_CPU
- * The minimum target CPU for the IEM emulation (IEMTARGETCPU_XXX value). The
- * default is the a "current" CPU, i.e. something newer than the pentium pro. By
- * twiddling this value, you can make IEM try behave like older CPUs which is
- * useful when checking software that needs to run on real old CPUs.
+ * The minimum target CPU for the IEM emulation (IEMTARGETCPU_XXX value).
+ *
+ * By default we allow this to be configured by the user via the
+ * CPUM/GuestCpuName config string, but this comes at a slight cost during
+ * decoding.  So, for applications of this code where there is no need to
+ * be dynamic wrt target CPU, just modify this define.
  */
 #if !defined(IEM_CFG_TARGET_CPU) || defined(DOXYGEN_RUNNING)
-# define IEM_CFG_TARGET_CPU IEMTARGETCPU_CURRENT
-/*# define IEM_CFG_TARGET_CPU IEMTARGETCPU_DYNAMIC*/
+# define IEM_CFG_TARGET_CPU     IEMTARGETCPU_DYNAMIC
 #endif
 
Index: /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 60414)
+++ /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 60415)
@@ -427,4 +427,5 @@
 #define IEM_MC_SUB_GREG_U32(a_iGReg, a_u32Value)        do { CHK_CONST(uint32_t, a_u32Value); } while (0)
 #define IEM_MC_SUB_GREG_U64(a_iGReg, a_u64Value)        do { CHK_CONST(uint64_t, a_u64Value); } while (0)
+#define IEM_MC_SUB_LOCAL_U16(a_u16Value, a_u16Const)    do { CHK_CONST(uint16_t, a_u16Const); } while (0)
 
 #define IEM_MC_AND_GREG_U8(a_iGReg, a_u8Value)          do { CHK_CONST(uint8_t,  a_u8Value);  } while (0)
@@ -459,4 +460,5 @@
 #define IEM_MC_AND_ARG_U64(a_u64Arg, a_u64Mask)         do { (a_u64Arg)   &= (a_u64Mask); CHK_TYPE(uint64_t, a_u64Arg);   CHK_CONST(uint64_t, a_u64Mask); } while (0)
 #define IEM_MC_OR_LOCAL_U8(a_u8Local, a_u8Mask)         do { (a_u8Local)  |= (a_u8Mask);  CHK_TYPE(uint8_t,  a_u8Local);  CHK_CONST(uint8_t,  a_u8Mask);  } while (0)
+#define IEM_MC_OR_LOCAL_U16(a_u16Local, a_u16Mask)      do { (a_u16Local) |= (a_u16Mask); CHK_TYPE(uint16_t, a_u16Local); CHK_CONST(uint16_t, a_u16Mask); } while (0)
 #define IEM_MC_OR_LOCAL_U32(a_u32Local, a_u32Mask)      do { (a_u32Local) |= (a_u32Mask); CHK_TYPE(uint32_t, a_u32Local); CHK_CONST(uint32_t, a_u32Mask); } while (0)
 #define IEM_MC_SAR_LOCAL_S16(a_i16Local, a_cShift)      do { (a_i16Local) >>= (a_cShift); CHK_TYPE(int16_t, a_i16Local);  CHK_CONST(uint8_t,  a_cShift);  } while (0)
