VirtualBox

Changeset 40164 in vbox for trunk/src


Ignore:
Timestamp:
Feb 17, 2012 12:36:19 AM (13 years ago)
Author:
vboxsync
Message:

IEM: A bunch of r80 by r80 instructions, needed fsubrp stN,st0.

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

Legend:

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

    r40162 r40164  
    35613561
    35623562/**
     3563 * Pops one item off the FPU stack if no pending exception prevents it.
     3564 *
     3565 * @param   pCtx                The CPU context.
     3566 */
     3567static void iemFpuMaybePopOne(PCPUMCTX pCtx)
     3568{
     3569    /* Check pending exceptions. */
     3570    uint16_t uFSW = pCtx->fpu.FSW;
     3571    if (   (pCtx->fpu.FSW & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE))
     3572        & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM)))
     3573        return;
     3574
     3575    /* TOP--. */
     3576    uint16_t iOldTop = uFSW & X86_FSW_TOP_MASK;
     3577    uFSW &= ~X86_FSW_TOP_MASK;
     3578    uFSW |= (iOldTop + (UINT16_C(9) << X86_FSW_TOP_SHIFT)) & X86_FSW_TOP_MASK;
     3579    pCtx->fpu.FSW = uFSW;
     3580
     3581    /* Mark the previous ST0 as empty. */
     3582    iOldTop >>= X86_FSW_TOP_SHIFT;
     3583    pCtx->fpu.FTW &= ~RT_BIT(iOldTop);
     3584
     3585    /* Rotate the registers. */
     3586    iemFpuRotateStackPop(pCtx);
     3587}
     3588
     3589
     3590/**
    35633591 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, and
    35643592 * FOP.
     
    35783606
    35793607/**
    3580  * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, FOP,
    3581  * FPUDP, and FPUDS.
     3608 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, and
     3609 * FOP, and then pops the stack.
    35823610 *
    35833611 * @param   pIemCpu             The IEM per CPU data.
     
    35863614 * @param   pCtx                The CPU context.
    35873615 */
     3616static void iemFpuStoreResultThenPop(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iStReg)
     3617{
     3618    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3619    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
     3620    iemFpuStoreResultOnly(pIemCpu, pResult, iStReg, pCtx);
     3621    iemFpuMaybePopOne(pCtx);
     3622}
     3623
     3624
     3625/**
     3626 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, FOP,
     3627 * FPUDP, and FPUDS.
     3628 *
     3629 * @param   pIemCpu             The IEM per CPU data.
     3630 * @param   pResult             The result to store.
     3631 * @param   iStReg              Which FPU register to store it in.
     3632 * @param   pCtx                The CPU context.
     3633 */
    35883634static void iemFpuStoreResultWithMemOp(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iStReg, uint8_t iEffSeg, RTGCPTR GCPtrEff)
    35893635{
     
    35923638    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
    35933639    iemFpuStoreResultOnly(pIemCpu, pResult, iStReg, pCtx);
     3640}
     3641
     3642
     3643/**
     3644 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, FOP,
     3645 * FPUDP, and FPUDS, and then pops the stack.
     3646 *
     3647 * @param   pIemCpu             The IEM per CPU data.
     3648 * @param   pResult             The result to store.
     3649 * @param   iStReg              Which FPU register to store it in.
     3650 * @param   pCtx                The CPU context.
     3651 */
     3652static void iemFpuStoreResultWithMemOpThenPop(PIEMCPU pIemCpu, PIEMFPURESULT pResult,
     3653                                              uint8_t iStReg, uint8_t iEffSeg, RTGCPTR GCPtrEff)
     3654{
     3655    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3656    iemFpuUpdateDP(pIemCpu, pIemCpu->CTX_SUFF(pCtx), iEffSeg, GCPtrEff);
     3657    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
     3658    iemFpuStoreResultOnly(pIemCpu, pResult, iStReg, pCtx);
     3659    iemFpuMaybePopOne(pCtx);
    35943660}
    35953661
     
    36313697}
    36323698
     3699
     3700DECL_NO_INLINE(static, void) iemFpuStackUnderflowThenPop(PIEMCPU pIemCpu, uint8_t iStReg)
     3701{
     3702    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3703    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
     3704    iemFpuStackUnderflowOnly(pIemCpu, iStReg, pCtx);
     3705    iemFpuMaybePopOne(pCtx);
     3706}
     3707
     3708
     3709DECL_NO_INLINE(static, void)
     3710iemFpuStackUnderflowWithMemOpThenPop(PIEMCPU pIemCpu, uint8_t iStReg, uint8_t iEffSeg, RTGCPTR GCPtrEff)
     3711{
     3712    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3713    iemFpuUpdateDP(pIemCpu, pIemCpu->CTX_SUFF(pCtx), iEffSeg, GCPtrEff);
     3714    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
     3715    iemFpuStackUnderflowOnly(pIemCpu, iStReg, pCtx);
     3716    iemFpuMaybePopOne(pCtx);
     3717}
     3718
     3719
    36333720static int iemFpuStRegNonEmptyRef(PIEMCPU pIemCpu, uint8_t iStReg, PCRTFLOAT80U *ppRef)
    36343721{
     
    36383725    {
    36393726        *ppRef = &pCtx->fpu.aRegs[iStReg].r80;
     3727        return VINF_SUCCESS;
     3728    }
     3729    return VERR_NOT_FOUND;
     3730}
     3731
     3732
     3733static int iemFpu2StRegsNonEmptyRef(PIEMCPU pIemCpu, uint8_t iStReg0, PCRTFLOAT80U *ppRef0,
     3734                                    uint8_t iStReg1, PCRTFLOAT80U *ppRef1)
     3735{
     3736    PCPUMCTX pCtx  = pIemCpu->CTX_SUFF(pCtx);
     3737    uint16_t iTop  = X86_FSW_TOP_GET(pCtx->fpu.FSW);
     3738    uint16_t iReg0 = (iTop + iStReg0) & X86_FSW_TOP_SMASK;
     3739    uint16_t iReg1 = (iTop + iStReg1) & X86_FSW_TOP_SMASK;
     3740    if ((pCtx->fpu.FTW & (RT_BIT(iReg0) | RT_BIT(iReg1))) == (RT_BIT(iReg0) | RT_BIT(iReg1)))
     3741    {
     3742        *ppRef0 = &pCtx->fpu.aRegs[iStReg0].r80;
     3743        *ppRef1 = &pCtx->fpu.aRegs[iStReg1].r80;
    36403744        return VINF_SUCCESS;
    36413745    }
     
    58125916#define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) \
    58135917    iemFpuStoreResult(pIemCpu, &a_FpuData, a_iStReg)
     5918/** Stores FPU result in a stack register and pops the stack. */
     5919#define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg) \
     5920    iemFpuStoreResultThenPop(pIemCpu, &a_FpuData, a_iStReg)
    58145921/** Stores FPU result in a stack register and sets the FPUDP. */
    58155922#define IEM_MC_STORE_FPU_RESULT_MEM_OP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) \
    58165923    iemFpuStoreResultWithMemOp(pIemCpu, &a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff)
     5924/** Stores FPU result in a stack register, sets the FPUDP, and pops the
     5925 *  stack. */
     5926#define IEM_MC_STORE_FPU_RESULT_WITH_MEM_OP_THEN_POP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) \
     5927    iemFpuStoreResultWithMemOpThenPop(pIemCpu, &a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff)
    58175928
    58185929/** Raises a FPU stack underflow. Sets FPUIP, FPUCS and FOP. */
    5819 #define IEM_MC_FPU_STACK_UNDERFLOW(a_iSt) \
    5820     iemFpuStackUnderflow(pIemCpu, a_iSt)
     5930#define IEM_MC_FPU_STACK_UNDERFLOW(a_iStDst) \
     5931    iemFpuStackUnderflow(pIemCpu, a_iStDst)
     5932/** Raises a FPU stack underflow. Sets FPUIP, FPUCS and FOP. Pops stack. */
     5933#define IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(a_iStDst) \
     5934    iemFpuStackUnderflowThenPop(pIemCpu, a_iStDst)
    58215935/** Raises a FPU stack underflow. Sets FPUIP, FPUCS, FOP, FPUDP and FPUDS. */
    5822 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iSt, a_iEffSeg, a_GCPtrEff) \
    5823     iemFpuStackUnderflowWithMemOp(pIemCpu, a_iSt, a_iEffSeg, a_GCPtrEff)
     5936#define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iStDst, a_iEffSeg, a_GCPtrEff) \
     5937    iemFpuStackUnderflowWithMemOp(pIemCpu, a_iStDst, a_iEffSeg, a_GCPtrEff)
     5938/** Raises a FPU stack underflow. Sets FPUIP, FPUCS, FOP, FPUDP and FPUDS.
     5939 *  Pops stack. */
     5940#define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStDst, a_iEffSeg, a_GCPtrEff) \
     5941    iemFpuStackUnderflowWithMemOpThenPop(pIemCpu, a_iStDst, a_iEffSeg, a_GCPtrEff)
    58245942
    58255943
     
    58675985#define IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(a_pr80Dst, a_iSt) \
    58685986    if (iemFpuStRegNonEmptyRef(pIemCpu, (a_iSt), &(a_pr80Dst)) == VINF_SUCCESS) {
     5987#define IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(a_pr80Dst0, a_iSt0, a_pr80Dst1, a_iSt1) \
     5988    if (iemFpu2StRegsNonEmptyRef(pIemCpu, (a_iSt0), &(a_pr80Dst0), (a_iSt1), &(a_pr80Dst1)) == VINF_SUCCESS) {
    58695989
    58705990#define IEM_MC_ELSE()                                   } else {
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm

    r40163 r40164  
    13751375; @param    A0      FPU context (fxsave).
    13761376; @param    A1      Pointer to a IEMFPURESULT for the output.
    1377 ; @param    A2      Pointer to the 80-bit dividend.
    1378 ; @param    A3      Pointer to the 64-bit divisor.
     1377; @param    A2      Pointer to the 80-bit value.
     1378; @param    A3      Pointer to the 64-bit value.
    13791379;
    13801380%macro IEMIMPL_FPU_R80_BY_R64 1
     
    14051405IEMIMPL_FPU_R80_BY_R64 fdivr
    14061406
     1407
     1408;;
     1409; FPU instruction working on two 80-bit floating point values.
     1410;
     1411; @param    1       The instruction
     1412;
     1413; @param    A0      FPU context (fxsave).
     1414; @param    A1      Pointer to a IEMFPURESULT for the output.
     1415; @param    A2      Pointer to the first 80-bit value.
     1416; @param    A3      Pointer to the second 80-bit value.
     1417;
     1418%macro IEMIMPL_FPU_R80_BY_R80 1
     1419BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16
     1420        PROLOGUE_4_ARGS
     1421        sub     xSP, 20h
     1422
     1423        fninit
     1424        fld     tword [A3]
     1425        fld     tword [A2]
     1426        FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0
     1427        %1      st0, st1
     1428
     1429        fnstsw  word  [A1 + IEMFPURESULT.FSW]
     1430        fnclex
     1431        fstp    tword [A1 + IEMFPURESULT.r80Result]
     1432
     1433        add     xSP, 20h
     1434        EPILOGUE_4_ARGS 8
     1435ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80
     1436%endmacro
     1437
     1438IEMIMPL_FPU_R80_BY_R80 fadd
     1439IEMIMPL_FPU_R80_BY_R80 fmul
     1440IEMIMPL_FPU_R80_BY_R80 fsub
     1441IEMIMPL_FPU_R80_BY_R80 fsubr
     1442IEMIMPL_FPU_R80_BY_R80 fdiv
     1443IEMIMPL_FPU_R80_BY_R80 fdivr
     1444IEMIMPL_FPU_R80_BY_R80 fcom
     1445IEMIMPL_FPU_R80_BY_R80 fucom
     1446
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h

    r40163 r40164  
    1025510255
    1025610256
     10257/**
     10258 * Common worker for FPU instructions working on ST0 and STn, and storing the
     10259 * result in ST0.
     10260 *
     10261 * @param   pfnAImpl    Pointer to the instruction implementation (assembly).
     10262 */
     10263FNIEMOP_DEF_2(iemOpHlpFpu_st0_stN, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl)
     10264{
     10265    IEMOP_HLP_NO_LOCK_PREFIX();
     10266
     10267    IEM_MC_BEGIN(3, 1);
     10268    IEM_MC_LOCAL(IEMFPURESULT,          FpuRes);
     10269    IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes,        FpuRes,     0);
     10270    IEM_MC_ARG(PCRTFLOAT80U,            pr80Value1,                 1);
     10271    IEM_MC_ARG(PCRTFLOAT80U,            pr80Value2,                 2);
     10272
     10273    IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
     10274    IEM_MC_MAYBE_RAISE_FPU_XCPT();
     10275    IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, bRm & X86_MODRM_RM_MASK)
     10276        IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2);
     10277        IEM_MC_STORE_FPU_RESULT(FpuRes, 0);
     10278    IEM_MC_ELSE()
     10279        IEM_MC_FPU_STACK_UNDERFLOW(0);
     10280    IEM_MC_ENDIF();
     10281    IEM_MC_ADVANCE_RIP();
     10282
     10283    IEM_MC_END();
     10284    return VINF_SUCCESS;
     10285}
     10286
     10287
    1025710288/** Opcode 0xd8 11/0. */
    10258 FNIEMOP_STUB_1(iemOp_fadd_stN,   uint8_t, bRm);
     10289FNIEMOP_DEF_1(iemOp_fadd_stN,   uint8_t, bRm)
     10290{
     10291    IEMOP_MNEMONIC("fadd st0,stN");
     10292    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fadd_r80_by_r80);
     10293}
     10294
    1025910295
    1026010296/** Opcode 0xd8 11/1. */
    10261 FNIEMOP_STUB_1(iemOp_fmul_stN,   uint8_t, bRm);
     10297FNIEMOP_DEF_1(iemOp_fmul_stN,   uint8_t, bRm)
     10298{
     10299    IEMOP_MNEMONIC("fmul st0,stN");
     10300    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fmul_r80_by_r80);
     10301}
     10302
    1026210303
    1026310304/** Opcode 0xd8 11/2. */
    10264 FNIEMOP_STUB_1(iemOp_fcom_stN,   uint8_t, bRm);
     10305FNIEMOP_DEF_1(iemOp_fcom_stN,   uint8_t, bRm)
     10306{
     10307    IEMOP_MNEMONIC(" st0,stN");
     10308    /** @todo No need to store ST0! */
     10309    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fcom_r80_by_r80);
     10310}
     10311
    1026510312
    1026610313/** Opcode 0xd8 11/3. */
     
    1026810315
    1026910316/** Opcode 0xd8 11/4. */
    10270 FNIEMOP_STUB_1(iemOp_fsub_stN,   uint8_t, bRm);
     10317FNIEMOP_DEF_1(iemOp_fsub_stN,   uint8_t, bRm)
     10318{
     10319    IEMOP_MNEMONIC("fsub st0,stN");
     10320    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fsub_r80_by_r80);
     10321}
     10322
    1027110323
    1027210324/** Opcode 0xd8 11/5. */
    10273 FNIEMOP_STUB_1(iemOp_fsubr_stN,  uint8_t, bRm);
     10325FNIEMOP_DEF_1(iemOp_fsubr_stN,  uint8_t, bRm)
     10326{
     10327    IEMOP_MNEMONIC("fsubr st0,stN");
     10328    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fsubr_r80_by_r80);
     10329}
     10330
    1027410331
    1027510332/** Opcode 0xd8 11/6. */
    10276 FNIEMOP_STUB_1(iemOp_fdiv_stN,   uint8_t, bRm);
     10333FNIEMOP_DEF_1(iemOp_fdiv_stN,   uint8_t, bRm)
     10334{
     10335    IEMOP_MNEMONIC("fdiv st0,stN");
     10336    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fdiv_r80_by_r80);
     10337}
     10338
    1027710339
    1027810340/** Opcode 0xd8 11/7. */
    10279 FNIEMOP_STUB_1(iemOp_fdivr_stN,  uint8_t, bRm);
     10341FNIEMOP_DEF_1(iemOp_fdivr_stN,  uint8_t, bRm)
     10342{
     10343    IEMOP_MNEMONIC("fdivr st0,stN");
     10344    return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fdivr_r80_by_r80);
     10345}
     10346
    1028010347
    1028110348/** Opcode 0xd8 !11/0. */
     
    1081110878 * memory operand, and storing the result in ST0.
    1081210879 *
    10813  * @param   pImpl       Pointer to the instruction implementation (assembly).
     10880 * @param   pfnAImpl    Pointer to the instruction implementation (assembly).
    1081410881 */
    1081510882FNIEMOP_DEF_2(iemOpHlpFpu_ST0_m64r, uint8_t, bRm, PFNIEMAIMPLFPUR64, pfnImpl)
     
    1103411101
    1103511102
     11103/**
     11104 * Common worker for FPU instructions working on STn and ST0, storing the result
     11105 * in STn, and poping the stack unless IE, DE or ZE was raised.
     11106 *
     11107 * @param   pfnAImpl    Pointer to the instruction implementation (assembly).
     11108 */
     11109FNIEMOP_DEF_2(iemOpHlpFpu_stN_st0_pop, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl)
     11110{
     11111    IEMOP_HLP_NO_LOCK_PREFIX();
     11112
     11113    IEM_MC_BEGIN(3, 1);
     11114    IEM_MC_LOCAL(IEMFPURESULT,          FpuRes);
     11115    IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes,        FpuRes,     0);
     11116    IEM_MC_ARG(PCRTFLOAT80U,            pr80Value1,                 1);
     11117    IEM_MC_ARG(PCRTFLOAT80U,            pr80Value2,                 2);
     11118
     11119    IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
     11120    IEM_MC_MAYBE_RAISE_FPU_XCPT();
     11121    IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, bRm & X86_MODRM_RM_MASK, pr80Value2, 0)
     11122        IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2);
     11123        IEM_MC_STORE_FPU_RESULT_THEN_POP(FpuRes, bRm & X86_MODRM_RM_MASK);
     11124    IEM_MC_ELSE()
     11125        IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(bRm & X86_MODRM_RM_MASK);
     11126    IEM_MC_ENDIF();
     11127    IEM_MC_ADVANCE_RIP();
     11128
     11129    IEM_MC_END();
     11130    return VINF_SUCCESS;
     11131}
     11132
     11133
    1103611134/** Opcode 0xde 11/0. */
    11037 FNIEMOP_STUB_1(iemOp_faddp_stN_st0, uint8_t, bRm);
     11135FNIEMOP_DEF_1(iemOp_faddp_stN_st0, uint8_t, bRm)
     11136{
     11137    IEMOP_MNEMONIC("faddp stN,st0");
     11138    return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fadd_r80_by_r80);
     11139}
     11140
    1103811141
    1103911142/** Opcode 0xde 11/0. */
    11040 FNIEMOP_STUB_1(iemOp_fmulp_stN_st0, uint8_t, bRm);
     11143FNIEMOP_DEF_1(iemOp_fmulp_stN_st0, uint8_t, bRm)
     11144{
     11145    IEMOP_MNEMONIC("fmulp stN,st0");
     11146    return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fmul_r80_by_r80);
     11147}
     11148
    1104111149
    1104211150/** Opcode 0xde 0xd9. */
    1104311151FNIEMOP_STUB(iemOp_fcompp);
    1104411152
     11153
    1104511154/** Opcode 0xde 11/4. */
    11046 FNIEMOP_STUB_1(iemOp_fsubrp_stN_st0, uint8_t, bRm);
     11155FNIEMOP_DEF_1(iemOp_fsubrp_stN_st0, uint8_t, bRm)
     11156{
     11157    IEMOP_MNEMONIC("fsubrp stN,st0");
     11158    return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fsubr_r80_by_r80);
     11159}
     11160
    1104711161
    1104811162/** Opcode 0xde 11/5. */
    11049 FNIEMOP_STUB_1(iemOp_fsubp_stN_st0, uint8_t, bRm);
     11163FNIEMOP_DEF_1(iemOp_fsubp_stN_st0, uint8_t, bRm)
     11164{
     11165    IEMOP_MNEMONIC("fsubp stN,st0");
     11166    return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fsub_r80_by_r80);
     11167}
     11168
    1105011169
    1105111170/** Opcode 0xde 11/6. */
    11052 FNIEMOP_STUB_1(iemOp_fdivrp_stN_st0, uint8_t, bRm);
     11171FNIEMOP_DEF_1(iemOp_fdivrp_stN_st0, uint8_t, bRm)
     11172{
     11173    IEMOP_MNEMONIC("fdivrp stN,st0");
     11174    return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fdivr_r80_by_r80);
     11175}
     11176
    1105311177
    1105411178/** Opcode 0xde 11/7. */
    11055 FNIEMOP_STUB_1(iemOp_fdivp_stN_st0, uint8_t, bRm);
     11179FNIEMOP_DEF_1(iemOp_fdivp_stN_st0, uint8_t, bRm)
     11180{
     11181    IEMOP_MNEMONIC("fdivp stN,st0");
     11182    return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fdiv_r80_by_r80);
     11183}
     11184
    1105611185
    1105711186/** Opcode 0xde !11/0. */
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r40163 r40164  
    734734/** @} */
    735735
     736/** @name FPU operations taking a 80-bit float argument
     737 * @{ */
     738typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR80,(PCX86FXSTATE pFpuState, PIEMFPURESULT pFpuRes,
     739                                                   PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2));
     740typedef FNIEMAIMPLFPUR80  *PFNIEMAIMPLFPUR80;
     741FNIEMAIMPLFPUR80  iemAImpl_fadd_r80_by_r80;
     742FNIEMAIMPLFPUR80  iemAImpl_fmul_r80_by_r80;
     743FNIEMAIMPLFPUR80  iemAImpl_fcom_r80_by_r80;
     744FNIEMAIMPLFPUR80  iemAImpl_fsub_r80_by_r80;
     745FNIEMAIMPLFPUR80  iemAImpl_fsubr_r80_by_r80;
     746FNIEMAIMPLFPUR80  iemAImpl_fdiv_r80_by_r80;
     747FNIEMAIMPLFPUR80  iemAImpl_fdivr_r80_by_r80;
     748
     749/** @} */
     750
    736751
    737752/** @name Function tables.
  • trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp

    r40163 r40164  
    405405#define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0)
    406406#define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg)                    do { } while (0)
    407 #define IEM_MC_STORE_FPU_RESULT_MEM_OP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff)  do { } while (0)
    408 #define IEM_MC_FPU_STACK_UNDERFLOW(a_iStReg)                            do { } while (0)
    409 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0)
     407#define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg)           do { } while (0)
     408#define IEM_MC_STORE_FPU_RESULT_MEM_OP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff)              do { } while (0)
     409#define IEM_MC_STORE_FPU_RESULT_MEM_OP_THEN_POP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff)     do { } while (0)
     410#define IEM_MC_FPU_STACK_UNDERFLOW(a_iStReg)                                                    do { } while (0)
     411#define IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(a_iStReg)                                           do { } while (0)
     412#define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iStReg, a_iEffSeg, a_GCPtrEff)                      do { } while (0)
     413#define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStReg, a_iEffSeg, a_GCPtrEff)             do { } while (0)
    410414
    411415#define IEM_MC_IF_EFL_BIT_SET(a_fBit)                                   if (g_fRandom) {
     
    429433#define IEM_MC_IF_GREG_BIT_SET(a_iGReg, a_iBitNo)                       if (g_fRandom) {
    430434#define IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(a_pr80Dst, a_iSt)            if (g_fRandom) {
     435#define IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(p0, i0, p1, i1)         if (g_fRandom) {
    431436#define IEM_MC_ELSE()                                                   } else {
    432437#define IEM_MC_ENDIF()                                                  } do {} while (0)
     
    441446#define iemAImpl_fdiv_r80_by_r64        NULL
    442447#define iemAImpl_fdivr_r80_by_r64       NULL
     448
     449#define iemAImpl_fadd_r80_by_r80        NULL
     450#define iemAImpl_fmul_r80_by_r80        NULL
     451#define iemAImpl_fcom_r80_by_r80        NULL
     452#define iemAImpl_fsub_r80_by_r80        NULL
     453#define iemAImpl_fsubr_r80_by_r80       NULL
     454#define iemAImpl_fdiv_r80_by_r80        NULL
     455#define iemAImpl_fdivr_r80_by_r80       NULL
    443456
    444457
  • trunk/src/VBox/VMM/testcase/tstX86-1A.asm

    r40160 r40164  
    105105g_r80_Max:      dt 07ffeffffffffffffffffh
    106106g_r80_Inf:      dt 07fff8000000000000000h
     107g_r80_DnMin:    dt 000000000000000000001h
     108g_r80_DnMax:    dt 000007fffffffffffffffh
    107109
    108110g_r32V1:        dd 3.2
     
    324326
    325327;;
    326 ; Checks that ST0 in a FXSAVE image has a certain value (empty or not
     328; Checks that STn in a FXSAVE image has a certain value (empty or not
    327329; is ignored).
     330;
     331; @uses         eax
     332; @param        1       Address expression for the FXSAVE image.
     333; @param        2       The register number.
     334; @param        3       First dword of value.
     335; @param        4       Second dword of value.
     336; @param        5       Final word of value.
     337;
     338%macro FxSaveCheckStNValueEx 5
     339        cmp     dword [%1 + X86FXSTATE.st0 + %2 * 16], %3
     340        je      %%ok1
     341%%bad:
     342        mov     eax, 40000000 + __LINE__
     343        jmp     .return
     344%%ok1:
     345        cmp     dword [%1 + X86FXSTATE.st0 + %2 * 16 + 4], %4
     346        jne     %%bad
     347        cmp     word  [%1 + X86FXSTATE.st0 + %2 * 16 + 8], %5
     348        jne     %%bad
     349%endmacro
     350
     351
     352;;
     353; Checks if STn in a FXSAVE image has the same value as the specified
     354; floating point (80-bit) constant.
     355;
     356; @uses         eax, xDX
     357; @param        1       Address expression for the FXSAVE image.
     358; @param        2       The register number.
     359; @param        3       The address expression of the constant.
     360;
     361%macro FxSaveCheckStNValueConstEx 3
     362        mov     eax, [%3]
     363        cmp     dword [%1 + X86FXSTATE.st0 + %2 * 16], eax
     364        je      %%ok1
     365%%bad:
     366        mov     eax, 40000000 + __LINE__
     367        jmp     .return
     368%%ok1:
     369        mov     eax, [4 + %3]
     370        cmp     dword [%1 + X86FXSTATE.st0 + %2 * 16 + 4], eax
     371        jne     %%bad
     372        mov     ax, [8 + %3]
     373        cmp     word  [%1 + X86FXSTATE.st0 + %2 * 16 + 8], ax
     374        jne     %%bad
     375%endmacro
     376
     377
     378;;
     379; Checks that ST0 in a FXSAVE image has a certain value.
    328380;
    329381; @uses         eax
     
    333385; @param        4       Final word of value.
    334386;
    335 %macro FxSaveCheckSt0ValueEx 4
    336         cmp     dword [%1 + X86FXSTATE.st0], %2
    337         je      %%ok1
    338 %%bad:
    339         mov     eax, 40000000 + __LINE__
    340         jmp     .return
    341 %%ok1:
    342         cmp     dword [%1 + X86FXSTATE.st0 + 4], %3
    343         jne     %%bad
    344         cmp     word  [%1 + X86FXSTATE.st0 + 8], %4
    345         jne     %%bad
     387%macro FxSaveCheckSt0Value 4
     388        FxSaveCheckSt0NonEmpty %1
     389        FxSaveCheckStNValueEx %1, 0, %2, %3, %4
    346390%endmacro
    347391
    348392
    349393;;
    350 ; Checks if ST0 in a FXSAVE image has the same value as the specified
    351 ; floating point (80-bit) constant.
    352 ;
    353 ; @uses         eax, xDX
    354 ; @param        1       Address expression for the FXSAVE image.
    355 ; @param        2       The address expression of the constant.
    356 ;
    357 %macro FxSaveCheckSt0ValueConstEx 2
    358         mov     eax, [%2]
    359         cmp     dword [%1 + X86FXSTATE.st0], eax
    360         je      %%ok1
    361 %%bad:
    362         mov     eax, 40000000 + __LINE__
    363         jmp     .return
    364 %%ok1:
    365         mov     eax, [4 + %2]
    366         cmp     dword [%1 + X86FXSTATE.st0 + 4], eax
    367         jne     %%bad
    368         mov     ax, [8 + %2]
    369         cmp     word  [%1 + X86FXSTATE.st0 + 8], ax
    370         jne     %%bad
    371 %endmacro
    372 
    373 
    374 ;;
    375 ; Checks that ST0 in a FXSAVE image has a certain value.
     394; Checks that ST0 in a FXSAVE image is empty and that the value stored is the
     395; init value set by FpuInitWithCW.
    376396;
    377397; @uses         eax
    378398; @param        1       Address expression for the FXSAVE image.
    379 ; @param        2       First dword of value.
    380 ; @param        3       Second dword of value.
    381 ; @param        4       Final word of value.
    382 ;
    383 %macro FxSaveCheckSt0Value 4
    384         FxSaveCheckSt0NonEmpty %1
    385         FxSaveCheckSt0ValueEx %1, %2, %3, %4
    386 %endmacro
    387 
    388 
    389 ;;
    390 ; Checks that ST0 in a FXSAVE image is empty and that the value stored is the
    391 ; init value set by FpuInitWithCW.
    392 ;
    393 ; @uses         eax
    394 ; @param        1       Address expression for the FXSAVE image.
    395399;
    396400%macro FxSaveCheckSt0EmptyInitValue 1
    397401        FxSaveCheckSt0Empty %1
    398         FxSaveCheckSt0ValueEx %1, 0x40404040, 0x40404040, 0xffff
     402        FxSaveCheckStNValueEx %1, 0, 0x40404040, 0x40404040, 0xffff
    399403%endmacro
    400404
     
    408412%macro FxSaveCheckSt0ValueConst 2
    409413        FxSaveCheckSt0NonEmpty %1
    410         FxSaveCheckSt0ValueConstEx %1, %2
     414        FxSaveCheckStNValueConstEx %1, 0, %2
    411415%endmacro
    412416
     
    419423;; Checks that ST0 contains 3 & 1/3.
    420424%define FxSaveCheckSt0Value_3_and_two_3rds(p)    FxSaveCheckSt0Value p, 0xaaaaaaab, 0xeaaaaaaa, 0x4000
     425
     426
     427
     428;;
     429; Checks that STn is empty in an FXSAVE image.
     430;
     431; @uses         eax
     432; @param        1       Address expression for the FXSAVE image.
     433; @param        2       The register number.
     434;
     435%macro FxSaveCheckStNEmpty 2
     436        movzx   eax, word [%1 + X86FXSTATE.FSW]
     437        and     eax, X86_FSW_TOP_MASK
     438        shr     eax, X86_FSW_TOP_SHIFT
     439        add     eax, %2
     440        and     eax, X86_FSW_TOP_SMASK
     441        bt      [%1 + X86FXSTATE.FTW], eax
     442        jnc     %%ok
     443        mov     eax, 20000000 + __LINE__
     444        jmp     .return
     445%%ok:
     446%endmacro
     447
     448
     449;;
     450; Checks that STn is not-empty in an FXSAVE image.
     451;
     452; @uses         eax
     453; @param        1       Address expression for the FXSAVE image.
     454; @param        2       The register number.
     455;
     456%macro FxSaveCheckStNNonEmpty 2
     457        movzx   eax, word [%1 + X86FXSTATE.FSW]
     458        and     eax, X86_FSW_TOP_MASK
     459        shr     eax, X86_FSW_TOP_SHIFT
     460        add     eax, %2
     461        and     eax, X86_FSW_TOP_SMASK
     462        bt      [%1 + X86FXSTATE.FTW], eax
     463        jc      %%ok
     464        mov     eax, 30000000 + __LINE__
     465        jmp     .return
     466%%ok:
     467%endmacro
     468
     469
     470;;
     471; Checks that STn in a FXSAVE image has a certain value.
     472;
     473; @uses         eax
     474; @param        1       Address expression for the FXSAVE image.
     475; @param        2       The register number.
     476; @param        3       First dword of value.
     477; @param        4       Second dword of value.
     478; @param        5       Final word of value.
     479;
     480%macro FxSaveCheckStNValue 5
     481        FxSaveCheckStNNonEmpty %1, %2
     482        FxSaveCheckStNValueEx %1, %2, %3, %4, %5
     483%endmacro
     484
     485;;
     486; Checks that ST0 in a FXSAVE image is non-empty and has the same value as the
     487; specified constant (80-bit).
     488;
     489; @uses         eax, xDX
     490; @param        1       Address expression for the FXSAVE image.
     491; @param        2       The register number.
     492; @param        3       The address expression of the constant.
     493%macro FxSaveCheckStNValueConst 3
     494        FxSaveCheckStNNonEmpty %1, %2
     495        FxSaveCheckStNValueConstEx %1, %2, %3
     496%endmacro
     497
     498;; Checks that ST0 contains QNaN.
     499%define FxSaveCheckStNValue_QNaN(p, iSt)            FxSaveCheckStNValue p, iSt, 0x00000000, 0xc0000000, 0xffff
     500;; Checks that ST0 contains +Inf.
     501%define FxSaveCheckStNValue_PlusInf(p, iSt)         FxSaveCheckStNValue p, iSt, 0x00000000, 0x80000000, 0x7fff
     502;; Checks that ST0 contains 3 & 1/3.
     503%define FxSaveCheckStNValue_3_and_a_3rd(p, iSt)     FxSaveCheckStNValue p, iSt, 0x55555555, 0xd5555555, 0x4000
     504;; Checks that ST0 contains 3 & 1/3.
     505%define FxSaveCheckStNValue_3_and_two_3rds(p, iSt)  FxSaveCheckStNValue p, iSt, 0xaaaaaaab, 0xeaaaaaaa, 0x4000
    421506
    422507
     
    23042389        ret
    23052390
     2391;;
     2392; Checks a FPU instruction, no memory operand.
     2393;
     2394; @uses xCX, xAX, Stack.
     2395;
     2396%macro FpuCheckOpcodeCsIp 1
     2397%%instruction:
     2398        %1
     2399        arch_fxsave  [xSP]
     2400        fnstenv [xSP + 512]             ; for the selectors (64-bit)
     2401        arch_fxrstor [xSP]              ; fnstenv screws up the ES bit.
     2402        lea     xCX, [REF(%%instruction)]
     2403        call    CheckOpcodeCsIp
     2404        jz      %%ok
     2405        or      eax, __LINE__
     2406        jmp     .return
     2407%%ok:
     2408%endmacro
     2409
     2410
     2411;;
     2412; Checks a trapping FPU instruction, no memory operand.
     2413;
     2414; Upon return, there is are two FXSAVE image on the stack at xSP.
     2415;
     2416; @uses xCX, xAX, Stack.
     2417;
     2418; @param    %1  The instruction.
     2419;
     2420%macro FpuTrapOpcodeCsIp 1
     2421%%instruction:
     2422        %1
     2423        fxsave [xSP + 1024 +512]        ; FPUDS and FPUCS for 64-bit hosts.
     2424                                        ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel)
     2425        arch_fxsave  [xSP]
     2426        fnstenv [xSP + 512]
     2427        arch_fxrstor [xSP]
     2428%%trap:
     2429        fwait
     2430%%trap_end:
     2431        mov     eax, __LINE__
     2432        jmp     .return
     2433BEGINDATA
     2434%%trapinfo: istruc TRAPINFO
     2435        at TRAPINFO.uTrapPC,    RTCCPTR_DEF     %%trap
     2436        at TRAPINFO.uResumePC,  RTCCPTR_DEF     %%resume
     2437        at TRAPINFO.u8TrapNo,   db              X86_XCPT_MF
     2438        at TRAPINFO.cbInstr,    db              (%%trap_end - %%trap)
     2439iend
     2440BEGINCODE
     2441%%resume:
     2442        lea     xCX, [REF(%%instruction)]
     2443        call    CheckOpcodeCsIp
     2444        jz      %%ok
     2445        or      eax, __LINE__
     2446        jmp     .return
     2447%%ok:
     2448%endmacro
    23062449
    23072450
     
    24052548        arch_fxsave  [xSP]
    24062549        fnstenv [xSP + 512]
    2407         arch_fxrstor [xSP]               
     2550        arch_fxrstor [xSP]
    24082551%%trap:
    24092552        fwait
     
    24682611        SAVE_ALL_PROLOGUE
    24692612        sub     xSP, 2048
    2470 
     2613%if 1
    24712614        ;
    24722615        ; FDIV with 64-bit floating point memory operand.
     
    24752618
    24762619        ; ## Normal operation. ##
     2620
    24772621        fninit
    24782622        FpuCheckOpcodeCsIpDsDp { fld  dword [REF(g_r32_3dot2)]     }, [REF(g_r32_3dot2)]
     
    24842628
    24852629        ; ## Masked exceptions. ##
     2630
    24862631        ; Masked stack underflow.
    24872632        fninit
     
    25472692
    25482693        ; ## Unmasked exceptions. ##
     2694
    25492695        ; Stack underflow - TOP and ST0 unmodified.
    25502696        FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
     
    26272773        mov     xBX, [REF_EXTERN(g_pbEfExecPage)]
    26282774        ShouldTrap X86_XCPT_MF, fdiv qword [xBX + PAGE_SIZE]
     2775%endif
     2776
     2777        ;
     2778        ; FSUBRP STn, ST0
     2779        ;
     2780        SetSubTest "FSUBRP STn, ST0"
     2781
     2782        ; ## Normal operation. ##
     2783        fninit
     2784        FpuCheckOpcodeCsIpDsDp { fld  dword [REF(g_r32_3dot2)]     }, [REF(g_r32_3dot2)]
     2785        FpuCheckOpcodeCsIpDsDp { fld  dword [REF(g_r32_3dot2)]     }, [REF(g_r32_3dot2)]
     2786        FpuCheckOpcodeCsIp     { fsubrp st1, st0 }
     2787        FxSaveCheckFSW xSP, 0, 0
     2788        FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero)
     2789
     2790        ; ## Masked exceptions. ##
     2791
     2792        ; Masked stack underflow, both operands.
     2793        fninit
     2794        FpuCheckOpcodeCsIp     { fsubrp st1, st0 }
     2795        FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
     2796        FxSaveCheckSt0Value_QNaN(xSP)
     2797
     2798        ; Masked stack underflow, one operand.
     2799        fninit
     2800        FpuCheckOpcodeCsIpDsDp { fld  dword [REF(g_r32_3dot2)]     }, [REF(g_r32_3dot2)]
     2801        FpuCheckOpcodeCsIp     { fsubrp st1, st0 }
     2802        FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
     2803        FxSaveCheckSt0Value_QNaN(xSP)
     2804
     2805        ; Denormal operand.
     2806        fninit
     2807        fld    tword [REF(g_r80_DnMax)]
     2808        fld    tword [REF(g_r80_DnMin)]
     2809        FpuCheckOpcodeCsIp     { fsubrp st1, st0 }
     2810        FxSaveCheckFSW xSP, X86_FSW_DE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
     2811        FxSaveCheckSt0Value xSP, 0xfffffffe, 0x7fffffff, 0x8000
     2812
     2813        ; ## Unmasked exceptions. ##
     2814
     2815        ; Stack underflow, both operands - no pop or change.
     2816        FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
     2817        FpuTrapOpcodeCsIp      { fsubrp st1, st0 }
     2818        FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
     2819        FxSaveCheckSt0EmptyInitValue xSP
     2820
     2821        ; Stack underflow, one operand - no pop or change.
     2822        FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST
     2823        FpuCheckOpcodeCsIpDsDp { fld  dword [REF(g_r32_3dot2)]     }, [REF(g_r32_3dot2)]
     2824        FpuTrapOpcodeCsIp      { fsubrp st1, st0 }
     2825        FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
     2826        FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2)
     2827
     2828        ; Denormal operand - no pop.
     2829        fninit
     2830        fld    tword [REF(g_r80_DnMax)]
     2831        fld    tword [REF(g_r80_DnMin)]
     2832        fnclex
     2833        mov     dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST
     2834        fldcw   [xSP]
     2835        FpuTrapOpcodeCsIp      { fsubrp st1, st0 }
     2836        FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3
     2837        FxSaveCheckStNValueConst xSP, 1, REF(g_r80_DnMax)
     2838        FxSaveCheckStNValueConst xSP, 0, REF(g_r80_DnMin)
     2839
    26292840
    26302841.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