Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 103587)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 103588)
@@ -4223,4 +4223,13 @@
     return iemRaiseXcptOrInt(pVCpu, 0, X86_XCPT_NM, IEM_XCPT_FLAGS_T_CPU_XCPT, 0, 0);
 }
+
+
+#ifdef IEM_WITH_SETJMP
+/** \#NM - 07.  */
+DECL_NO_RETURN(void) iemRaiseDeviceNotAvailableJmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
+{
+    iemRaiseXcptOrIntJmp(pVCpu, 0, X86_XCPT_NM, IEM_XCPT_FLAGS_T_CPU_XCPT, 0, 0);
+}
+#endif
 
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 103587)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 103588)
@@ -3105,5 +3105,5 @@
     'IEM_MC_NOREF':                                              (McBlock.parseMcGeneric,           False, False, True,  ),
     'IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT':                       (McBlock.parseMcGeneric,           True,  True,  False, ),
-    'IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE':                   (McBlock.parseMcGeneric,           True,  True,  False, ),
+    'IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE':                   (McBlock.parseMcGeneric,           True,  True,  True,  ),
     'IEM_MC_MAYBE_RAISE_FPU_XCPT':                               (McBlock.parseMcGeneric,           True,  True,  False, ),
     'IEM_MC_MAYBE_RAISE_FSGSBASE_XCPT':                          (McBlock.parseMcGeneric,           True,  True,  False, ),
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstTwoByte0f.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstTwoByte0f.cpp.h	(revision 103587)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstTwoByte0f.cpp.h	(revision 103588)
@@ -1719,5 +1719,6 @@
         IEM_MC_ARG_CONST(RTGCPTR,  GCPtrEffDst, NIL_RTGCPTR, 1);
         IEM_MC_FETCH_GREG_U16(u16Tmp, IEM_GET_MODRM_RM(pVCpu, bRm));
-        IEM_MC_CALL_CIMPL_2(IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT, 0, iemCImpl_lmsw, u16Tmp, GCPtrEffDst);
+        IEM_MC_CALL_CIMPL_2(IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT, RT_BIT_64(kIemNativeGstReg_Cr0),
+                            iemCImpl_lmsw, u16Tmp, GCPtrEffDst);
         IEM_MC_END();
     }
@@ -1730,5 +1731,6 @@
         IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
         IEM_MC_FETCH_MEM_U16(u16Tmp, pVCpu->iem.s.iEffSeg, GCPtrEffDst);
-        IEM_MC_CALL_CIMPL_2(IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT, 0, iemCImpl_lmsw, u16Tmp, GCPtrEffDst);
+        IEM_MC_CALL_CIMPL_2(IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT, RT_BIT_64(kIemNativeGstReg_Cr0),
+                            iemCImpl_lmsw, u16Tmp, GCPtrEffDst);
         IEM_MC_END();
     }
@@ -1978,7 +1980,8 @@
     IEMOP_MNEMONIC(syscall, "syscall"); /** @todo 286 LOADALL   */
     IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+    /** @todo r=aeichner Clobbers cr0 only if this is a 286 LOADALL instruction. */
     IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_BRANCH_INDIRECT | IEM_CIMPL_F_BRANCH_FAR | IEM_CIMPL_F_BRANCH_STACK_FAR
-                                | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_END_TB, 0,
-                                iemCImpl_syscall);
+                                | IEM_CIMPL_F_MODE | IEM_CIMPL_F_RFLAGS | IEM_CIMPL_F_END_TB,
+                                RT_BIT_64(kIemNativeGstReg_Cr0), iemCImpl_syscall);
 }
 
@@ -1989,5 +1992,5 @@
     IEMOP_MNEMONIC(clts, "clts");
     IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
-    IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_VMEXIT, 0, iemCImpl_clts);
+    IEM_MC_DEFER_TO_CIMPL_0_RET(IEM_CIMPL_F_VMEXIT, RT_BIT_64(kIemNativeGstReg_Cr0), iemCImpl_clts);
 }
 
@@ -3381,9 +3384,10 @@
     IEMOP_HLP_DONE_DECODING();
 
+    /** @todo r=aeichner Split this up as flushing the cr0 is excessive for crX != 0? */
     if (iCrReg & (2 | 8))
         IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_VMEXIT, 0,
                                     iemCImpl_mov_Cd_Rd, iCrReg, IEM_GET_MODRM_RM(pVCpu, bRm));
     else
-        IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT, 0,
+        IEM_MC_DEFER_TO_CIMPL_2_RET(IEM_CIMPL_F_MODE | IEM_CIMPL_F_VMEXIT, RT_BIT_64(kIemNativeGstReg_Cr0),
                                     iemCImpl_mov_Cd_Rd, iCrReg, IEM_GET_MODRM_RM(pVCpu, bRm));
 }
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 103587)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 103588)
@@ -1598,4 +1598,16 @@
 
 /**
+ * Used by TB code when it wants to raise a \#NM.
+ */
+IEM_DECL_NATIVE_HLP_DEF(int, iemNativeHlpExecRaiseNm,(PVMCPUCC pVCpu))
+{
+    iemRaiseDeviceNotAvailableJmp(pVCpu);
+#ifndef _MSC_VER
+    return VINF_IEM_RAISED_XCPT; /* not reached */
+#endif
+}
+
+
+/**
  * Used by TB code when detecting opcode changes.
  * @see iemThreadeFuncWorkerObsoleteTb
@@ -2906,5 +2918,5 @@
     pReNative->Core.u64ArgVars             = UINT64_MAX;
 
-    AssertCompile(RT_ELEMENTS(pReNative->aidxUniqueLabels) == 9);
+    AssertCompile(RT_ELEMENTS(pReNative->aidxUniqueLabels) == 10);
     pReNative->aidxUniqueLabels[0]         = UINT32_MAX;
     pReNative->aidxUniqueLabels[1]         = UINT32_MAX;
@@ -2916,4 +2928,5 @@
     pReNative->aidxUniqueLabels[7]         = UINT32_MAX;
     pReNative->aidxUniqueLabels[8]         = UINT32_MAX;
+    pReNative->aidxUniqueLabels[9]         = UINT32_MAX;
 
     /* Full host register reinit: */
@@ -3485,5 +3498,5 @@
     /* [kIemNativeGstReg_GprFirst + X86_GREG_x15] = */  { CPUMCTX_OFF_AND_SIZE(r15),                "r15", },
     /* [kIemNativeGstReg_Pc] = */                       { CPUMCTX_OFF_AND_SIZE(rip),                "rip", },
-    /* [kIemNativeGstReg_LivenessPadding17] = */        { UINT32_MAX / 4, 0,                        "pad17", },
+    /* [kIemNativeGstReg_Cr0] = */                      { CPUMCTX_OFF_AND_SIZE(cr0),                "cr0", },
     /* [kIemNativeGstReg_LivenessPadding18] = */        { UINT32_MAX / 4, 0,                        "pad18", },
     /* [kIemNativeGstReg_LivenessPadding19] = */        { UINT32_MAX / 4, 0,                        "pad19", },
@@ -5768,4 +5781,25 @@
 
 /**
+ * Emits the code at the RaiseNm label.
+ */
+static uint32_t iemNativeEmitRaiseNm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxReturnLabel)
+{
+    uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_RaiseNm);
+    if (idxLabel != UINT32_MAX)
+    {
+        iemNativeLabelDefine(pReNative, idxLabel, off);
+
+        /* iemNativeHlpExecRaiseNm(PVMCPUCC pVCpu) */
+        off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
+        off = iemNativeEmitCallImm(pReNative, off, (uintptr_t)iemNativeHlpExecRaiseNm);
+
+        /* jump back to the return sequence. */
+        off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel);
+    }
+    return off;
+}
+
+
+/**
  * Emits the code at the ReturnWithFlags label (returns
  * VINF_IEM_REEXEC_FINISH_WITH_FLAGS).
@@ -6578,4 +6612,54 @@
     iemNativeVarRegisterRelease(pReNative, idxVarPc);
     /** @todo implictly free the variable? */
+
+    return off;
+}
+
+
+
+/*********************************************************************************************************************************
+*   Emitters for raising exceptions (IEM_MC_MAYBE_RAISE_XXX)                                                                     *
+*********************************************************************************************************************************/
+
+#define IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE() \
+    off = iemNativeEmitMaybeRaiseDeviceNotAvailable(pReNative, off, pCallEntry->idxInstr)
+
+/**
+ * Emits code to check if a \#NM exception should be raised.
+ *
+ * @returns New code buffer offset, UINT32_MAX on failure.
+ * @param   pReNative       The native recompile state.
+ * @param   off             The code buffer offset.
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitMaybeRaiseDeviceNotAvailable(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr)
+{
+    /*
+     * Make sure we don't have any outstanding guest register writes as we may
+     * raise an #NM and all guest register must be up to date in CPUMCTX.
+     *
+     * @todo r=aeichner Can we postpone this to the RaiseNm path?
+     */
+    off = iemNativeRegFlushPendingWrites(pReNative, off);
+
+#ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING
+    off = iemNativeEmitStoreImmToVCpuU8(pReNative, off, idxInstr, RT_UOFFSETOF(VMCPUCC, iem.s.idxTbCurInstr));
+#else
+    RT_NOREF(idxInstr);
+#endif
+
+    /* Allocate a temporary CR0 register. */
+    uint8_t const idxCr0Reg       = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Cr0, kIemNativeGstRegUse_ReadOnly);
+    uint8_t const idxLabelRaiseNm = iemNativeLabelCreate(pReNative, kIemNativeLabelType_RaiseNm);
+
+    /*
+     * if (cr0 & (X86_CR0_EM | X86_CR0_TS) != 0)
+     *     return raisexcpt();
+     */
+    /* Test and jump. */
+    off = iemNativeEmitTestAnyBitsInGprAndJmpToLabelIfAnySet(pReNative, off, idxCr0Reg, X86_CR0_EM | X86_CR0_TS, idxLabelRaiseNm);
+
+    /* Free but don't flush the CR0 register. */
+    iemNativeRegFreeTmp(pReNative, idxCr0Reg);
 
     return off;
@@ -13639,4 +13723,7 @@
                                     pszName = "RaiseGp0";
                                     break;
+                                case kIemNativeLabelType_RaiseNm:
+                                    pszName = "RaiseNm";
+                                    break;
                                 case kIemNativeLabelType_ObsoleteTb:
                                     pszName = "ObsoleteTb";
@@ -14186,4 +14273,6 @@
         if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_RaiseGp0))
             off = iemNativeEmitRaiseGp0(pReNative, off, idxReturnLabel);
+        if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_RaiseNm))
+            off = iemNativeEmitRaiseNm(pReNative, off, idxReturnLabel);
         if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_ObsoleteTb))
             off = iemNativeEmitObsoleteTb(pReNative, off, idxReturnLabel);
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 103587)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 103588)
@@ -5148,4 +5148,7 @@
 VBOXSTRICTRC            iemRaiseUndefinedOpcode(PVMCPUCC pVCpu) RT_NOEXCEPT;
 VBOXSTRICTRC            iemRaiseDeviceNotAvailable(PVMCPUCC pVCpu) RT_NOEXCEPT;
+#ifdef IEM_WITH_SETJMP
+DECL_NO_RETURN(void)    iemRaiseDeviceNotAvailableJmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP;
+#endif
 VBOXSTRICTRC            iemRaiseTaskSwitchFaultWithErr(PVMCPUCC pVCpu, uint16_t uErr) RT_NOEXCEPT;
 VBOXSTRICTRC            iemRaiseTaskSwitchFaultCurrentTSS(PVMCPUCC pVCpu) RT_NOEXCEPT;
Index: /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 103587)
+++ /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 103588)
@@ -319,4 +319,5 @@
     kIemNativeLabelType_NonZeroRetOrPassUp,
     kIemNativeLabelType_RaiseGp0,
+    kIemNativeLabelType_RaiseNm,
     kIemNativeLabelType_ObsoleteTb,
     kIemNativeLabelType_NeedCsLimChecking,
@@ -686,5 +687,5 @@
     kIemNativeGstReg_GprLast       = kIemNativeGstReg_GprFirst + 15,
     kIemNativeGstReg_Pc,
-    kIemNativeGstReg_LivenessPadding17,
+    kIemNativeGstReg_Cr0,
     kIemNativeGstReg_LivenessPadding18,
     kIemNativeGstReg_LivenessPadding19,
