VirtualBox

Changeset 40242 in vbox


Ignore:
Timestamp:
Feb 23, 2012 9:58:44 PM (13 years ago)
Author:
vboxsync
Message:

f2xm1, fyl2x, fptan. fpu stack push bugfix.

Location:
trunk/src/VBox/VMM
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r40239 r40242  
    34003400
    34013401/**
    3402  * Pushes a FPU result onto the FPU stack if no pending exception prevents it.
     3402 * Updates FSW and pushes a FPU result onto the FPU stack if no pending
     3403 * exception prevents it.
    34033404 *
    34043405 * @param   pIemCpu             The IEM per CPU data.
     
    34083409static void iemFpuMaybePushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, PCPUMCTX pCtx)
    34093410{
    3410     /* Check pending exceptions. */
    3411     uint16_t uFSW = pCtx->fpu.FSW;
    3412     if (   (pCtx->fpu.FSW & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
     3411    /* Update FSW and bail if there are pending exceptions afterwards. */
     3412    uint16_t fFsw = pCtx->fpu.FSW & ~X86_FSW_C_MASK;
     3413    fFsw |= pResult->FSW & ~X86_FSW_TOP_MASK;
     3414    if (   (fFsw          & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
    34133415        & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM)))
     3416    {
     3417        pCtx->fpu.FSW = fFsw;
    34143418        return;
    3415 
    3416     uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK;
     3419    }
     3420
     3421    uint16_t iNewTop = (X86_FSW_TOP_GET(fFsw) + 7) & X86_FSW_TOP_SMASK;
    34173422    if (!(pCtx->fpu.FTW & RT_BIT(iNewTop)))
    34183423    {
    34193424        /* All is fine, push the actual value. */
    34203425        pCtx->fpu.FTW |= RT_BIT(iNewTop);
    3421         pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);
    3422         pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_TOP_MASK;
    3423         pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
    34243426        pCtx->fpu.aRegs[7].r80 = pResult->r80Result;
    34253427    }
     
    34273429    {
    34283430        /* Masked stack overflow, push QNaN. */
    3429         pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);
    3430         pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_TOP_MASK;
    3431         pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1;
    3432         pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
     3431        fFsw |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1;
    34333432        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
    34343433    }
     
    34403439        return;
    34413440    }
     3441
     3442    fFsw &= ~X86_FSW_TOP_MASK;
     3443    fFsw |= iNewTop << X86_FSW_TOP_SHIFT;
     3444    pCtx->fpu.FSW = fFsw;
    34423445
    34433446    iemFpuRotateStackPush(pCtx);
     
    35353538    iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx);
    35363539    iemFpuMaybePushResult(pIemCpu, pResult, pCtx);
     3540}
     3541
     3542
     3543/**
     3544 * Replace ST0 with the first value and push the second onto the FPU stack,
     3545 * unless a pending exception prevents it.
     3546 *
     3547 * @param   pIemCpu             The IEM per CPU data.
     3548 * @param   pResult             The FPU operation result to store and push.
     3549 */
     3550static void iemFpuPushResultTwo(PIEMCPU pIemCpu, PIEMFPURESULTTWO pResult)
     3551{
     3552    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3553    iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx);
     3554
     3555    /* Update FSW and bail if there are pending exceptions afterwards. */
     3556    uint16_t fFsw = pCtx->fpu.FSW & ~X86_FSW_C_MASK;
     3557    fFsw |= pResult->FSW & ~X86_FSW_TOP_MASK;
     3558    if (   (fFsw          & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
     3559        & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM)))
     3560    {
     3561        pCtx->fpu.FSW = fFsw;
     3562        return;
     3563    }
     3564
     3565    uint16_t iNewTop = (X86_FSW_TOP_GET(fFsw) + 7) & X86_FSW_TOP_SMASK;
     3566    if (!(pCtx->fpu.FTW & RT_BIT(iNewTop)))
     3567    {
     3568        /* All is fine, push the actual value. */
     3569        pCtx->fpu.FTW |= RT_BIT(iNewTop);
     3570        pCtx->fpu.aRegs[0].r80 = pResult->r80Result1;
     3571        pCtx->fpu.aRegs[7].r80 = pResult->r80Result2;
     3572    }
     3573    else if (pCtx->fpu.FCW & X86_FCW_IM)
     3574    {
     3575        /* Masked stack overflow, push QNaN. */
     3576        fFsw |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1;
     3577        iemFpuStoreQNan(&pCtx->fpu.aRegs[0].r80);
     3578        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
     3579    }
     3580    else
     3581    {
     3582        /* Raise stack overflow, don't push anything. */
     3583        pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_C_MASK;
     3584        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1 | X86_FSW_B | X86_FSW_ES;
     3585        return;
     3586    }
     3587
     3588    fFsw &= ~X86_FSW_TOP_MASK;
     3589    fFsw |= iNewTop << X86_FSW_TOP_SHIFT;
     3590    pCtx->fpu.FSW = fFsw;
     3591
     3592    iemFpuRotateStackPush(pCtx);
    35373593}
    35383594
     
    37803836        pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
    37813837        pCtx->fpu.FTW |= RT_BIT(iNewTop);
     3838        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
     3839        iemFpuRotateStackPush(pCtx);
     3840    }
     3841    else
     3842    {
     3843        /* Exception pending - don't change TOP or the register stack. */
     3844        pCtx->fpu.FSW &= ~X86_FSW_C_MASK;
     3845        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B;
     3846    }
     3847}
     3848
     3849
     3850DECL_NO_INLINE(static, void)
     3851iemFpuStackPushUnderflowTwo(PIEMCPU pIemCpu)
     3852{
     3853    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3854    iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx);
     3855
     3856    if (pCtx->fpu.FCW & X86_FCW_IM)
     3857    {
     3858        /* Masked overflow - Push QNaN. */
     3859        uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK;
     3860        pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);
     3861        pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF;
     3862        pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;
     3863        pCtx->fpu.FTW |= RT_BIT(iNewTop);
     3864        iemFpuStoreQNan(&pCtx->fpu.aRegs[0].r80);
    37823865        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
    37833866        iemFpuRotateStackPush(pCtx);
     
    61846267    iemFpuPushResultWithMemOp(pIemCpu, &a_FpuData, a_iEffSeg, a_GCPtrEff)
    61856268
     6269/** Replaces ST0 with value one and pushes value 2 onto the FPU stack. */
     6270#define IEM_MC_PUSH_FPU_RESULT_TWO(a_FpuDataTwo) \
     6271    iemFpuPushResultTwo(pIemCpu, &a_FpuDataTwo)
     6272
    61866273/** Stores FPU result in a stack register. */
    61876274#define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) \
     
    62356322#define IEM_MC_FPU_STACK_PUSH_UNDERFLOW() \
    62366323    iemFpuStackPushUnderflow(pIemCpu)
     6324/** Raises a FPU stack underflow exception for an instruction pushing a result
     6325 *  value onto the stack and replacing ST0. Sets FPUIP, FPUCS and FOP. */
     6326#define IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO() \
     6327    iemFpuStackPushUnderflowTwo(pIemCpu)
    62376328
    62386329/** Raises a FPU stack overflow exception as part of a push attempt.  Sets
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm

    r40239 r40242  
    13151315
    13161316;;
     1317; Need to move this as well somewhere better?
     1318;
     1319struc IEMFPURESULTTWO
     1320    .r80Result1 resw 5
     1321    .FSW        resw 1
     1322    .r80Result2 resw 5
     1323endstruc
     1324
     1325
     1326;;
    13171327; Converts a 80-bit floating point value to a 32-bit signed integer.
    13181328;
     
    16961706IEMIMPL_FPU_R80 fchs
    16971707IEMIMPL_FPU_R80 fabs
     1708IEMIMPL_FPU_R80 f2xm1
     1709IEMIMPL_FPU_R80 fyl2x
    16981710
    16991711
     
    17661778IEMIMPL_FPU_R80_CONST fldz
    17671779
     1780
     1781;;
     1782; FPU instruction working on one 80-bit floating point value, outputing two.
     1783;
     1784; @param    1       The instruction
     1785;
     1786; @param    A0      FPU context (fxsave).
     1787; @param    A1      Pointer to a IEMFPURESULTTWO for the output.
     1788; @param    A2      Pointer to the 80-bit value.
     1789;
     1790BEGINPROC_FASTCALL iemAImpl_fptan_r80_r80, 12
     1791        PROLOGUE_3_ARGS
     1792        sub     xSP, 20h
     1793
     1794        fninit
     1795        fld     tword [A2]
     1796        FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
     1797        fptan
     1798
     1799        fnstsw  word  [A1 + IEMFPURESULTTWO.FSW]
     1800        fnclex
     1801        fstp    tword [A1 + IEMFPURESULTTWO.r80Result2]
     1802        fnclex
     1803        fstp    tword [A1 + IEMFPURESULTTWO.r80Result1]
     1804
     1805        fninit
     1806        add     xSP, 20h
     1807        EPILOGUE_3_ARGS 4
     1808ENDPROC iemAImpl_fptan_r80_r80
     1809
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h

    r40239 r40242  
    1105211052
    1105311053/** Opcode 0xd9 0xf0. */
    11054 FNIEMOP_STUB(iemOp_f2xm1);
     11054FNIEMOP_DEF(iemOp_f2xm1)
     11055{
     11056    IEMOP_MNEMONIC("f2xm1 st0");
     11057    return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_f2xm1_r80);
     11058}
     11059
    1105511060
    1105611061/** Opcode 0xd9 0xf1. */
    11057 FNIEMOP_STUB(iemOp_fylx2);
     11062FNIEMOP_DEF(iemOp_fylx2)
     11063{
     11064    IEMOP_MNEMONIC("fylx2 st0");
     11065    return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fylx2_r80);
     11066}
     11067
    1105811068
    1105911069/** Opcode 0xd9 0xf2. */
    11060 FNIEMOP_STUB(iemOp_fptan);
     11070FNIEMOP_DEF(iemOp_fptan)
     11071{
     11072    IEMOP_MNEMONIC("fptan st0");
     11073    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     11074
     11075    IEM_MC_BEGIN(2, 1);
     11076    IEM_MC_LOCAL(IEMFPURESULTTWO,           FpuResTwo);
     11077    IEM_MC_ARG_LOCAL_REF(PIEMFPURESULTTWO,  pFpuResTwo, FpuResTwo,  0);
     11078    IEM_MC_ARG(PCRTFLOAT80U,                pr80Value,              1);
     11079
     11080    IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
     11081    IEM_MC_MAYBE_RAISE_FPU_XCPT();
     11082    IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0)
     11083        IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fptan_r80_r80, pFpuResTwo, pr80Value);
     11084        IEM_MC_PUSH_FPU_RESULT_TWO(FpuResTwo);
     11085    IEM_MC_ELSE()
     11086        IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO();
     11087    IEM_MC_ENDIF();
     11088    IEM_MC_ADVANCE_RIP();
     11089
     11090    IEM_MC_END();
     11091    return VINF_SUCCESS;
     11092
     11093}
    1106111094
    1106211095/** Opcode 0xd9 0xf3. */
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r40239 r40242  
    9999/** Pointer to a const FPU result. */
    100100typedef IEMFPURESULT const *PCIEMFPURESULT;
     101
     102
     103/**
     104 * A FPU result consisting of two output values and FSW.
     105 */
     106typedef struct IEMFPURESULTTWO
     107{
     108    /** The first output value. */
     109    RTFLOAT80U      r80Result1;
     110    /** The output status. */
     111    uint16_t        FSW;
     112    /** The second output value. */
     113    RTFLOAT80U      r80Result2;
     114} IEMFPURESULTTWO;
     115AssertCompileMemberOffset(IEMFPURESULTTWO, FSW, 10);
     116AssertCompileMemberOffset(IEMFPURESULTTWO, r80Result2, 12);
     117/** Pointer to a FPU result consisting of two output values and FSW. */
     118typedef IEMFPURESULTTWO *PIEMFPURESULTTWO;
     119/** Pointer to a const FPU result consisting of two output values and FSW. */
     120typedef IEMFPURESULTTWO const *PCIEMFPURESULTTWO;
    101121
    102122
     
    789809FNIEMAIMPLFPUR80UNARY       iemAImpl_fabs_r80;
    790810FNIEMAIMPLFPUR80UNARY       iemAImpl_fchs_r80;
     811FNIEMAIMPLFPUR80UNARY       iemAImpl_f2xm1_r80;
     812FNIEMAIMPLFPUR80UNARY       iemAImpl_fylx2_r80;
    791813
    792814typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR80UNARYFSW,(PCX86FXSTATE pFpuState, uint16_t *pu16Fsw, PCRTFLOAT80U pr80Val));
     
    804826FNIEMAIMPLFPUR80LDCONST     iemAImpl_fldln2;
    805827FNIEMAIMPLFPUR80LDCONST     iemAImpl_fldz;
     828
     829IEM_DECL_IMPL_DEF(void, iemAImpl_fptan_r80_r80,(PCX86FXSTATE pFpuState, PIEMFPURESULTTWO pFpuResTwo, PCRTFLOAT80U pr80Val));
     830
    806831/** @} */
    807832
  • trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp

    r40239 r40242  
    190190#define iemAImpl_ftst_r80               NULL
    191191#define iemAImpl_fxam_r80               NULL
     192#define iemAImpl_f2xm1_r80              NULL
     193#define iemAImpl_flx2y_r80              NULL
    192194#define iemAImpl_fld1                   NULL
    193195#define iemAImpl_fldl2t                 NULL
     
    451453#define IEM_MC_PUSH_FPU_RESULT(a_FpuData)                               do { } while (0)
    452454#define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0)
     455#define IEM_MC_PUSH_FPU_RESULT_TWO(a_FpuDataTwo)                        do { } while (0)
    453456#define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg)                    do { } while (0)
    454457#define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg)           do { } while (0)
     
    460463#define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStReg, a_iEffSeg, a_GCPtrEff)             do { } while (0)
    461464#define IEM_MC_FPU_STACK_PUSH_UNDERFLOW()                                                       do { } while (0)
     465#define IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO()                                                   do { } while (0)
    462466#define IEM_MC_FPU_STACK_PUSH_OVERFLOW()                                                        do { } while (0)
    463467#define IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(a_iEffSeg, a_GCPtrEff)                            do { } while (0)
  • trunk/src/VBox/VMM/testcase/tstX86-1.cpp

    r40209 r40242  
    255255            RTTestFailed(hTest, "x861_Test5 -> %d", rc);
    256256
    257 #endif
    258257        RTTestSub(hTest, "Floating point exceptions ++");
    259258        rc = x861_Test7();
    260259        if (rc != 0)
    261260            RTTestFailed(hTest, "x861_Test6 -> %d", rc);
     261#endif
    262262
    263263        rc = x861_TestFPUInstr1();
  • trunk/src/VBox/VMM/testcase/tstX86-1A.asm

    r40209 r40242  
    107107g_r80_QNaN:     dt 07fffc000000000000000h
    108108g_r80_QNaNMax:  dt 07fffffffffffffffffffh
     109g_r80_NegQNaN:  dt 0ffffc000000000000000h
    109110g_r80_SNaN:     dt 07fff8000000000000001h
    110111g_r80_SNaNMax:  dt 07fffbfffffffffffffffh
     
    30633064        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
    30643065        FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
    3065 %endif
    30663066
    30673067        ;
     
    31153115        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2)
    31163116        FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1)
     3117%endif
     3118
     3119        ;
     3120        ; FPTAN - calc, store ST0, push 1.0.
     3121        ;
     3122        SetSubTest "FPTAN"
     3123
     3124        ; ## Normal operation. ##
     3125        fninit
     3126        fldpi
     3127        FpuCheckOpcodeCsIp     { fptan }
     3128        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One)
     3129        FxSaveCheckStNValue xSP, 1, 0x00000000, 0x80000000, 0x3fbf ; should be zero, so, this might fail due to precision later.
     3130
     3131        ; Masked stack underflow - two QNaNs.
     3132        fninit
     3133        FpuCheckOpcodeCsIp     { fptan }
     3134        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
     3135        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
     3136
     3137        ; Masked stack overflow - two QNaNs
     3138        fninit
     3139        fldpi
     3140        fldpi
     3141        fldpi
     3142        fldpi
     3143        fldpi
     3144        fldpi
     3145        fldpi
     3146        fldpi
     3147        FpuCheckOpcodeCsIp     { fptan }
     3148        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN)
     3149        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN)
     3150
     3151        ;; @todo Finish FPTAN testcase.
     3152
    31173153
    31183154.success:
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette