Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 37038)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 37039)
@@ -537,4 +537,7 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
+static VBOXSTRICTRC     iemRaiseTaskSwitchFaultCurrentTSS(PIEMCPU pIemCpu);
+static VBOXSTRICTRC     iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr);
+static VBOXSTRICTRC     iemRaiseGeneralProtectionFault(PIEMCPU pIemCpu, uint16_t uErr);
 static VBOXSTRICTRC     iemRaiseGeneralProtectionFault0(PIEMCPU pIemCpu);
 static VBOXSTRICTRC     iemRaiseSelectorBounds(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess);
@@ -542,4 +545,10 @@
 static VBOXSTRICTRC     iemRaiseSelectorNotPresent(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess);
 static VBOXSTRICTRC     iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc);
+static VBOXSTRICTRC     iemMemFetchDataU32(PIEMCPU pIemCpu, uint32_t *pu32Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
+static VBOXSTRICTRC     iemMemFetchDataU64(PIEMCPU pIemCpu, uint64_t *pu64Dst, uint8_t iSegReg, RTGCPTR GCPtrMem);
+static VBOXSTRICTRC     iemMemFetchSelDesc(PIEMCPU pIemCpu, PIEMSELDESC pDesc, uint16_t uSel);
+static VBOXSTRICTRC     iemMemStackPushCommitSpecial(PIEMCPU pIemCpu, void *pvMem, uint64_t uNewRsp);
+static VBOXSTRICTRC     iemMemStackPushBeginSpecial(PIEMCPU pIemCpu, size_t cbMem, void **ppvMem, uint64_t *puNewRsp);
+
 #ifdef IEM_VERIFICATION_MODE
 static PIEMVERIFYEVTREC iemVerifyAllocRecord(PIEMCPU pIemCpu);
@@ -1196,4 +1205,458 @@
  */
 
+/** @name IEM_XCPT_FLAGS_XXX - flags for iemRaiseXcptOrInt.
+ * @{ */
+/** CPU exception. */
+#define IEM_XCPT_FLAGS_T_CPU_XCPT       RT_BIT_32(0)
+/** External interrupt (from PIC, APIC, whatever). */
+#define IEM_XCPT_FLAGS_T_EXT_INT        RT_BIT_32(1)
+/** Software interrupt (int, into or bound). */
+#define IEM_XCPT_FLAGS_T_SOFT_INT       RT_BIT_32(2)
+/** Takes an error code. */
+#define IEM_XCPT_FLAGS_ERR              RT_BIT_32(3)
+/** Takes a CR2. */
+#define IEM_XCPT_FLAGS_CR2              RT_BIT_32(4)
+/** Generated by the breakpoint instruction. */
+#define IEM_XCPT_FLAGS_BP_INSTR         RT_BIT_32(5)
+/** Mask out the nesting level. */
+#define IEM_XCPT_FLAGS_NESTING_MASK     UINT32_C(0xff000000)
+/** Shift count for the nesting level. */
+#define IEM_XCPT_FLAGS_NESTING_SHIFT    24
+/** Mask out the nesting level after shifting. */
+#define IEM_XCPT_FLAGS_NESTING_SMASK    UINT32_C(0x000000ff)
+/** @}  */
+
+/**
+ * Loads the specified stack far pointer from the TSS.
+ *
+ * @returns VBox strict status code.
+ * @param   pIemCpu         The IEM per CPU instance data.
+ * @param   pCtx            The CPU context.
+ * @param   uCpl            The CPL to load the stack for.
+ * @param   pSelSS          Where to return the new stack segment.
+ * @param   puEsp           Where to return the new stack pointer.
+ */
+static VBOXSTRICTRC iemRaiseLoadStackFromTss32Or16(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint8_t uCpl,
+                                                   PRTSEL pSelSS, uint32_t *puEsp)
+{
+    VBOXSTRICTRC rcStrict;
+    Assert(uCpl < 4);
+
+    switch (pCtx->trHid.Attr.n.u4Type)
+    {
+        /*
+         * 16-bit TSS (X86TSS16).
+         */
+        case X86_SEL_TYPE_SYS_286_TSS_AVAIL: AssertFailed();
+        case X86_SEL_TYPE_SYS_286_TSS_BUSY:
+        {
+            uint32_t off = uCpl * 4 + 2;
+            if (off + 4 > pCtx->trHid.u32Limit)
+            {
+                Log(("LoadStackFromTss32Or16: out of bounds! uCpl=%d, u32Limit=%#x TSS16\n", uCpl, pCtx->trHid.u32Limit));
+                return iemRaiseTaskSwitchFaultCurrentTSS(pIemCpu);
+            }
+
+            uint32_t u32Tmp;
+            rcStrict = iemMemFetchDataU32(pIemCpu, &u32Tmp, UINT8_MAX, pCtx->trHid.u64Base + off);
+            if (rcStrict == VINF_SUCCESS)
+            {
+                *puEsp  = RT_LOWORD(u32Tmp);
+                *pSelSS = RT_HIWORD(u32Tmp);
+                return VINF_SUCCESS;
+            }
+            break;
+        }
+
+        /*
+         * 32-bit TSS (X86TSS32).
+         */
+        case X86_SEL_TYPE_SYS_386_TSS_AVAIL: AssertFailed();
+        case X86_SEL_TYPE_SYS_386_TSS_BUSY:
+        {
+            uint32_t off = uCpl * 8 + 4;
+            if (off + 7 > pCtx->trHid.u32Limit)
+            {
+                Log(("LoadStackFromTss32Or16: out of bounds! uCpl=%d, u32Limit=%#x TSS16\n", uCpl, pCtx->trHid.u32Limit));
+                return iemRaiseTaskSwitchFaultCurrentTSS(pIemCpu);
+            }
+
+            uint64_t u64Tmp;
+            rcStrict = iemMemFetchDataU64(pIemCpu, &u64Tmp, UINT8_MAX, pCtx->trHid.u64Base + off);
+            if (rcStrict == VINF_SUCCESS)
+            {
+                *puEsp  = u64Tmp & UINT32_MAX;
+                *pSelSS = (RTSEL)(u64Tmp >> 32);
+                return VINF_SUCCESS;
+            }
+            break;
+        }
+
+        default:
+            AssertFailedReturn(VERR_INTERNAL_ERROR_2);
+    }
+    return rcStrict;
+}
+
+
+/**
+ * Adjust the CPU state according to the exception being raised.
+ *
+ * @param   pCtx                The CPU context.
+ * @param   u8Vector            The exception that has been raised.
+ */
+DECLINLINE(void) iemRaiseXcptAdjustState(PCPUMCTX pCtx, uint8_t u8Vector)
+{
+    switch (u8Vector)
+    {
+        case X86_XCPT_DB:
+            pCtx->dr[7] &= ~X86_DR7_GD;
+            break;
+        /** @todo Read the AMD and Intel exception reference... */
+    }
+}
+
+
+/**
+ * Implements exceptions and interrupts for real mode.
+ *
+ * @returns VBox strict status code.
+ * @param   pIemCpu         The IEM per CPU instance data.
+ * @param   pCtx            The CPU context.
+ * @param   cbInstr         The number of bytes to offset rIP by in the return
+ *                          address.
+ * @param   u8Vector        The interrupt / exception vector number.
+ * @param   fFlags          The flags.
+ * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
+ * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
+ */
+static VBOXSTRICTRC
+iemRaiseXcptOrIntInRealMode(PIEMCPU     pIemCpu,
+                             PCPUMCTX    pCtx,
+                             uint8_t     cbInstr,
+                             uint8_t     u8Vector,
+                             uint32_t    fFlags,
+                             uint16_t    uErr,
+                             uint64_t    uCr2)
+{
+    AssertReturn(pIemCpu->enmCpuMode == IEMMODE_16BIT, VERR_INTERNAL_ERROR_3);
+
+    /*
+     * Read the IDT entry.
+     */
+    if (pCtx->idtr.cbIdt < UINT32_C(4) * u8Vector + 3)
+    {
+        Log(("RaiseXcptOrIntInRealMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt));
+        return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
+    }
+    RTFAR16 Idte;
+    VBOXSTRICTRC rcStrict = iemMemFetchDataU32(pIemCpu, (uint32_t *)&Idte, UINT8_MAX,
+                                               pCtx->idtr.pIdt + UINT32_C(4) * u8Vector);
+    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
+        return rcStrict;
+
+    /*
+     * Push the stack frame.
+     */
+    uint16_t *pu16Frame;
+    uint64_t  uNewRsp;
+    rcStrict = iemMemStackPushBeginSpecial(pIemCpu, 6, (void **)&pu16Frame, &uNewRsp);
+    if (rcStrict != VINF_SUCCESS)
+        return rcStrict;
+
+    pu16Frame[2] = (uint16_t)pCtx->eflags.u;
+    pu16Frame[1] = (uint16_t)pCtx->cs;
+    pu16Frame[0] = pCtx->ip + cbInstr;
+    rcStrict = iemMemStackPushCommitSpecial(pIemCpu, pu16Frame, uNewRsp);
+    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
+        return rcStrict;
+
+    /*
+     * Load the vector address into cs:ip and make exception specific state
+     * adjustments.
+     */
+    pCtx->cs               = Idte.sel;
+    pCtx->csHid.u64Base    = (uint32_t)Idte.sel << 4;
+    /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */
+    pCtx->rip              = Idte.off;
+    pCtx->eflags.Bits.u1IF = 0;
+
+    /** @todo do we actually do this in real mode? */
+    if (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT)
+        iemRaiseXcptAdjustState(pCtx, u8Vector);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Implements exceptions and interrupts for protected mode.
+ *
+ * @returns VBox strict status code.
+ * @param   pIemCpu         The IEM per CPU instance data.
+ * @param   pCtx            The CPU context.
+ * @param   cbInstr         The number of bytes to offset rIP by in the return
+ *                          address.
+ * @param   u8Vector        The interrupt / exception vector number.
+ * @param   fFlags          The flags.
+ * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
+ * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
+ */
+static VBOXSTRICTRC
+iemRaiseXcptOrIntInProtMode(PIEMCPU     pIemCpu,
+                            PCPUMCTX    pCtx,
+                            uint8_t     cbInstr,
+                            uint8_t     u8Vector,
+                            uint32_t    fFlags,
+                            uint16_t    uErr,
+                            uint64_t    uCr2)
+{
+    /*
+     * Read the IDT entry.
+     */
+    if (pCtx->idtr.cbIdt < UINT32_C(8) * u8Vector + 7)
+    {
+        Log(("RaiseXcptOrIntInProtMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt));
+        return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
+    }
+    X86DESC Idte;
+    VBOXSTRICTRC rcStrict = iemMemFetchDataU64(pIemCpu, &Idte.u, UINT8_MAX,
+                                               pCtx->idtr.pIdt + UINT32_C(8) * u8Vector);
+    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
+        return rcStrict;
+
+    /*
+     * Check the descriptor type, DPL and such.
+     * ASSUMES this is done in the same order as described for call-gate calls.
+     */
+    if (Idte.Gate.u1DescType)
+    {
+        Log(("RaiseXcptOrIntInProtMode %#x - not system selector (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type));
+        return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
+    }
+    uint32_t fEflToClear = X86_EFL_TF | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM;
+    switch (Idte.Gate.u4Type)
+    {
+        case X86_SEL_TYPE_SYS_UNDEFINED:
+        case X86_SEL_TYPE_SYS_286_TSS_AVAIL:
+        case X86_SEL_TYPE_SYS_LDT:
+        case X86_SEL_TYPE_SYS_286_TSS_BUSY:
+        case X86_SEL_TYPE_SYS_286_CALL_GATE:
+        case X86_SEL_TYPE_SYS_UNDEFINED2:
+        case X86_SEL_TYPE_SYS_386_TSS_AVAIL:
+        case X86_SEL_TYPE_SYS_UNDEFINED3:
+        case X86_SEL_TYPE_SYS_386_TSS_BUSY:
+        case X86_SEL_TYPE_SYS_386_CALL_GATE:
+        case X86_SEL_TYPE_SYS_UNDEFINED4:
+        {
+            /** @todo check what actually happens when the type is wrong...
+             *        esp. call gates. */
+            Log(("RaiseXcptOrIntInProtMode %#x - invalid type (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type));
+            return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
+        }
+
+        case X86_SEL_TYPE_SYS_286_INT_GATE:
+        case X86_SEL_TYPE_SYS_386_INT_GATE:
+            fEflToClear |= X86_EFL_IF;
+            break;
+
+        case X86_SEL_TYPE_SYS_TASK_GATE:
+            /** @todo task gates. */
+            AssertFailedReturn(VERR_NOT_SUPPORTED);
+
+        case X86_SEL_TYPE_SYS_286_TRAP_GATE:
+        case X86_SEL_TYPE_SYS_386_TRAP_GATE:
+            break;
+
+        IEM_NOT_REACHED_DEFAULT_CASE_RET();
+    }
+
+    /* Check DPL against CPL if applicable. */
+    if (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)
+    {
+        if (pIemCpu->uCpl > Idte.Gate.u2Dpl)
+        {
+            Log(("RaiseXcptOrIntInProtMode %#x - CPL (%d) > DPL (%d) -> #GP\n", u8Vector, pIemCpu->uCpl, Idte.Gate.u2Dpl));
+            return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
+        }
+    }
+
+    /* Is it there? */
+    if (!Idte.Gate.u1Present)
+    {
+        Log(("RaiseXcptOrIntInProtMode %#x - not present -> #NP\n", u8Vector));
+        return iemRaiseSelectorNotPresentWithErr(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
+    }
+
+    /* A null CS is bad. */
+    RTSEL NewCS = Idte.Gate.u16Sel;
+    if (!(NewCS & (X86_SEL_MASK | X86_SEL_LDT)))
+    {
+        Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x -> #GP\n", u8Vector, NewCS));
+        return iemRaiseGeneralProtectionFault0(pIemCpu);
+    }
+
+    /* Fetch the descriptor for the new CS. */
+    IEMSELDESC DescCS;
+    rcStrict = iemMemFetchSelDesc(pIemCpu, &DescCS, NewCS);
+    if (rcStrict != VINF_SUCCESS)
+        return rcStrict;
+
+    /* Must be a code segment. */
+    if (!DescCS.Legacy.Gen.u1DescType)
+    {
+        Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x - system selector (%#x) -> #GP\n", u8Vector, NewCS, DescCS.Legacy.Gen.u4Type));
+        return iemRaiseGeneralProtectionFault(pIemCpu, NewCS & (X86_SEL_MASK | X86_SEL_LDT));
+    }
+    if (!(DescCS.Legacy.Gen.u4Type & X86_SEL_TYPE_CODE))
+    {
+        Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x - data selector (%#x) -> #GP\n", u8Vector, NewCS, DescCS.Legacy.Gen.u4Type));
+        return iemRaiseGeneralProtectionFault(pIemCpu, NewCS & (X86_SEL_MASK | X86_SEL_LDT));
+    }
+
+    /* Don't allow lowering the privilege level. */
+    /** @todo Does the lowering of privileges apply to software interrupts
+     *        only?  This has bearings on the more-privileged or
+     *        same-privilege stack behavior further down.  A testcase would
+     *        be nice. */
+    if (DescCS.Legacy.Gen.u2Dpl > pIemCpu->uCpl)
+    {
+        Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x - DPL (%d) > CPL (%d) -> #GP\n",
+             u8Vector, NewCS, DescCS.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
+        return iemRaiseGeneralProtectionFault(pIemCpu, NewCS & (X86_SEL_MASK | X86_SEL_LDT));
+    }
+    /** @todo is the RPL of the interrupt/trap gate descriptor checked? */
+
+    /*
+     * If the privilege level changes, we need to get a new stack from the TSS.
+     */
+    uint8_t const uNewCpl = DescCS.Legacy.Gen.u4Type & X86_SEL_TYPE_CONF
+                          ? pIemCpu->uCpl : DescCS.Legacy.Gen.u2Dpl;
+    if (uNewCpl != pIemCpu->uCpl)
+    {
+        uint32_t uNewEsp;
+        RTSEL    uNewSs;
+        rcStrict = iemRaiseLoadStackFromTss32Or16(pIemCpu, pCtx, uNewCpl, &uNewSs, &uNewEsp);
+        if (rcStrict != VINF_SUCCESS)
+            return rcStrict;
+
+    }
+
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Implements exceptions and interrupts for V8086 mode.
+ *
+ * @returns VBox strict status code.
+ * @param   pIemCpu         The IEM per CPU instance data.
+ * @param   pCtx            The CPU context.
+ * @param   cbInstr         The number of bytes to offset rIP by in the return
+ *                          address.
+ * @param   u8Vector        The interrupt / exception vector number.
+ * @param   fFlags          The flags.
+ * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
+ * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
+ */
+static VBOXSTRICTRC
+iemRaiseXcptOrIntInV8086Mode(PIEMCPU     pIemCpu,
+                             PCPUMCTX    pCtx,
+                             uint8_t     cbInstr,
+                             uint8_t     u8Vector,
+                             uint32_t    fFlags,
+                             uint16_t    uErr,
+                             uint64_t    uCr2)
+{
+    AssertMsgFailed(("V8086 exception / interrupt dispatching\n"));
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Implements exceptions and interrupts for long mode.
+ *
+ * @returns VBox strict status code.
+ * @param   pIemCpu         The IEM per CPU instance data.
+ * @param   pCtx            The CPU context.
+ * @param   cbInstr         The number of bytes to offset rIP by in the return
+ *                          address.
+ * @param   u8Vector        The interrupt / exception vector number.
+ * @param   fFlags          The flags.
+ * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
+ * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
+ */
+static VBOXSTRICTRC
+iemRaiseXcptOrIntInLongMode(PIEMCPU     pIemCpu,
+                            PCPUMCTX    pCtx,
+                            uint8_t     cbInstr,
+                            uint8_t     u8Vector,
+                            uint32_t    fFlags,
+                            uint16_t    uErr,
+                            uint64_t    uCr2)
+{
+    AssertMsgFailed(("long mode exception / interrupt dispatching\n"));
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Implements exceptions and interrupts.
+ *
+ * All exceptions and interrupts goes thru this function!
+ *
+ * @returns VBox strict status code.
+ * @param   pIemCpu         The IEM per CPU instance data.
+ * @param   cbInstr         The number of bytes to offset rIP by in the return
+ *                          address.
+ * @param   u8Vector        The interrupt / exception vector number.
+ * @param   fFlags          The flags.
+ * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
+ * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
+ */
+static VBOXSTRICTRC
+iemRaiseXcptOrInt(PIEMCPU     pIemCpu,
+                  uint8_t     cbInstr,
+                  uint8_t     u8Vector,
+                  uint32_t    fFlags,
+                  uint16_t    uErr,
+                  uint64_t    uCr2)
+{
+    /*
+     * Do recursion accounting.
+     */
+    uint8_t uPrevXcpt = pIemCpu->uCurXcpt;
+    if (pIemCpu->cXcptRecursions > 0)
+    {
+        /** @todo double and tripple faults. */
+        AssertReturn(pIemCpu->cXcptRecursions < 3, VERR_NOT_IMPLEMENTED);
+    }
+    pIemCpu->cXcptRecursions++;
+    pIemCpu->uCurXcpt = u8Vector;
+
+    /*
+     * Call mode specific worker function.
+     */
+    VBOXSTRICTRC    rcStrict;
+    PCPUMCTX        pCtx = pIemCpu->CTX_SUFF(pCtx);
+    if (!(pCtx->cr0 & X86_CR0_PE))
+        rcStrict = iemRaiseXcptOrIntInRealMode( pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
+    else if (pCtx->msrEFER & MSR_K6_EFER_LMA)
+        rcStrict = iemRaiseXcptOrIntInLongMode( pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
+    else if (!pCtx->eflags.Bits.u1VM)
+        rcStrict = iemRaiseXcptOrIntInProtMode( pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
+    else
+        rcStrict = iemRaiseXcptOrIntInV8086Mode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
+
+    /*
+     * Unwind.
+     */
+    pIemCpu->cXcptRecursions--;
+    pIemCpu->uCurXcpt = uPrevXcpt;
+    return rcStrict;
+}
+
+
+/** \#DE - 00.  */
 static VBOXSTRICTRC iemRaiseDivideError(PIEMCPU pIemCpu)
 {
@@ -1202,4 +1665,6 @@
 }
 
+
+/** \#DB - 01.  */
 static VBOXSTRICTRC iemRaiseDebugException(PIEMCPU pIemCpu)
 {
@@ -1208,5 +1673,15 @@
 }
 
+
+/** \#UD - 06.  */
 static VBOXSTRICTRC iemRaiseUndefinedOpcode(PIEMCPU pIemCpu)
+{
+    AssertFailed(/** @todo implement X86_XCPT_UD */);
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** \#NM - 07.  */
+static VBOXSTRICTRC iemRaiseDeviceNotAvailable(PIEMCPU pIemCpu)
 {
     AssertFailed(/** @todo implement this */);
@@ -1215,5 +1690,6 @@
 
 
-static VBOXSTRICTRC iemRaiseDeviceNotAvailable(PIEMCPU pIemCpu)
+/** \#TS(err) - 0a.  */
+static VBOXSTRICTRC iemRaiseTaskSwitchFaultWithErr(PIEMCPU pIemCpu, uint16_t uErr)
 {
     AssertFailed(/** @todo implement this */);
@@ -1222,5 +1698,13 @@
 
 
-static VBOXSTRICTRC iemRaiseGeneralProtectionFault(PIEMCPU pIemCpu, uint16_t uErr)
+/** \#TS(tr) - 0a.  */
+static VBOXSTRICTRC iemRaiseTaskSwitchFaultCurrentTSS(PIEMCPU pIemCpu)
+{
+    return iemRaiseTaskSwitchFaultWithErr(pIemCpu, pIemCpu->CTX_SUFF(pCtx)->tr);
+}
+
+
+/** \#NP(err) - 0b.  */
+static VBOXSTRICTRC iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr)
 {
     AssertFailed(/** @todo implement this */);
@@ -1229,5 +1713,6 @@
 
 
-static VBOXSTRICTRC iemRaiseGeneralProtectionFault0(PIEMCPU pIemCpu)
+/** \#NP(seg) - 0b.  */
+static VBOXSTRICTRC iemRaiseSelectorNotPresentBySegReg(PIEMCPU pIemCpu, uint32_t iSegReg)
 {
     AssertFailed(/** @todo implement this */);
@@ -1236,5 +1721,6 @@
 
 
-static VBOXSTRICTRC iemRaiseNotCanonical(PIEMCPU pIemCpu)
+/** \#NP(sel) - 0b.  */
+static VBOXSTRICTRC iemRaiseSelectorNotPresentBySelector(PIEMCPU pIemCpu, uint16_t uSel)
 {
     AssertFailed(/** @todo implement this */);
@@ -1243,5 +1729,6 @@
 
 
-static VBOXSTRICTRC iemRaiseSelectorBounds(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess)
+/** \#GP(n) - 0d.  */
+static VBOXSTRICTRC iemRaiseGeneralProtectionFault(PIEMCPU pIemCpu, uint16_t uErr)
 {
     AssertFailed(/** @todo implement this */);
@@ -1250,5 +1737,13 @@
 
 
-static VBOXSTRICTRC iemRaiseSelectorInvalidAccess(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess)
+/** \#GP(0) - 0d.  */
+static VBOXSTRICTRC iemRaiseGeneralProtectionFault0(PIEMCPU pIemCpu)
+{
+    return iemRaiseGeneralProtectionFault(pIemCpu, 0);
+}
+
+
+/** \#GP(0) - 0d.  */
+static VBOXSTRICTRC iemRaiseNotCanonical(PIEMCPU pIemCpu)
 {
     AssertFailed(/** @todo implement this */);
@@ -1257,5 +1752,6 @@
 
 
-static VBOXSTRICTRC iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr)
+/** \#GP(sel) - 0d.  */
+static VBOXSTRICTRC iemRaiseSelectorBounds(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess)
 {
     AssertFailed(/** @todo implement this */);
@@ -1264,5 +1760,6 @@
 
 
-static VBOXSTRICTRC iemRaiseSelectorNotPresentBySegReg(PIEMCPU pIemCpu, uint32_t iSegReg)
+/** \#GP(sel) - 0d.  */
+static VBOXSTRICTRC iemRaiseSelectorInvalidAccess(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess)
 {
     AssertFailed(/** @todo implement this */);
@@ -1271,5 +1768,6 @@
 
 
-static VBOXSTRICTRC iemRaiseSelectorNotPresentBySelector(PIEMCPU pIemCpu, uint16_t uSel)
+/** \#PF(n) - 0e.  */
+static VBOXSTRICTRC iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc)
 {
     AssertFailed(/** @todo implement this */);
@@ -1278,11 +1776,5 @@
 
 
-static VBOXSTRICTRC iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc)
-{
-    AssertFailed(/** @todo implement this */);
-    return VERR_NOT_IMPLEMENTED;
-}
-
-
+/** \#MF(n) - 10.  */
 static VBOXSTRICTRC iemRaiseMathFault(PIEMCPU pIemCpu)
 {
@@ -5365,5 +5857,5 @@
     }
 
-    return iemCImpl_RaiseXcptOrInt(&pVCpu->iem.s, 0, u8TrapNo, fFlags, uErrCode, uCr2);
-}
-
+    return iemRaiseXcptOrInt(&pVCpu->iem.s, 0, u8TrapNo, fFlags, uErrCode, uCr2);
+}
+
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 37038)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 37039)
@@ -1115,302 +1115,4 @@
 
 
-/** @name IEM_XCPT_FLAGS_XXX - flags for iemCImpl_RaiseXcptOrInt.
- * @{ */
-/** CPU exception. */
-#define IEM_XCPT_FLAGS_T_CPU_XCPT       RT_BIT_32(0)
-/** External interrupt (from PIC, APIC, whatever). */
-#define IEM_XCPT_FLAGS_T_EXT_INT        RT_BIT_32(1)
-/** Software interrupt (int, into or bound). */
-#define IEM_XCPT_FLAGS_T_SOFT_INT       RT_BIT_32(2)
-/** Takes an error code. */
-#define IEM_XCPT_FLAGS_ERR              RT_BIT_32(3)
-/** Takes a CR2. */
-#define IEM_XCPT_FLAGS_CR2              RT_BIT_32(4)
-/** Generated by the breakpoint instruction. */
-#define IEM_XCPT_FLAGS_BP_INSTR         RT_BIT_32(5)
-/** Mask out the nesting level. */
-#define IEM_XCPT_FLAGS_NESTING_MASK     UINT32_C(0xff000000)
-/** Shift count for the nesting level. */
-#define IEM_XCPT_FLAGS_NESTING_SHIFT    24
-/** Mask out the nesting level after shifting. */
-#define IEM_XCPT_FLAGS_NESTING_SMASK    UINT32_C(0x000000ff)
-/** @}  */
-
-
-/**
- * Adjust the CPU state according to the exception being raised.
- *
- * @param   pCtx                The CPU context.
- * @param   u8Vector            The exception that has been raised.
- */
-DECLINLINE(void) iemCImpl_RaiseXcptAdjustState(PCPUMCTX pCtx, uint8_t u8Vector)
-{
-    switch (u8Vector)
-    {
-        case X86_XCPT_DB:
-            pCtx->dr[7] &= ~X86_DR7_GD;
-            break;
-        /** @todo Read the AMD and Intel exception reference... */
-    }
-}
-
-
-/**
- * Implements exceptions and interrupts for real mode.
- *
- * @returns VBox strict status code.
- * @param   pIemCpu         The IEM per CPU instance data.
- * @param   pCtx            The CPU context.
- * @param   cbInstr         The number of bytes to offset rIP by in the return
- *                          address.
- * @param   u8Vector        The interrupt / exception vector number.
- * @param   fFlags          The flags.
- * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
- * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
- */
-static VBOXSTRICTRC
-iemCImpl_RaiseXcptOrIntInRealMode(PIEMCPU     pIemCpu,
-                                  PCPUMCTX    pCtx,
-                                  uint8_t     cbInstr,
-                                  uint8_t     u8Vector,
-                                  uint32_t    fFlags,
-                                  uint16_t    uErr,
-                                  uint64_t    uCr2)
-{
-    AssertReturn(pIemCpu->enmCpuMode == IEMMODE_16BIT, VERR_INTERNAL_ERROR_3);
-
-    /*
-     * Read the IDT entry.
-     */
-    if (pCtx->idtr.cbIdt < UINT32_C(4) * u8Vector + 3)
-    {
-        Log(("RaiseXcptOrIntInRealMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt));
-        return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
-    }
-    RTFAR16 Idte;
-    VBOXSTRICTRC rcStrict = iemMemFetchDataU32(pIemCpu, (uint32_t *)&Idte, UINT8_MAX,
-                                               pCtx->idtr.pIdt + UINT32_C(4) * u8Vector);
-    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
-        return rcStrict;
-
-    /*
-     * Push the stack frame.
-     */
-    uint16_t *pu16Frame;
-    uint64_t  uNewRsp;
-    rcStrict = iemMemStackPushBeginSpecial(pIemCpu, 6, (void **)&pu16Frame, &uNewRsp);
-    if (rcStrict != VINF_SUCCESS)
-        return rcStrict;
-
-    pu16Frame[2] = (uint16_t)pCtx->eflags.u;
-    pu16Frame[1] = (uint16_t)pCtx->cs;
-    pu16Frame[0] = pCtx->ip + cbInstr;
-    rcStrict = iemMemStackPushCommitSpecial(pIemCpu, pu16Frame, uNewRsp);
-    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
-        return rcStrict;
-
-    /*
-     * Load the vector address into cs:ip and make exception specific state
-     * adjustments.
-     */
-    pCtx->cs               = Idte.sel;
-    pCtx->csHid.u64Base    = (uint32_t)Idte.sel << 4;
-    /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */
-    pCtx->rip              = Idte.off;
-    pCtx->eflags.Bits.u1IF = 0;
-
-    /** @todo do we actually do this in real mode? */
-    if (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT)
-        iemCImpl_RaiseXcptAdjustState(pCtx, u8Vector);
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Implements exceptions and interrupts for protected mode.
- *
- * @returns VBox strict status code.
- * @param   pIemCpu         The IEM per CPU instance data.
- * @param   pCtx            The CPU context.
- * @param   cbInstr         The number of bytes to offset rIP by in the return
- *                          address.
- * @param   u8Vector        The interrupt / exception vector number.
- * @param   fFlags          The flags.
- * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
- * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
- */
-static VBOXSTRICTRC
-iemCImpl_RaiseXcptOrIntInProtMode(PIEMCPU     pIemCpu,
-                                  PCPUMCTX    pCtx,
-                                  uint8_t     cbInstr,
-                                  uint8_t     u8Vector,
-                                  uint32_t    fFlags,
-                                  uint16_t    uErr,
-                                  uint64_t    uCr2)
-{
-    /*
-     * Read the IDT entry.
-     */
-    if (pCtx->idtr.cbIdt < UINT32_C(8) * u8Vector + 7)
-    {
-        Log(("RaiseXcptOrIntInProtMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt));
-        return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
-    }
-    X86DESC Idte;
-    VBOXSTRICTRC rcStrict = iemMemFetchDataU64(pIemCpu, &Idte.u, UINT8_MAX,
-                                               pCtx->idtr.pIdt + UINT32_C(8) * u8Vector);
-    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
-        return rcStrict;
-
-    /*
-     * Check the descriptor type, DPL and such.
-     * ASSUMES this is done in the same order as described for selectors.
-     */
-    if (Idte.Gate.u1DescType)
-    {
-        Log(("RaiseXcptOrIntInProtMode %#x - not system selector (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type));
-        return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
-    }
-    uint32_t fEflToClear = X86_EFL_TF | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM;
-    switch (Idte.Gate.u4Type)
-    {
-        case X86_SEL_TYPE_SYS_UNDEFINED:
-        case X86_SEL_TYPE_SYS_286_TSS_AVAIL:
-        case X86_SEL_TYPE_SYS_LDT:
-        case X86_SEL_TYPE_SYS_286_TSS_BUSY:
-        case X86_SEL_TYPE_SYS_286_CALL_GATE:
-        case X86_SEL_TYPE_SYS_UNDEFINED2:
-        case X86_SEL_TYPE_SYS_386_TSS_AVAIL:
-        case X86_SEL_TYPE_SYS_UNDEFINED3:
-        case X86_SEL_TYPE_SYS_386_TSS_BUSY:
-        case X86_SEL_TYPE_SYS_386_CALL_GATE:
-        case X86_SEL_TYPE_SYS_UNDEFINED4:
-        {
-            /** @todo check what actually happens when the type is wrong...
-             *        esp. call gates. */
-            Log(("RaiseXcptOrIntInProtMode %#x - invalid type (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type));
-            return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
-        }
-
-        case X86_SEL_TYPE_SYS_286_INT_GATE:
-        case X86_SEL_TYPE_SYS_386_INT_GATE:
-            fEflToClear |= X86_EFL_IF;
-            break;
-
-        case X86_SEL_TYPE_SYS_TASK_GATE:
-        case X86_SEL_TYPE_SYS_286_TRAP_GATE:
-        case X86_SEL_TYPE_SYS_386_TRAP_GATE:
-            break;
-
-        IEM_NOT_REACHED_DEFAULT_CASE_RET();
-    }
-
-    /* Check DPL against CPL if applicable. */
-    if (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)
-    {
-#if 0 /** @todo continue here */
-        if (pIemCpu->uCpl > Desc.Legacy.Gen.u2Dpl)
-        {
-            Log(("load sreg%u, %#x - CPL (%d) is greater than DPL (%d) -> #GP\n",
-                 iSegReg, uSel, pIemCpu->uCpl, Desc.Legacy.Gen.u2Dpl));
-            return iemRaiseGeneralProtectionFault(pIemCpu, uSel & (X86_SEL_MASK | X86_SEL_LDT));
-        }
-#endif
-    }
-
-    /* Is it there? */
-    if (!Idte.Gate.u1Present)
-    {
-        Log(("RaiseXcptOrIntInProtMode %#x - not present -> #NP\n", u8Vector));
-        return iemRaiseSelectorNotPresentWithErr(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));
-    }
-
-    return VERR_NOT_IMPLEMENTED;
-}
-
-
-/**
- * Implements exceptions and interrupts for long mode.
- *
- * @returns VBox strict status code.
- * @param   pIemCpu         The IEM per CPU instance data.
- * @param   pCtx            The CPU context.
- * @param   cbInstr         The number of bytes to offset rIP by in the return
- *                          address.
- * @param   u8Vector        The interrupt / exception vector number.
- * @param   fFlags          The flags.
- * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
- * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
- */
-static VBOXSTRICTRC
-iemCImpl_RaiseXcptOrIntInLongMode(PIEMCPU     pIemCpu,
-                                  PCPUMCTX    pCtx,
-                                  uint8_t     cbInstr,
-                                  uint8_t     u8Vector,
-                                  uint32_t    fFlags,
-                                  uint16_t    uErr,
-                                  uint64_t    uCr2)
-{
-    AssertMsgFailed(("long mode exception / interrupt dispatching\n"));
-    return VERR_NOT_IMPLEMENTED;
-}
-
-
-/**
- * Implements exceptions and interrupts.
- *
- * All exceptions and interrupts goes thru this function!
- *
- * @returns VBox strict status code.
- * @param   pIemCpu         The IEM per CPU instance data.
- * @param   cbInstr         The number of bytes to offset rIP by in the return
- *                          address.
- * @param   u8Vector        The interrupt / exception vector number.
- * @param   fFlags          The flags.
- * @param   uErr            The error value if IEM_XCPT_FLAGS_ERR is set.
- * @param   uCr2            The CR2 value if IEM_XCPT_FLAGS_CR2 is set.
- */
-static VBOXSTRICTRC
-iemCImpl_RaiseXcptOrInt(PIEMCPU     pIemCpu,
-                        uint8_t     cbInstr,
-                        uint8_t     u8Vector,
-                        uint32_t    fFlags,
-                        uint16_t    uErr,
-                        uint64_t    uCr2)
-{
-    /*
-     * Do recursion accounting.
-     */
-    uint8_t uPrevXcpt = pIemCpu->uCurXcpt;
-    if (pIemCpu->cXcptRecursions > 0)
-    {
-        /** @todo double and tripple faults. */
-        AssertReturn(pIemCpu->cXcptRecursions < 3, VERR_NOT_IMPLEMENTED);
-    }
-    pIemCpu->cXcptRecursions++;
-    pIemCpu->uCurXcpt = u8Vector;
-
-    /*
-     * Call mode specific worker function.
-     */
-    VBOXSTRICTRC    rcStrict;
-    PCPUMCTX        pCtx = pIemCpu->CTX_SUFF(pCtx);
-    if (!(pCtx->cr0 & X86_CR0_PE))
-        rcStrict = iemCImpl_RaiseXcptOrIntInRealMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
-    else if (pCtx->msrEFER & MSR_K6_EFER_LMA)
-        rcStrict = iemCImpl_RaiseXcptOrIntInLongMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
-    else
-        rcStrict = iemCImpl_RaiseXcptOrIntInProtMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);
-
-    /*
-     * Unwind.
-     */
-    pIemCpu->cXcptRecursions--;
-    pIemCpu->uCurXcpt = uPrevXcpt;
-    return rcStrict;
-}
-
-
 /**
  * Implements int3 and int XX.
@@ -1422,10 +1124,10 @@
 {
     Assert(pIemCpu->cXcptRecursions == 0);
-    return iemCImpl_RaiseXcptOrInt(pIemCpu,
-                                   cbInstr,
-                                   u8Int,
-                                   (fIsBpInstr ? IEM_XCPT_FLAGS_BP_INSTR : 0) | IEM_XCPT_FLAGS_T_SOFT_INT,
-                                   0,
-                                   0);
+    return iemRaiseXcptOrInt(pIemCpu,
+                             cbInstr,
+                             u8Int,
+                             (fIsBpInstr ? IEM_XCPT_FLAGS_BP_INSTR : 0) | IEM_XCPT_FLAGS_T_SOFT_INT,
+                             0,
+                             0);
 }
 
