Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 40241)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 40242)
@@ -3400,5 +3400,6 @@
 
 /**
- * Pushes a FPU result onto the FPU stack if no pending exception prevents it.
+ * Updates FSW and pushes a FPU result onto the FPU stack if no pending
+ * exception prevents it.
  *
  * @param   pIemCpu             The IEM per CPU data.
@@ -3408,18 +3409,19 @@
 static void iemFpuMaybePushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, PCPUMCTX pCtx)
 {
-    /* Check pending exceptions. */
-    uint16_t uFSW = pCtx->fpu.FSW;
-    if (   (pCtx->fpu.FSW & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
+    /* Update FSW and bail if there are pending exceptions afterwards. */
+    uint16_t fFsw = pCtx->fpu.FSW & ~X86_FSW_C_MASK;
+    fFsw |= pResult->FSW & ~X86_FSW_TOP_MASK;
+    if (   (fFsw          & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
         & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM)))
+    {
+        pCtx->fpu.FSW = fFsw;
         return;
-
-    uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK;
+    }
+
+    uint16_t iNewTop = (X86_FSW_TOP_GET(fFsw) + 7) & X86_FSW_TOP_SMASK;
     if (!(pCtx->fpu.FTW & RT_BIT(iNewTop)))
     {
         /* All is fine, push the actual value. */
         pCtx->fpu.FTW |= RT_BIT(iNewTop);
-        pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);
-        pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_TOP_MASK;
-        pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
         pCtx->fpu.aRegs[7].r80 = pResult->r80Result;
     }
@@ -3427,8 +3429,5 @@
     {
         /* Masked stack overflow, push QNaN. */
-        pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);
-        pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_TOP_MASK;
-        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1;
-        pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
+        fFsw |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1;
         iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
     }
@@ -3440,4 +3439,8 @@
         return;
     }
+
+    fFsw &= ~X86_FSW_TOP_MASK;
+    fFsw |= iNewTop << X86_FSW_TOP_SHIFT;
+    pCtx->fpu.FSW = fFsw;
 
     iemFpuRotateStackPush(pCtx);
@@ -3535,4 +3538,57 @@
     iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx);
     iemFpuMaybePushResult(pIemCpu, pResult, pCtx);
+}
+
+
+/**
+ * Replace ST0 with the first value and push the second onto the FPU stack,
+ * unless a pending exception prevents it.
+ *
+ * @param   pIemCpu             The IEM per CPU data.
+ * @param   pResult             The FPU operation result to store and push.
+ */
+static void iemFpuPushResultTwo(PIEMCPU pIemCpu, PIEMFPURESULTTWO pResult)
+{
+    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
+    iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx);
+
+    /* Update FSW and bail if there are pending exceptions afterwards. */
+    uint16_t fFsw = pCtx->fpu.FSW & ~X86_FSW_C_MASK;
+    fFsw |= pResult->FSW & ~X86_FSW_TOP_MASK;
+    if (   (fFsw          & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
+        & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM)))
+    {
+        pCtx->fpu.FSW = fFsw;
+        return;
+    }
+
+    uint16_t iNewTop = (X86_FSW_TOP_GET(fFsw) + 7) & X86_FSW_TOP_SMASK;
+    if (!(pCtx->fpu.FTW & RT_BIT(iNewTop)))
+    {
+        /* All is fine, push the actual value. */
+        pCtx->fpu.FTW |= RT_BIT(iNewTop);
+        pCtx->fpu.aRegs[0].r80 = pResult->r80Result1;
+        pCtx->fpu.aRegs[7].r80 = pResult->r80Result2;
+    }
+    else if (pCtx->fpu.FCW & X86_FCW_IM)
+    {
+        /* Masked stack overflow, push QNaN. */
+        fFsw |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1;
+        iemFpuStoreQNan(&pCtx->fpu.aRegs[0].r80);
+        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
+    }
+    else
+    {
+        /* Raise stack overflow, don't push anything. */
+        pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_C_MASK;
+        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1 | X86_FSW_B | X86_FSW_ES;
+        return;
+    }
+
+    fFsw &= ~X86_FSW_TOP_MASK;
+    fFsw |= iNewTop << X86_FSW_TOP_SHIFT;
+    pCtx->fpu.FSW = fFsw;
+
+    iemFpuRotateStackPush(pCtx);
 }
 
@@ -3780,4 +3836,31 @@
         pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
         pCtx->fpu.FTW |= RT_BIT(iNewTop);
+        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
+        iemFpuRotateStackPush(pCtx);
+    }
+    else
+    {
+        /* Exception pending - don't change TOP or the register stack. */
+        pCtx->fpu.FSW &= ~X86_FSW_C_MASK;
+        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B;
+    }
+}
+
+
+DECL_NO_INLINE(static, void)
+iemFpuStackPushUnderflowTwo(PIEMCPU pIemCpu)
+{
+    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
+    iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx);
+
+    if (pCtx->fpu.FCW & X86_FCW_IM)
+    {
+        /* Masked overflow - Push QNaN. */
+        uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK;
+        pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);
+        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF;
+        pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
+        pCtx->fpu.FTW |= RT_BIT(iNewTop);
+        iemFpuStoreQNan(&pCtx->fpu.aRegs[0].r80);
         iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
         iemFpuRotateStackPush(pCtx);
@@ -6184,4 +6267,8 @@
     iemFpuPushResultWithMemOp(pIemCpu, &a_FpuData, a_iEffSeg, a_GCPtrEff)
 
+/** Replaces ST0 with value one and pushes value 2 onto the FPU stack. */
+#define IEM_MC_PUSH_FPU_RESULT_TWO(a_FpuDataTwo) \
+    iemFpuPushResultTwo(pIemCpu, &a_FpuDataTwo)
+
 /** Stores FPU result in a stack register. */
 #define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) \
@@ -6235,4 +6322,8 @@
 #define IEM_MC_FPU_STACK_PUSH_UNDERFLOW() \
     iemFpuStackPushUnderflow(pIemCpu)
+/** Raises a FPU stack underflow exception for an instruction pushing a result
+ *  value onto the stack and replacing ST0. Sets FPUIP, FPUCS and FOP. */
+#define IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO() \
+    iemFpuStackPushUnderflowTwo(pIemCpu)
 
 /** Raises a FPU stack overflow exception as part of a push attempt.  Sets
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm	(revision 40241)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm	(revision 40242)
@@ -1315,4 +1315,14 @@
 
 ;;
+; Need to move this as well somewhere better?
+;
+struc IEMFPURESULTTWO
+    .r80Result1 resw 5
+    .FSW        resw 1
+    .r80Result2 resw 5
+endstruc
+
+
+;;
 ; Converts a 80-bit floating point value to a 32-bit signed integer.
 ;
@@ -1696,4 +1706,6 @@
 IEMIMPL_FPU_R80 fchs
 IEMIMPL_FPU_R80 fabs
+IEMIMPL_FPU_R80 f2xm1
+IEMIMPL_FPU_R80 fyl2x
 
 
@@ -1766,2 +1778,32 @@
 IEMIMPL_FPU_R80_CONST fldz
 
+
+;;
+; FPU instruction working on one 80-bit floating point value, outputing two.
+;
+; @param    1       The instruction
+;
+; @param    A0      FPU context (fxsave).
+; @param    A1      Pointer to a IEMFPURESULTTWO for the output.
+; @param    A2      Pointer to the 80-bit value.
+;
+BEGINPROC_FASTCALL iemAImpl_fptan_r80_r80, 12
+        PROLOGUE_3_ARGS
+        sub     xSP, 20h
+
+        fninit
+        fld     tword [A2]
+        FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
+        fptan
+
+        fnstsw  word  [A1 + IEMFPURESULTTWO.FSW]
+        fnclex
+        fstp    tword [A1 + IEMFPURESULTTWO.r80Result2]
+        fnclex
+        fstp    tword [A1 + IEMFPURESULTTWO.r80Result1]
+
+        fninit
+        add     xSP, 20h
+        EPILOGUE_3_ARGS 4
+ENDPROC iemAImpl_fptan_r80_r80
+
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 40241)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h	(revision 40242)
@@ -11052,11 +11052,44 @@
 
 /** Opcode 0xd9 0xf0. */
-FNIEMOP_STUB(iemOp_f2xm1);
+FNIEMOP_DEF(iemOp_f2xm1)
+{
+    IEMOP_MNEMONIC("f2xm1 st0");
+    return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_f2xm1_r80);
+}
+
 
 /** Opcode 0xd9 0xf1. */
-FNIEMOP_STUB(iemOp_fylx2);
+FNIEMOP_DEF(iemOp_fylx2)
+{
+    IEMOP_MNEMONIC("fylx2 st0");
+    return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fylx2_r80);
+}
+
 
 /** Opcode 0xd9 0xf2. */
-FNIEMOP_STUB(iemOp_fptan);
+FNIEMOP_DEF(iemOp_fptan)
+{
+    IEMOP_MNEMONIC("fptan st0");
+    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
+
+    IEM_MC_BEGIN(2, 1);
+    IEM_MC_LOCAL(IEMFPURESULTTWO,           FpuResTwo);
+    IEM_MC_ARG_LOCAL_REF(PIEMFPURESULTTWO,  pFpuResTwo, FpuResTwo,  0);
+    IEM_MC_ARG(PCRTFLOAT80U,                pr80Value,              1);
+
+    IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
+    IEM_MC_MAYBE_RAISE_FPU_XCPT();
+    IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0)
+        IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fptan_r80_r80, pFpuResTwo, pr80Value);
+        IEM_MC_PUSH_FPU_RESULT_TWO(FpuResTwo);
+    IEM_MC_ELSE()
+        IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO();
+    IEM_MC_ENDIF();
+    IEM_MC_ADVANCE_RIP();
+
+    IEM_MC_END();
+    return VINF_SUCCESS;
+
+}
 
 /** Opcode 0xd9 0xf3. */
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 40241)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 40242)
@@ -99,4 +99,24 @@
 /** Pointer to a const FPU result. */
 typedef IEMFPURESULT const *PCIEMFPURESULT;
+
+
+/**
+ * A FPU result consisting of two output values and FSW.
+ */
+typedef struct IEMFPURESULTTWO
+{
+    /** The first output value. */
+    RTFLOAT80U      r80Result1;
+    /** The output status. */
+    uint16_t        FSW;
+    /** The second output value. */
+    RTFLOAT80U      r80Result2;
+} IEMFPURESULTTWO;
+AssertCompileMemberOffset(IEMFPURESULTTWO, FSW, 10);
+AssertCompileMemberOffset(IEMFPURESULTTWO, r80Result2, 12);
+/** Pointer to a FPU result consisting of two output values and FSW. */
+typedef IEMFPURESULTTWO *PIEMFPURESULTTWO;
+/** Pointer to a const FPU result consisting of two output values and FSW. */
+typedef IEMFPURESULTTWO const *PCIEMFPURESULTTWO;
 
 
@@ -789,4 +809,6 @@
 FNIEMAIMPLFPUR80UNARY       iemAImpl_fabs_r80;
 FNIEMAIMPLFPUR80UNARY       iemAImpl_fchs_r80;
+FNIEMAIMPLFPUR80UNARY       iemAImpl_f2xm1_r80;
+FNIEMAIMPLFPUR80UNARY       iemAImpl_fylx2_r80;
 
 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR80UNARYFSW,(PCX86FXSTATE pFpuState, uint16_t *pu16Fsw, PCRTFLOAT80U pr80Val));
@@ -804,4 +826,7 @@
 FNIEMAIMPLFPUR80LDCONST     iemAImpl_fldln2;
 FNIEMAIMPLFPUR80LDCONST     iemAImpl_fldz;
+
+IEM_DECL_IMPL_DEF(void, iemAImpl_fptan_r80_r80,(PCX86FXSTATE pFpuState, PIEMFPURESULTTWO pFpuResTwo, PCRTFLOAT80U pr80Val));
+
 /** @} */
 
Index: /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 40241)
+++ /trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp	(revision 40242)
@@ -190,4 +190,6 @@
 #define iemAImpl_ftst_r80               NULL
 #define iemAImpl_fxam_r80               NULL
+#define iemAImpl_f2xm1_r80              NULL
+#define iemAImpl_flx2y_r80              NULL
 #define iemAImpl_fld1                   NULL
 #define iemAImpl_fldl2t                 NULL
@@ -451,4 +453,5 @@
 #define IEM_MC_PUSH_FPU_RESULT(a_FpuData)                               do { } while (0)
 #define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0)
+#define IEM_MC_PUSH_FPU_RESULT_TWO(a_FpuDataTwo)                        do { } while (0)
 #define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg)                    do { } while (0)
 #define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg)           do { } while (0)
@@ -460,4 +463,5 @@
 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStReg, a_iEffSeg, a_GCPtrEff)             do { } while (0)
 #define IEM_MC_FPU_STACK_PUSH_UNDERFLOW()                                                       do { } while (0)
+#define IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO()                                                   do { } while (0)
 #define IEM_MC_FPU_STACK_PUSH_OVERFLOW()                                                        do { } while (0)
 #define IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(a_iEffSeg, a_GCPtrEff)                            do { } while (0)
Index: /trunk/src/VBox/VMM/testcase/tstX86-1.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstX86-1.cpp	(revision 40241)
+++ /trunk/src/VBox/VMM/testcase/tstX86-1.cpp	(revision 40242)
@@ -255,9 +255,9 @@
             RTTestFailed(hTest, "x861_Test5 -> %d", rc);
 
-#endif
         RTTestSub(hTest, "Floating point exceptions ++");
         rc = x861_Test7();
         if (rc != 0)
             RTTestFailed(hTest, "x861_Test6 -> %d", rc);
+#endif
 
         rc = x861_TestFPUInstr1();
Index: /trunk/src/VBox/VMM/testcase/tstX86-1A.asm
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstX86-1A.asm	(revision 40241)
+++ /trunk/src/VBox/VMM/testcase/tstX86-1A.asm	(revision 40242)
@@ -107,4 +107,5 @@
 g_r80_QNaN:     dt 07fffc000000000000000h
 g_r80_QNaNMax:  dt 07fffffffffffffffffffh
+g_r80_NegQNaN:  dt 0ffffc000000000000000h
 g_r80_SNaN:     dt 07fff8000000000000001h
 g_r80_SNaNMax:  dt 07fffbfffffffffffffffh
@@ -3063,5 +3064,4 @@
         FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
         FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
-%endif
 
         ;
@@ -3115,4 +3115,40 @@
         FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
         FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
+%endif
+
+        ;
+        ; FPTAN - calc, store ST0, push 1.0.
+        ;
+        SetSubTest "FPTAN"
+
+        ; ## Normal operation. ##
+        fninit
+        fldpi
+        FpuCheckOpcodeCsIp     { fptan }
+        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One)
+        FxSaveCheckStNValue xSP, 1, 0x00000000, 0x80000000, 0x3fbf ; should be zero, so, this might fail due to precision later.
+
+        ; Masked stack underflow - two QNaNs.
+        fninit
+        FpuCheckOpcodeCsIp     { fptan }
+        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
+        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
+
+        ; Masked stack overflow - two QNaNs
+        fninit
+        fldpi
+        fldpi
+        fldpi
+        fldpi
+        fldpi
+        fldpi
+        fldpi
+        fldpi
+        FpuCheckOpcodeCsIp     { fptan }
+        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
+        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
+
+        ;; @todo Finish FPTAN testcase.
+
 
 .success:
