Index: /trunk/include/VBox/vmm/iem.h
===================================================================
--- /trunk/include/VBox/vmm/iem.h	(revision 60383)
+++ /trunk/include/VBox/vmm/iem.h	(revision 60384)
@@ -50,4 +50,40 @@
 } IEMMODE;
 AssertCompileSize(IEMMODE, 4);
+
+
+/** @name IEMTARGETCPU_XXX - IEM target CPU specification.
+ *
+ * This is a gross simpliciation of CPUMMICROARCH for dealing with really old
+ * CPUs which didn't have much in the way of hinting at supported instructions
+ * and features.  This slowly changes with the introduction of CPUID with the
+ * Intel Pentium.
+ *
+ * @{
+ */
+/** The dynamic target CPU mode is for getting thru the BIOS and then use
+ * the debugger or modifying instruction behaviour (e.g. HLT) to switch to a
+ * different target CPU. */
+#define IEMTARGETCPU_DYNAMIC    UINT32_C(0)
+/** Intel 8086/8088.  */
+#define IEMTARGETCPU_8086       UINT32_C(1)
+/** NEC V20/V30.  */
+#define IEMTARGETCPU_V20        UINT32_C(2)
+/** Intel 80186/80188.  */
+#define IEMTARGETCPU_186        UINT32_C(3)
+/** Intel 80286.  */
+#define IEMTARGETCPU_286        UINT32_C(4)
+/** Intel 80386.  */
+#define IEMTARGETCPU_386        UINT32_C(5)
+/** Intel 80486.  */
+#define IEMTARGETCPU_486        UINT32_C(6)
+/** Intel Pentium .  */
+#define IEMTARGETCPU_PENTIUM    UINT32_C(7)
+/** Intel PentiumPro.  */
+#define IEMTARGETCPU_PPRO       UINT32_C(8)
+/** A reasonably current CPU, probably newer than the pentium pro when it comes
+ * to the feature set and behaviour.  Generally the CPUID info and CPU vendor
+ * dicates the behaviour here. */
+#define IEMTARGETCPU_CURRENT    UINT32_C(9)
+/** @} */
 
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 60383)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 60384)
@@ -9344,4 +9344,72 @@
  */
 
+#ifdef IN_RING3
+# define IEMOP_HLP_MIN_CPU(a_uMinCpu, a_fOnlyIf) \
+    do { \
+        if (IEM_GET_TARGET_CPU(pIemCpu) >= (a_uMinCpu) || !(a_fOnlyIf)) { } \
+        else \
+        { \
+            DBGFSTOP(IEMCPU_TO_VM(pIemCpu)); \
+            return IEMOP_RAISE_INVALID_OPCODE(); \
+        } \
+    } while (0)
+#else
+# define IEMOP_HLP_MIN_CPU(a_uMinCpu, a_fOnlyIf) \
+    do { \
+        if (IEM_GET_TARGET_CPU(pIemCpu) >= (a_uMinCpu) || !(a_fOnlyIf)) { } \
+        else return IEMOP_RAISE_INVALID_OPCODE(); \
+    } while (0)
+#endif
+
+/** The instruction requires a 186 or later. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_186
+# define IEMOP_HLP_MIN_186() do { } while (0)
+#else
+# define IEMOP_HLP_MIN_186() IEMOP_HLP_MIN_CPU(IEMTARGETCPU_186, true)
+#endif
+
+/** The instruction requires a 286 or later. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_286
+# define IEMOP_HLP_MIN_286() do { } while (0)
+#else
+# define IEMOP_HLP_MIN_286() IEMOP_HLP_MIN_CPU(IEMTARGETCPU_286, true)
+#endif
+
+/** The instruction requires a 386 or later. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_386
+# define IEMOP_HLP_MIN_386() do { } while (0)
+#else
+# define IEMOP_HLP_MIN_386() IEMOP_HLP_MIN_CPU(IEMTARGETCPU_386, true)
+#endif
+
+/** The instruction requires a 386 or later if the given expression is true. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_386
+# define IEMOP_HLP_MIN_386_EX(a_fOnlyIf) do { } while (0)
+#else
+# define IEMOP_HLP_MIN_386_EX(a_fOnlyIf) IEMOP_HLP_MIN_CPU(IEMTARGETCPU_386, a_fOnlyIf)
+#endif
+
+/** The instruction requires a 486 or later. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_486
+# define IEMOP_HLP_MIN_486() do { } while (0)
+#else
+# define IEMOP_HLP_MIN_486() IEMOP_HLP_MIN_CPU(IEMTARGETCPU_486, true)
+#endif
+
+/** The instruction requires a Pentium (586) or later. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_586
+# define IEMOP_HLP_MIN_586() do { } while (0)
+#else
+# define IEMOP_HLP_MIN_586() IEMOP_HLP_MIN_CPU(IEMTARGETCPU_586, true)
+#endif
+
+/** The instruction requires a PentiumPro (686) or later. */
+#if IEM_CFG_TARGET_CPU >= IEMTARGETCPU_686
+# define IEMOP_HLP_MIN_686() do { } while (0)
+#else
+# define IEMOP_HLP_MIN_686() IEMOP_HLP_MIN_CPU(IEMTARGETCPU_686, true)
+#endif
+
+
 /** The instruction raises an \#UD in real and V8086 mode. */
 #define IEMOP_HLP_NO_REAL_OR_V86_MODE() \
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 60383)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 60384)
@@ -541,4 +541,5 @@
 {
     IEMOP_MNEMONIC("sldt Rv/Mw");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_REAL_OR_V86_MODE();
 
@@ -598,4 +599,5 @@
 {
     IEMOP_MNEMONIC("str Rv/Mw");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_REAL_OR_V86_MODE();
 
@@ -655,4 +657,5 @@
 {
     IEMOP_MNEMONIC("lldt Ew");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_REAL_OR_V86_MODE();
 
@@ -686,4 +689,5 @@
 {
     IEMOP_MNEMONIC("ltr Ew");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_REAL_OR_V86_MODE();
 
@@ -716,4 +720,5 @@
 FNIEMOP_DEF_2(iemOpCommonGrp6VerX, uint8_t, bRm, bool, fWrite)
 {
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_REAL_OR_V86_MODE();
 
@@ -748,4 +753,5 @@
 {
     IEMOP_MNEMONIC("verr Ew");
+    IEMOP_HLP_MIN_286();
     return FNIEMOP_CALL_2(iemOpCommonGrp6VerX, bRm, false);
 }
@@ -756,4 +762,5 @@
 {
     IEMOP_MNEMONIC("verr Ew");
+    IEMOP_HLP_MIN_286();
     return FNIEMOP_CALL_2(iemOpCommonGrp6VerX, bRm, true);
 }
@@ -784,4 +791,5 @@
 {
     IEMOP_MNEMONIC("sgdt Ms");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_64BIT_OP_SIZE();
     IEM_MC_BEGIN(3, 1);
@@ -834,4 +842,5 @@
 {
     IEMOP_MNEMONIC("sidt Ms");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_64BIT_OP_SIZE();
     IEM_MC_BEGIN(3, 1);
@@ -957,4 +966,5 @@
 {
     IEMOP_MNEMONIC("smsw");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_LOCK_PREFIX();
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
@@ -1014,4 +1024,5 @@
        lower 3-bits are used. */
     IEMOP_MNEMONIC("lmsw");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_LOCK_PREFIX();
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
@@ -1041,4 +1052,5 @@
 {
     IEMOP_MNEMONIC("invlpg");
+    IEMOP_HLP_MIN_486();
     IEMOP_HLP_NO_LOCK_PREFIX();
     IEM_MC_BEGIN(1, 1);
@@ -1055,6 +1067,6 @@
 {
     IEMOP_MNEMONIC("swapgs");
+    IEMOP_HLP_ONLY_64BIT();
     IEMOP_HLP_NO_LOCK_PREFIX();
-    IEMOP_HLP_ONLY_64BIT();
     return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_swapgs);
 }
@@ -1267,8 +1279,8 @@
 
 
-/** Opcode 0x0f 0x04. */
+/** Opcode 0x0f 0x05. */
 FNIEMOP_DEF(iemOp_syscall)
 {
-    IEMOP_MNEMONIC("syscall");
+    IEMOP_MNEMONIC("syscall"); /** @todo 286 LOADALL   */
     IEMOP_HLP_NO_LOCK_PREFIX();
     return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_syscall);
@@ -1276,5 +1288,5 @@
 
 
-/** Opcode 0x0f 0x05. */
+/** Opcode 0x0f 0x06. */
 FNIEMOP_DEF(iemOp_clts)
 {
@@ -1285,8 +1297,8 @@
 
 
-/** Opcode 0x0f 0x06. */
+/** Opcode 0x0f 0x07. */
 FNIEMOP_DEF(iemOp_sysret)
 {
-    IEMOP_MNEMONIC("sysret");
+    IEMOP_MNEMONIC("sysret");  /** @todo 386 LOADALL   */
     IEMOP_HLP_NO_LOCK_PREFIX();
     return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_sysret);
@@ -1296,4 +1308,5 @@
 /** Opcode 0x0f 0x08. */
 FNIEMOP_STUB(iemOp_invd);
+// IEMOP_HLP_MIN_486();
 
 
@@ -1302,4 +1315,5 @@
 {
     IEMOP_MNEMONIC("wbinvd");
+    IEMOP_HLP_MIN_486();
     IEMOP_HLP_NO_LOCK_PREFIX();
     IEM_MC_BEGIN(0, 0);
@@ -1555,4 +1569,5 @@
     /* mod is ignored, as is operand size overrides. */
     IEMOP_MNEMONIC("mov Rd,Cd");
+    IEMOP_HLP_MIN_386();
     if (pIemCpu->enmCpuMode == IEMMODE_64BIT)
         pIemCpu->enmEffOpSize = pIemCpu->enmDefOpSize = IEMMODE_64BIT;
@@ -1586,4 +1601,5 @@
 {
     IEMOP_MNEMONIC("mov Rd,Dd");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX();
@@ -1601,4 +1617,5 @@
     /* mod is ignored, as is operand size overrides. */
     IEMOP_MNEMONIC("mov Cd,Rd");
+    IEMOP_HLP_MIN_386();
     if (pIemCpu->enmCpuMode == IEMMODE_64BIT)
         pIemCpu->enmEffOpSize = pIemCpu->enmDefOpSize = IEMMODE_64BIT;
@@ -1632,4 +1649,5 @@
 {
     IEMOP_MNEMONIC("mov Dd,Rd");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
@@ -1646,4 +1664,5 @@
 {
     IEMOP_MNEMONIC("mov Rd,Td");
+    /** @todo works on 386 and 486. */
     /* The RM byte is not considered, see testcase. */
     return IEMOP_RAISE_INVALID_OPCODE();
@@ -1655,4 +1674,5 @@
 {
     IEMOP_MNEMONIC("mov Td,Rd");
+    /** @todo works on 386 and 486. */
     /* The RM byte is not considered, see testcase. */
     return IEMOP_RAISE_INVALID_OPCODE();
@@ -3122,4 +3142,5 @@
 {
     IEMOP_MNEMONIC("jo  Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3157,4 +3178,5 @@
 {
     IEMOP_MNEMONIC("jno Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3192,4 +3214,5 @@
 {
     IEMOP_MNEMONIC("jc/jb/jnae Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3227,4 +3250,5 @@
 {
     IEMOP_MNEMONIC("jnc/jnb/jae Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3262,4 +3286,5 @@
 {
     IEMOP_MNEMONIC("je/jz Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3297,4 +3322,5 @@
 {
     IEMOP_MNEMONIC("jne/jnz Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3332,4 +3358,5 @@
 {
     IEMOP_MNEMONIC("jbe/jna Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3367,4 +3394,5 @@
 {
     IEMOP_MNEMONIC("jnbe/ja Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3402,4 +3430,5 @@
 {
     IEMOP_MNEMONIC("js  Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3437,4 +3466,5 @@
 {
     IEMOP_MNEMONIC("jns Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3472,4 +3502,5 @@
 {
     IEMOP_MNEMONIC("jp  Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3507,4 +3538,5 @@
 {
     IEMOP_MNEMONIC("jo  Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3542,4 +3574,5 @@
 {
     IEMOP_MNEMONIC("jl/jnge Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3577,4 +3610,5 @@
 {
     IEMOP_MNEMONIC("jnl/jge Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3612,4 +3646,5 @@
 {
     IEMOP_MNEMONIC("jle/jng Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3647,4 +3682,5 @@
 {
     IEMOP_MNEMONIC("jnle/jg Jv");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -3682,4 +3718,5 @@
 {
     IEMOP_MNEMONIC("seto Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3722,4 +3759,5 @@
 {
     IEMOP_MNEMONIC("setno Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3762,4 +3800,5 @@
 {
     IEMOP_MNEMONIC("setc Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3802,4 +3841,5 @@
 {
     IEMOP_MNEMONIC("setnc Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3842,4 +3882,5 @@
 {
     IEMOP_MNEMONIC("sete Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3882,4 +3923,5 @@
 {
     IEMOP_MNEMONIC("setne Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3922,4 +3964,5 @@
 {
     IEMOP_MNEMONIC("setbe Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -3962,4 +4005,5 @@
 {
     IEMOP_MNEMONIC("setnbe Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4002,4 +4046,5 @@
 {
     IEMOP_MNEMONIC("sets Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4042,4 +4087,5 @@
 {
     IEMOP_MNEMONIC("setns Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4082,4 +4128,5 @@
 {
     IEMOP_MNEMONIC("setnp Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4122,4 +4169,5 @@
 {
     IEMOP_MNEMONIC("setnp Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4162,4 +4210,5 @@
 {
     IEMOP_MNEMONIC("setl Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4202,4 +4251,5 @@
 {
     IEMOP_MNEMONIC("setnl Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4242,4 +4292,5 @@
 {
     IEMOP_MNEMONIC("setle Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4282,4 +4333,5 @@
 {
     IEMOP_MNEMONIC("setnle Eb");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_HLP_NO_LOCK_PREFIX(); /** @todo too early? */
@@ -4366,4 +4418,5 @@
 {
     IEMOP_MNEMONIC("push fs");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_NO_LOCK_PREFIX();
     return FNIEMOP_CALL_1(iemOpCommonPushSReg, X86_SREG_FS);
@@ -4375,4 +4428,5 @@
 {
     IEMOP_MNEMONIC("pop fs");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_NO_LOCK_PREFIX();
     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_pop_Sreg, X86_SREG_FS, pIemCpu->enmEffOpSize);
@@ -4384,4 +4438,5 @@
 {
     IEMOP_MNEMONIC("cpuid");
+    IEMOP_HLP_MIN_486(); /* not all 486es. */
     IEMOP_HLP_NO_LOCK_PREFIX();
     return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_cpuid);
@@ -4571,4 +4626,5 @@
 {
     IEMOP_MNEMONIC("bt  Gv,Gv");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonBit_Ev_Gv, &g_iemAImpl_bt);
 }
@@ -4871,12 +4927,14 @@
 {
     IEMOP_MNEMONIC("shld Ev,Gv,Ib");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonShldShrd_Ib, &g_iemAImpl_shld);
 }
 
 
-/** Opcode 0x0f 0xa7. */
+/** Opcode 0x0f 0xa5. */
 FNIEMOP_DEF(iemOp_shld_Ev_Gv_CL)
 {
     IEMOP_MNEMONIC("shld Ev,Gv,CL");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonShldShrd_CL, &g_iemAImpl_shld);
 }
@@ -4887,4 +4945,5 @@
 {
     IEMOP_MNEMONIC("push gs");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_NO_LOCK_PREFIX();
     return FNIEMOP_CALL_1(iemOpCommonPushSReg, X86_SREG_GS);
@@ -4896,4 +4955,5 @@
 {
     IEMOP_MNEMONIC("pop gs");
+    IEMOP_HLP_MIN_386();
     IEMOP_HLP_NO_LOCK_PREFIX();
     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_pop_Sreg, X86_SREG_GS, pIemCpu->enmEffOpSize);
@@ -4903,4 +4963,5 @@
 /** Opcode 0x0f 0xaa. */
 FNIEMOP_STUB(iemOp_rsm);
+//IEMOP_HLP_MIN_386();
 
 
@@ -4909,4 +4970,5 @@
 {
     IEMOP_MNEMONIC("bts Ev,Gv");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonBit_Ev_Gv, &g_iemAImpl_bts);
 }
@@ -4917,4 +4979,5 @@
 {
     IEMOP_MNEMONIC("shrd Ev,Gv,Ib");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonShldShrd_Ib, &g_iemAImpl_shrd);
 }
@@ -4925,4 +4988,5 @@
 {
     IEMOP_MNEMONIC("shrd Ev,Gv,CL");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonShldShrd_CL, &g_iemAImpl_shrd);
 }
@@ -5061,4 +5125,5 @@
 FNIEMOP_DEF(iemOp_Grp15)
 {
+    IEMOP_HLP_MIN_586(); /* Not entirely accurate nor needed, but useful for debugging 286 code. */
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) != (3 << X86_MODRM_MOD_SHIFT))
@@ -5122,4 +5187,5 @@
 {
     IEMOP_MNEMONIC("imul Gv,Ev");
+    IEMOP_HLP_MIN_386();
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rv_rm, &g_iemAImpl_imul_two);
@@ -5131,4 +5197,5 @@
 {
     IEMOP_MNEMONIC("cmpxchg Eb,Gb");
+    IEMOP_HLP_MIN_486();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
 
@@ -5189,4 +5256,5 @@
 {
     IEMOP_MNEMONIC("cmpxchg Ev,Gv");
+    IEMOP_HLP_MIN_486();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
 
@@ -5446,4 +5514,5 @@
 {
     IEMOP_MNEMONIC("lss Gv,Mp");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
@@ -5465,4 +5534,5 @@
 {
     IEMOP_MNEMONIC("lfs Gv,Mp");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
@@ -5476,4 +5546,5 @@
 {
     IEMOP_MNEMONIC("lgs Gv,Mp");
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     if ((bRm & X86_MODRM_MOD_MASK) == (3 << X86_MODRM_MOD_SHIFT))
@@ -5487,4 +5558,5 @@
 {
     IEMOP_MNEMONIC("movzx Gv,Eb");
+    IEMOP_HLP_MIN_386();
 
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
@@ -5578,4 +5650,5 @@
 {
     IEMOP_MNEMONIC("movzx Gv,Ew");
+    IEMOP_HLP_MIN_386();
 
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
@@ -5656,4 +5729,5 @@
 FNIEMOP_DEF(iemOp_Grp8)
 {
+    IEMOP_HLP_MIN_386();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     PCIEMOPBINSIZES pImpl;
@@ -5820,4 +5894,5 @@
 {
     IEMOP_MNEMONIC("btc Ev,Gv");
+    IEMOP_HLP_MIN_386();
     return FNIEMOP_CALL_1(iemOpCommonBit_Ev_Gv, &g_iemAImpl_btc);
 }
@@ -5828,4 +5903,5 @@
 {
     IEMOP_MNEMONIC("bsf Gv,Ev");
+    IEMOP_HLP_MIN_386();
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rv_rm, &g_iemAImpl_bsf);
@@ -5837,4 +5913,5 @@
 {
     IEMOP_MNEMONIC("bsr Gv,Ev");
+    IEMOP_HLP_MIN_386();
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_OF | X86_EFL_SF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF);
     return FNIEMOP_CALL_1(iemOpHlpBinaryOperator_rv_rm, &g_iemAImpl_bsr);
@@ -5846,4 +5923,5 @@
 {
     IEMOP_MNEMONIC("movsx Gv,Eb");
+    IEMOP_HLP_MIN_386();
 
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
@@ -5937,4 +6015,5 @@
 {
     IEMOP_MNEMONIC("movsx Gv,Ew");
+    IEMOP_HLP_MIN_386();
 
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
@@ -6004,4 +6083,5 @@
 {
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
+    IEMOP_HLP_MIN_486();
     IEMOP_MNEMONIC("xadd Eb,Gb");
 
@@ -6063,4 +6143,5 @@
 {
     IEMOP_MNEMONIC("xadd Ev,Gv");
+    IEMOP_HLP_MIN_486();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
 
@@ -6385,4 +6466,5 @@
              prefix.  REX.B is the correct prefix it appears.  For a parallel
              case, see iemOp_mov_AL_Ib and iemOp_mov_eAX_Iv. */
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xAX | pIemCpu->uRexB);
 }
@@ -6393,4 +6475,5 @@
 {
     IEMOP_MNEMONIC("bswap rCX/r9");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xCX | pIemCpu->uRexB);
 }
@@ -6401,4 +6484,5 @@
 {
     IEMOP_MNEMONIC("bswap rDX/r9");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xDX | pIemCpu->uRexB);
 }
@@ -6409,4 +6493,5 @@
 {
     IEMOP_MNEMONIC("bswap rBX/r9");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xBX | pIemCpu->uRexB);
 }
@@ -6417,4 +6502,5 @@
 {
     IEMOP_MNEMONIC("bswap rSP/r12");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xSP | pIemCpu->uRexB);
 }
@@ -6425,4 +6511,5 @@
 {
     IEMOP_MNEMONIC("bswap rBP/r13");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xBP | pIemCpu->uRexB);
 }
@@ -6433,4 +6520,5 @@
 {
     IEMOP_MNEMONIC("bswap rSI/r14");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xSI | pIemCpu->uRexB);
 }
@@ -6441,4 +6529,5 @@
 {
     IEMOP_MNEMONIC("bswap rDI/r15");
+    IEMOP_HLP_MIN_486();
     return FNIEMOP_CALL_1(iemOpCommonBswapGReg, X86_GREG_xDI | pIemCpu->uRexB);
 }
@@ -6999,4 +7088,6 @@
 {
     uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b);
+    /** @todo PUSH CS on 8086, undefined on 80186. */
+    IEMOP_HLP_MIN_286();
     return FNIEMOP_CALL(g_apfnTwoByteMap[b]);
 }
@@ -8084,4 +8175,5 @@
 {
     IEMOP_MNEMONIC("pusha");
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_NO_64BIT();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -8096,4 +8188,5 @@
 {
     IEMOP_MNEMONIC("popa");
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_NO_64BIT();
     if (pIemCpu->enmEffOpSize == IEMMODE_16BIT)
@@ -8106,4 +8199,5 @@
 /** Opcode 0x62. */
 FNIEMOP_STUB(iemOp_bound_Gv_Ma_evex);
+//    IEMOP_HLP_MIN_186();
 
 
@@ -8112,4 +8206,5 @@
 {
     IEMOP_MNEMONIC("arpl Ew,Gw");
+    IEMOP_HLP_MIN_286();
     IEMOP_HLP_NO_REAL_OR_V86_MODE();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
@@ -8205,4 +8300,6 @@
 {
     IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg fs");
+    IEMOP_HLP_MIN_386();
+
     pIemCpu->fPrefixes |= IEM_OP_PRF_SEG_FS;
     pIemCpu->iEffSeg    = X86_SREG_FS;
@@ -8217,4 +8314,6 @@
 {
     IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("seg gs");
+    IEMOP_HLP_MIN_386();
+
     pIemCpu->fPrefixes |= IEM_OP_PRF_SEG_GS;
     pIemCpu->iEffSeg    = X86_SREG_GS;
@@ -8229,4 +8328,6 @@
 {
     IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("op size");
+    IEMOP_HLP_MIN_386();
+
     pIemCpu->fPrefixes |= IEM_OP_PRF_SIZE_OP;
     iemRecalEffOpSize(pIemCpu);
@@ -8241,4 +8342,6 @@
 {
     IEMOP_HLP_CLEAR_REX_NOT_BEFORE_OPCODE("addr size");
+    IEMOP_HLP_MIN_386();
+
     pIemCpu->fPrefixes |= IEM_OP_PRF_SIZE_ADDR;
     switch (pIemCpu->enmDefAddrMode)
@@ -8259,4 +8362,5 @@
 {
     IEMOP_MNEMONIC("push Iz");
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     switch (pIemCpu->enmEffOpSize)
@@ -8304,4 +8408,5 @@
 {
     IEMOP_MNEMONIC("imul Gv,Ev,Iz"); /* Gv = Ev * Iz; */
+    IEMOP_HLP_MIN_186();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
@@ -8464,4 +8569,5 @@
 {
     IEMOP_MNEMONIC("push Ib");
+    IEMOP_HLP_MIN_186();
     int8_t i8Imm; IEM_OPCODE_GET_NEXT_S8(&i8Imm);
     IEMOP_HLP_NO_LOCK_PREFIX();
@@ -8491,4 +8597,5 @@
 {
     IEMOP_MNEMONIC("imul Gv,Ev,Ib"); /* Gv = Ev * Iz; */
+    IEMOP_HLP_MIN_186();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_VERIFICATION_UNDEFINED_EFLAGS(X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF);
@@ -8644,4 +8751,5 @@
 FNIEMOP_DEF(iemOp_insb_Yb_DX)
 {
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_NO_LOCK_PREFIX();
     if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
@@ -8673,4 +8781,5 @@
 FNIEMOP_DEF(iemOp_inswd_Yv_DX)
 {
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_NO_LOCK_PREFIX();
     if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ))
@@ -8734,4 +8843,5 @@
 FNIEMOP_DEF(iemOp_outsb_Yb_DX)
 {
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_NO_LOCK_PREFIX();
     if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPNZ | IEM_OP_PRF_REPZ))
@@ -8763,4 +8873,5 @@
 FNIEMOP_DEF(iemOp_outswd_Yv_DX)
 {
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_NO_LOCK_PREFIX();
     if (pIemCpu->fPrefixes & (IEM_OP_PRF_REPZ | IEM_OP_PRF_REPNZ))
@@ -9373,4 +9484,7 @@
     uint8_t bRm;   IEM_OPCODE_GET_NEXT_U8(&bRm);
     IEMOP_MNEMONIC2("add\0or\0\0adc\0sbb\0and\0sub\0xor\0cmp" + ((bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK)*4, "Ev,Ib");
+    /* Note! Seems the OR, AND, and XOR instructions are present on CPUs prior
+             to the 386 even if absent in the intel reference manuals and some
+             3rd party opcode listings. */
     PCIEMOPBINSIZES pImpl = g_apIemImplGrp1[(bRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK];
 
@@ -11766,4 +11880,5 @@
 FNIEMOP_DEF(iemOp_Grp2_Eb_Ib)
 {
+    IEMOP_HLP_MIN_186();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     PCIEMOPSHIFTSIZES pImpl;
@@ -11826,4 +11941,5 @@
 FNIEMOP_DEF(iemOp_Grp2_Ev_Ib)
 {
+    IEMOP_HLP_MIN_186();
     uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     PCIEMOPSHIFTSIZES pImpl;
@@ -12164,4 +12280,5 @@
 {
     IEMOP_MNEMONIC("enter Iw,Ib");
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     IEMOP_HLP_NO_LOCK_PREFIX();
@@ -12176,4 +12293,5 @@
 {
     IEMOP_MNEMONIC("retn");
+    IEMOP_HLP_MIN_186();
     IEMOP_HLP_DEFAULT_64BIT_OP_SIZE();
     IEMOP_HLP_NO_LOCK_PREFIX();
@@ -12656,4 +12774,5 @@
 {
     IEMOP_MNEMONIC("salc");
+    IEMOP_HLP_MIN_286(); /* (undocument at the time) */
     uint8_t bImm; IEM_OPCODE_GET_NEXT_U8(&bImm);
     IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
@@ -16204,4 +16323,5 @@
 {
     IEMOP_MNEMONIC("int1"); /* icebp */
+    IEMOP_HLP_MIN_386(); /** @todo does not generate #UD on 286, or so they say... */
     /** @todo testcase! */
     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_int, X86_XCPT_DB, false /*fIsBpInstr*/);
@@ -16239,4 +16359,12 @@
 {
     IEMOP_HLP_NO_LOCK_PREFIX();
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC && 0
+    if (   pIemCpu->uTargetCpu == IEMTARGETCPU_CURRENT
+        && pIemCpu->CTX_SUFF(pCtx)->cs.Sel <= 1000)
+    {
+        pIemCpu->uTargetCpu = IEMTARGETCPU_286;
+        LogAlways(("\niemOp_hlt: Enabled CPU restrictions!\n\n"));
+    }
+#endif
     return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_hlt);
 }
Index: /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 60383)
+++ /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 60384)
@@ -72,4 +72,7 @@
          * Host and guest CPU information.
          */
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+        pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT;
+#endif
         if (idCpu == 0)
         {
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 60383)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 60384)
@@ -48,4 +48,17 @@
 # define IEM_VERIFICATION_MODE_FULL
 #endif
+
+
+/** @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.
+ */
+#if !defined(IEM_CFG_TARGET_CPU) || defined(DOXYGEN_RUNNING)
+# define IEM_CFG_TARGET_CPU IEMTARGETCPU_CURRENT
+/*# define IEM_CFG_TARGET_CPU IEMTARGETCPU_DYNAMIC*/
+#endif
+
 
 
@@ -382,5 +395,5 @@
     uint8_t                 offFpuOpcode;
 
-    /** @}*/
+    /** @} */
 
     /** The number of active guest memory mappings. */
@@ -451,4 +464,10 @@
     /** @name Target CPU information.
      * @{ */
+#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
+    /** The target CPU. */
+    uint32_t                uTargetCpu;
+#else
+    uint32_t                u32TargetCpuPadding;
+#endif
     /** The CPU vendor. */
     CPUMCPUVENDOR           enmCpuVendor;
@@ -460,4 +479,6 @@
     CPUMCPUVENDOR           enmHostCpuVendor;
     /** @} */
+
+    uint32_t                u32Alignment6; /**< Alignment padding. */
 
 #ifdef IEM_VERIFICATION_MODE_FULL
@@ -490,4 +511,14 @@
  */
 #define IEMCPU_TO_VM(a_pIemCpu)     ((PVM)( (uintptr_t)(a_pIemCpu) + a_pIemCpu->offVM ))
+
+/** Gets the current IEMTARGETCPU value.
+ * @returns IEMTARGETCPU value.
+ * @param   a_pIemCpu       The IEM per CPU instance data.
+ */
+#if IEM_CFG_TARGET_CPU != IEMTARGETCPU_DYNAMIC
+# define IEM_GET_TARGET_CPU(a_pIemCpu)   (IEM_CFG_TARGET_CPU)
+#else
+# define IEM_GET_TARGET_CPU(a_pIemCpu)   ((a_pIemCpu)->uTargetCpu)
+#endif
 
 /** @name IEM_ACCESS_XXX - Access details.
Index: /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 60383)
+++ /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 60384)
@@ -100,4 +100,11 @@
 #define IEM_OPCODE_GET_NEXT_S32_SX_U64(a_pu64)              do { *(a_pu64) = g_bRandom; CHK_PTYPE(uint64_t *, a_pu64); } while (0)
 #define IEM_OPCODE_GET_NEXT_U64(a_pu64)                     do { *(a_pu64) = g_bRandom; CHK_PTYPE(uint64_t *, a_pu64); } while (0)
+#define IEMOP_HLP_MIN_186()                                 do { } while (0)
+#define IEMOP_HLP_MIN_286()                                 do { } while (0)
+#define IEMOP_HLP_MIN_386()                                 do { } while (0)
+#define IEMOP_HLP_MIN_386_EX(a_fTrue)                       do { } while (0)
+#define IEMOP_HLP_MIN_486()                                 do { } while (0)
+#define IEMOP_HLP_MIN_586()                                 do { } while (0)
+#define IEMOP_HLP_MIN_686()                                 do { } while (0)
 #define IEMOP_HLP_NO_REAL_OR_V86_MODE()                     do { } while (0)
 #define IEMOP_HLP_NO_LOCK_PREFIX()                          do { } while (0)
