VirtualBox

Changeset 40093 in vbox


Ignore:
Timestamp:
Feb 13, 2012 1:05:21 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
76233
Message:

IEM: fld m64i

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

Legend:

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

    r40077 r40093  
    32853285
    32863286/**
    3287  * Pushes a FPU result onto the FPU stack after inspecting the resulting
    3288  * statuses.
     3287 * Updates the FOP, FPU.CS and FPUIP registers.
     3288 *
     3289 * @param   pIemCpu             The IEM per CPU data.
     3290 * @param   pCtx                The CPU context.
     3291 */
     3292DECLINLINE(void) iemFpuUpdateOpcodeAndIP(PIEMCPU pIemCpu, PCPUMCTX pCtx)
     3293{
     3294    pCtx->fpu.FOP   = pIemCpu->abOpcode[pIemCpu->offFpuOpcode]
     3295                    | ((uint16_t)(pIemCpu->abOpcode[pIemCpu->offFpuOpcode - 1] & 0x7) << 8);
     3296    /** @todo FPU.CS and FPUIP needs to be kept seperately. */
     3297    pCtx->fpu.CS    = pCtx->cs;
     3298    pCtx->fpu.FPUIP = pCtx->rip;
     3299}
     3300
     3301
     3302/**
     3303 * Updates the FPU.DS and FPUDP registers.
     3304 *
     3305 * @param   pIemCpu             The IEM per CPU data.
     3306 * @param   pCtx                The CPU context.
     3307 * @param   iEffSeg             The effective segment register.
     3308 * @param   GCPtrEff            The effective address relative to @a iEffSeg.
     3309 */
     3310DECLINLINE(void) iemFpuUpdateDP(PIEMCPU pIemCpu, PCPUMCTX pCtx, uint8_t iEffSeg, RTGCPTR GCPtrEff)
     3311{
     3312    RTSEL sel;
     3313    switch (iEffSeg)
     3314    {
     3315        case X86_SREG_DS: sel = pCtx->ds; break;
     3316        case X86_SREG_SS: sel = pCtx->ss; break;
     3317        case X86_SREG_CS: sel = pCtx->cs; break;
     3318        case X86_SREG_ES: sel = pCtx->es; break;
     3319        case X86_SREG_FS: sel = pCtx->fs; break;
     3320        case X86_SREG_GS: sel = pCtx->gs; break;
     3321        default:
     3322            AssertMsgFailed(("%d\n", iEffSeg));
     3323            sel = pCtx->ds;
     3324    }
     3325    /** @todo FPU.DS and FPUDP needs to be kept seperately. */
     3326    pCtx->fpu.DS    = sel;
     3327    pCtx->fpu.FPUDP = GCPtrEff;
     3328}
     3329
     3330
     3331/**
     3332 * Rotates the stack registers in the push direction.
     3333 *
     3334 * @param   pCtx                The CPU context.
     3335 * @remarks This is a complete waste of time, but fxsave stores the registers in
     3336 *          stack order.
     3337 */
     3338DECLINLINE(void) iemFpuRotateStackPush(PCPUMCTX pCtx)
     3339{
     3340    RTFLOAT80U r80Tmp = pCtx->fpu.aRegs[7].r80;
     3341    pCtx->fpu.aRegs[7].r80 = pCtx->fpu.aRegs[6].r80;
     3342    pCtx->fpu.aRegs[6].r80 = pCtx->fpu.aRegs[5].r80;
     3343    pCtx->fpu.aRegs[5].r80 = pCtx->fpu.aRegs[4].r80;
     3344    pCtx->fpu.aRegs[4].r80 = pCtx->fpu.aRegs[3].r80;
     3345    pCtx->fpu.aRegs[3].r80 = pCtx->fpu.aRegs[2].r80;
     3346    pCtx->fpu.aRegs[2].r80 = pCtx->fpu.aRegs[1].r80;
     3347    pCtx->fpu.aRegs[1].r80 = pCtx->fpu.aRegs[0].r80;
     3348    pCtx->fpu.aRegs[0].r80 = r80Tmp;
     3349}
     3350
     3351
     3352/**
     3353 * Rotates the stack registers in the pop direction.
     3354 *
     3355 * @param   pCtx                The CPU context.
     3356 * @remarks This is a complete waste of time, but fxsave stores the registers in
     3357 *          stack order.
     3358 */
     3359DECLINLINE(void) iemFpuRotateStackPop(PCPUMCTX pCtx)
     3360{
     3361    RTFLOAT80U r80Tmp = pCtx->fpu.aRegs[0].r80;
     3362    pCtx->fpu.aRegs[0].r80 = pCtx->fpu.aRegs[1].r80;
     3363    pCtx->fpu.aRegs[1].r80 = pCtx->fpu.aRegs[2].r80;
     3364    pCtx->fpu.aRegs[2].r80 = pCtx->fpu.aRegs[3].r80;
     3365    pCtx->fpu.aRegs[3].r80 = pCtx->fpu.aRegs[4].r80;
     3366    pCtx->fpu.aRegs[4].r80 = pCtx->fpu.aRegs[5].r80;
     3367    pCtx->fpu.aRegs[5].r80 = pCtx->fpu.aRegs[6].r80;
     3368    pCtx->fpu.aRegs[6].r80 = pCtx->fpu.aRegs[7].r80;
     3369    pCtx->fpu.aRegs[7].r80 = r80Tmp;
     3370}
     3371
     3372
     3373#if 0
     3374/**
    32893375 *
    32903376 * @param   pIemCpu             The IEM per CPU data.
    32913377 * @param   pResult             The FPU operation result to push.
    3292  */
    3293 static void iemFpuPushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult)
     3378 * @param   pCtx                The CPU context.
     3379 * @param   iDstReg             The destination register,
     3380 * @param   cStackAdj           The stack adjustment on successful operation.
     3381 *                              Note that this is an unsigned value.
     3382 * @param   fFlags              Flags.
     3383 */
     3384static void iemFpuPushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, PCPUMCTX pCtx, uint16_t iDstReg,
     3385                             uint8_t cStackAdj, )
    32943386{
    32953387    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3388    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
    32963389
    32973390    uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK;
     
    33313424    }
    33323425
    3333     /* This is stupid, but we must now rotate the registers since they stored
    3334        in stack order. A complete waste of time! */
    3335     RTFLOAT80U r80Tmp = pCtx->fpu.aRegs[7].r80;
    3336     memmove(&pCtx->fpu.aRegs[1], &pCtx->fpu.aRegs[0], sizeof(pCtx->fpu.aRegs[0]) * 7);
    3337     pCtx->fpu.aRegs[0].r80 = r80Tmp;
    3338 }
    3339 
     3426    iemFpuRotateStackPush(pCtx);
     3427}
     3428
     3429
     3430/**
     3431 * Writes a FPU result to the FPU stack after inspecting the resulting
     3432 * statuses.
     3433 *
     3434 * @param   pIemCpu             The IEM per CPU data.
     3435 * @param   pResult             The FPU operation result to push.
     3436 * @param   iReg                The stack relative FPU register number.
     3437 */
     3438static void iemFpuStoreResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iReg)
     3439{
     3440    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3441    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
     3442
     3443    uint16_t iReg = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + iReg) & X86_FSW_TOP_SMASK;
     3444
     3445    uint16_t fXcpts = (pResult->FSW   & (X86_FSW_IE | X86_FSW_DE | X86_FSW_ZE | X86_FSW_OE | X86_FSW_UE | X86_FSW_PE))
     3446                    & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_DM | X86_FCW_ZM | X86_FCW_OM | X86_FCW_UM | X86_FCW_PM));
     3447    if (!fXcpts)
     3448    {
     3449        /* No unmasked exceptions, just store the result. */
     3450        pCtx->fpu.FSW &= X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3;
     3451        pCtx->fpu.FSW |= (pResult->FSW & ~(X86_FSW_TOP_MASK | X86_FSW_B | X86_FSW_ES));
     3452        pCtx->fpu.FTW |= RT_BIT(iNewTop);
     3453        pCtx->fpu.aRegs[7].r80 = pResult->r80Result;
     3454    }
     3455    else
     3456    {
     3457        AssertFailed();
     3458    }
     3459}
     3460#endif
     3461
     3462
     3463/**
     3464 * Pushes a FPU result onto the FPU stack after inspecting the resulting
     3465 * statuses.
     3466 *
     3467 * @param   pIemCpu             The IEM per CPU data.
     3468 * @param   pResult             The FPU operation result to push.
     3469 */
     3470static void iemFpuPushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult)
     3471{
     3472    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     3473    iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx);
     3474
     3475    uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK;
     3476    if (!(RT_BIT(iNewTop) & pCtx->fpu.FTW))
     3477    {
     3478        /* No stack error. */
     3479        uint16_t fXcpts = (pResult->FSW   & (X86_FSW_IE | X86_FSW_DE | X86_FSW_ZE | X86_FSW_OE | X86_FSW_UE | X86_FSW_PE))
     3480                        & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_DM | X86_FCW_ZM | X86_FCW_OM | X86_FCW_UM | X86_FCW_PM));
     3481        if (!fXcpts)
     3482        {
     3483            /* No unmasked exceptions, just store the result. */
     3484            pCtx->fpu.FSW &= X86_FSW_TOP_MASK | X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3;
     3485            pCtx->fpu.FSW |= (iNewTop << X86_FSW_TOP_SHIFT) | (pResult->FSW & ~(X86_FSW_TOP_MASK | X86_FSW_B | X86_FSW_ES));
     3486            pCtx->fpu.FTW |= RT_BIT(iNewTop);
     3487            pCtx->fpu.aRegs[7].r80 = pResult->r80Result;
     3488        }
     3489        else
     3490        {
     3491            AssertFailed();
     3492        }
     3493
     3494    }
     3495    else if (pCtx->fpu.FCW & X86_FCW_IM)
     3496    {
     3497        /* Masked stack overflow. */
     3498        pCtx->fpu.FSW &= X86_FSW_TOP_MASK | X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3;
     3499        pCtx->fpu.FSW |= (iNewTop << X86_FSW_TOP_SHIFT) | X86_FSW_C1 | X86_FSW_IE | X86_FSW_SF;
     3500        pCtx->fpu.FTW |= RT_BIT(iNewTop);
     3501        iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80);
     3502    }
     3503    else
     3504    {
     3505        /* Stack overflow exception. */
     3506        pCtx->fpu.FSW &= X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3;
     3507        pCtx->fpu.FSW |= X86_FSW_C1 | X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B;
     3508        return;
     3509    }
     3510
     3511    iemFpuRotateStackPush(pCtx);
     3512}
     3513
     3514
     3515/**
     3516 * Pushes a FPU result onto the FPU stack after inspecting the resulting
     3517 * statuses, and sets FPU.DS and FPUDP.
     3518 *
     3519 * @param   pIemCpu             The IEM per CPU data.
     3520 * @param   pResult             The FPU operation result to push.
     3521 * @param   iEffSeg             The effective segment register.
     3522 * @param   GCPtrEff            The effective address relative to @a iEffSeg.
     3523 */
     3524static void iemFpuPushResultWithMemOp(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iEffSeg, RTGCPTR GCPtrEff)
     3525{
     3526    iemFpuUpdateDP(pIemCpu, pIemCpu->CTX_SUFF(pCtx), iEffSeg, GCPtrEff);
     3527    iemFpuPushResult(pIemCpu, pResult);
     3528}
    33403529
    33413530/** @}  */
     
    52335422    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU32(pIemCpu, &(a_r32Dst).u32, (a_iSeg), (a_GCPtrMem)))
    52345423#define IEM_MC_FETCH_MEM_R64(a_r64Dst, a_iSeg, a_GCPtrMem) \
    5235     IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU64(pIemCpu, &(a_r64Dst).u64, (a_iSeg), (a_GCPtrMem)))
     5424    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU64(pIemCpu, &(a_r64Dst).au64[0], (a_iSeg), (a_GCPtrMem)))
    52365425#define IEM_MC_FETCH_MEM_R80(a_r80Dst, a_iSeg, a_GCPtrMem) \
    52375426    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataR80(pIemCpu, &(a_r64Dst), (a_iSeg), (a_GCPtrMem)))
     
    54825671    } while (0)
    54835672/** Pushes FPU result onto the stack. */
    5484 #define IEM_MC_PUSH_FPU_RESULT(a_FpuData) iemFpuPushResult(pIemCpu, &a_FpuData)
     5673#define IEM_MC_PUSH_FPU_RESULT(a_FpuData) \
     5674    iemFpuPushResult(pIemCpu, &a_FpuData)
     5675/** Pushes FPU result onto the stack and sets the FPUDP. */
     5676#define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) \
     5677    iemFpuPushResultWithMemOp(pIemCpu, &a_FpuData, a_iEffSeg, a_GCPtrEff)
    54855678
    54865679
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm

    r40077 r40093  
    13611361ENDPROC iemAImpl_fpu_r32_to_r80
    13621362
     1363
     1364;;
     1365; Converts a 64-bit floating point value to a 80-bit one (fpu register).
     1366;
     1367; @param    A0      FPU context (fxsave).
     1368; @param    A1      Pointer to a IEMFPURESULT for the output.
     1369; @param    A2      Pointer to the 32-bit floating point value to convert.
     1370;
     1371BEGINPROC_FASTCALL iemAImpl_fpu_r64_to_r80, 12
     1372        PROLOGUE_3_ARGS
     1373        sub     xSP, 20h
     1374
     1375        FPU_SAFE_INIT A0
     1376        fld     qword [A2]
     1377
     1378        fnstsw  word  [A1 + IEMFPURESULT.FSW]
     1379        fstp    tword [A1 + IEMFPURESULT.r80Result]
     1380
     1381        add     xSP, 20h
     1382        EPILOGUE_3_ARGS 0
     1383ENDPROC iemAImpl_fpu_r64_to_r80
     1384
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h

    r40092 r40093  
    1034210342
    1034310343
    10344 /** Opcode 0xd9 /0 mem32real */
     10344/** Opcode 0xd9 /0 mem32real
     10345 * @sa  iemOp_fld_m64r */
    1034510346FNIEMOP_DEF_1(iemOp_fld_m32r, uint8_t, bRm)
    1034610347{
     
    1036010361    IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fpu_r32_to_r80, pFpuRes, r32Val);
    1036110362
    10362     IEM_MC_PUSH_FPU_RESULT(FpuRes);
     10363    IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pIemCpu->iEffSeg, GCPtrEffSrc);
    1036310364    IEM_MC_ADVANCE_RIP();
    1036410365
     
    1082410825
    1082510826/** Opcode 0xdc !11/6. */
     10827#if 0
     10828FNIEMOP_DEF_1(iemOp_fdiv_m64r,  uint8_t, bRm)
     10829{
     10830    IEMOP_MNEMONIC("fdiv m64r");
     10831    IEMOP_HLP_NO_LOCK_PREFIX();
     10832
     10833    IEM_MC_BEGIN(2, 3);
     10834    IEM_MC_LOCAL(RTGCPTR,               GCPtrEffSrc);
     10835    IEM_MC_LOCAL(IEMFPURESULT,          FpuRes);
     10836    IEM_MC_LOCAL(RTFLOAT64U,            r64Val);
     10837    IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes,    FpuRes, 0);
     10838    IEM_MC_ARG_LOCAL_REF(PRTFLOAT64U,   pr64Val,    r64Val, 1);
     10839
     10840    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
     10841    IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
     10842    IEM_MC_MAYBE_RAISE_FPU_XCPT();
     10843    IEM_MC_FETCH_MEM_R64(r64Val, pIemCpu->iEffSeg, GCPtrEffSrc);
     10844    IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fpu_r64_to_r80, pFpuRes, pr64Val);
     10845
     10846    IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pIemCpu->iEffSeg, GCPtrEffSrc);
     10847    IEM_MC_ADVANCE_RIP();
     10848
     10849    IEM_MC_END();
     10850    return VINF_SUCCESS;
     10851}
     10852#else
    1082610853FNIEMOP_STUB_1(iemOp_fdiv_m64r,  uint8_t, bRm);
     10854#endif
    1082710855
    1082810856/** Opcode 0xdc !11/7. */
     
    1086810896
    1086910897
    10870 /** Opcode 0xdd !11/0. */
    10871 FNIEMOP_STUB_1(iemOp_fld_m64r,    uint8_t, bRm);
     10898/** Opcode 0xdd !11/0.
     10899 * @sa iemOp_fld_m32r */
     10900FNIEMOP_DEF_1(iemOp_fld_m64r,    uint8_t, bRm)
     10901{
     10902    IEMOP_MNEMONIC("fld m64r");
     10903    IEMOP_HLP_NO_LOCK_PREFIX();
     10904
     10905    IEM_MC_BEGIN(2, 3);
     10906    IEM_MC_LOCAL(RTGCPTR,               GCPtrEffSrc);
     10907    IEM_MC_LOCAL(IEMFPURESULT,          FpuRes);
     10908    IEM_MC_LOCAL(RTFLOAT64U,            r64Val);
     10909    IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes,    FpuRes, 0);
     10910    IEM_MC_ARG_LOCAL_REF(PRTFLOAT64U,   pr64Val,    r64Val, 1);
     10911
     10912    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
     10913    IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE();
     10914    IEM_MC_MAYBE_RAISE_FPU_XCPT();
     10915    IEM_MC_FETCH_MEM_R64(r64Val, pIemCpu->iEffSeg, GCPtrEffSrc);
     10916    IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fpu_r64_to_r80, pFpuRes, pr64Val);
     10917
     10918    IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pIemCpu->iEffSeg, GCPtrEffSrc);
     10919    IEM_MC_ADVANCE_RIP();
     10920
     10921    IEM_MC_END();
     10922    return VINF_SUCCESS;
     10923}
    1087210924
    1087310925/** Opcode 0xdd !11/0. */
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r40082 r40093  
    716716/** @} */
    717717
     718/** @name FPU operations taking a 64-bit float argument
     719 * @{ */
     720typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR64,(PCX86FXSTATE pFpuState, PIEMFPURESULT pFpuRes, PCRTFLOAT64U pr64Val));
     721typedef FNIEMAIMPLFPUR64  *PFNIEMAIMPLFPUR64;
     722FNIEMAIMPLFPUR64 iemAImpl_fpu_r64_to_r80;
     723/** @} */
     724
    718725
    719726/** @name Function tables.
  • trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp

    r40072 r40093  
    402402#define IEM_MC_CALL_FPU_AIMPL_2(a_pfnAImpl, a0, a1)                     do { } while (0)
    403403#define IEM_MC_PUSH_FPU_RESULT(a_FpuData)                               do { } while (0)
     404#define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0)
    404405
    405406#define IEM_MC_IF_EFL_BIT_SET(a_fBit)                                   if (g_fRandom) {
Note: See TracChangeset for help on using the changeset viewer.

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