VirtualBox

Changeset 40222 in vbox


Ignore:
Timestamp:
Feb 22, 2012 9:14:52 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
76399
Message:

IEM: Implemented fldcw, fldenv fnstcw and fnstenv.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/x86.h

    r40182 r40222  
    21632163/** Exception Mask: Precision.  */
    21642164#define X86_FCW_PM          RT_BIT(5)
    2165 /** Mask all exceptions.  */
     2165/** Mask all exceptions, the value typically loaded (by for instance fninit).
     2166 * @remarks This includes reserved bit 6.  */
    21662167#define X86_FCW_MASK_ALL    UINT16_C(0x007f)
     2168/** Mask all exceptions. Same as X86_FSW_XCPT_MASK. */
     2169#define X86_FCW_XCPT_MASK    UINT16_C(0x003f)
    21672170/** Precision control mask. */
    21682171#define X86_FCW_PC_MASK     UINT16_C(0x0300)
     
    21852188/** Rounding control: Towards zero. */
    21862189#define X86_FCW_RC_ZERO     UINT16_C(0x0c00)
     2190/** Bits which should be zero, apparently. */
     2191#define X86_FCW_ZERO_MASK   UINT16_C(0xf080)
    21872192/** @} */
    21882193
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r40209 r40222  
    28022802
    28032803/**
    2804  * Gets the FPU status word.
    2805  *
    2806  * @returns FPU status word
    2807  * @param   pIemCpu             The per CPU data.
    2808  */
    2809 static uint16_t iemFRegFetchFsw(PIEMCPU pIemCpu)
    2810 {
    2811     PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
    2812     uint16_t u16Fsw;
    2813     if (iemFRegIsFxSaveFormat(pIemCpu))
    2814         u16Fsw = pCtx->fpu.FSW;
    2815     else
    2816     {
    2817         PX86FPUSTATE pFpu = (PX86FPUSTATE)&pCtx->fpu;
    2818         u16Fsw = pFpu->FSW;
    2819     }
    2820     return u16Fsw;
    2821 }
    2822 
    2823 /**
    28242804 * Adds a 8-bit signed jump offset to RIP/EIP/IP.
    28252805 *
     
    33253305                    | ((uint16_t)(pIemCpu->abOpcode[pIemCpu->offFpuOpcode - 1] & 0x7) << 8);
    33263306    /** @todo FPU.CS and FPUIP needs to be kept seperately. */
    3327     pCtx->fpu.CS    = pCtx->cs;
    3328     pCtx->fpu.FPUIP = pCtx->rip;
     3307    if (IEM_IS_REAL_OR_V86_MODE(pIemCpu))
     3308    {
     3309        /** @todo Testcase: making assumptions about how FPUIP and FPUDP are handled
     3310         *        happens in real mode here based on the fnsave and fnstenv images. */
     3311        pCtx->fpu.CS    = 0;
     3312        pCtx->fpu.FPUIP = pCtx->eip | ((uint32_t)pCtx->cs << 4);
     3313    }
     3314    else
     3315    {
     3316        pCtx->fpu.CS    = pCtx->cs;
     3317        pCtx->fpu.FPUIP = pCtx->rip;
     3318    }
    33293319}
    33303320
     
    33543344    }
    33553345    /** @todo FPU.DS and FPUDP needs to be kept seperately. */
    3356     pCtx->fpu.DS    = sel;
    3357     pCtx->fpu.FPUDP = GCPtrEff;
     3346    if (IEM_IS_REAL_OR_V86_MODE(pIemCpu))
     3347    {
     3348        pCtx->fpu.DS    = 0;
     3349        pCtx->fpu.FPUDP = (uint32_t)GCPtrEff | ((uint32_t)sel << 4);
     3350    }
     3351    else
     3352    {
     3353        pCtx->fpu.DS    = sel;
     3354        pCtx->fpu.FPUDP = GCPtrEff;
     3355    }
    33583356}
    33593357
     
    38333831    }
    38343832    return VERR_NOT_FOUND;
     3833}
     3834
     3835
     3836/**
     3837 * Updates the FPU exception status after FCW is changed.
     3838 *
     3839 * @param   pCtx                The CPU context.
     3840 */
     3841static void iemFpuRecalcExceptionStatus(PCPUMCTX pCtx)
     3842{
     3843    uint16_t u16Fsw = pCtx->fpu.FSW;
     3844    if ((u16Fsw & X86_FSW_XCPT_MASK) & ~(pCtx->fpu.FCW & X86_FCW_XCPT_MASK))
     3845        u16Fsw |= X86_FSW_ES | X86_FSW_B;
     3846    else
     3847        u16Fsw &= ~(X86_FSW_ES | X86_FSW_B);
     3848    pCtx->fpu.FSW = u16Fsw;
     3849}
     3850
     3851
     3852/**
     3853 * Calculates the full FTW (FPU tag word) for use in FNSTENV and FNSAVE.
     3854 *
     3855 * @returns The full FTW.
     3856 * @param   pCtx                The CPU state.
     3857 */
     3858static uint16_t iemFpuCalcFullFtw(PCCPUMCTX pCtx)
     3859{
     3860    uint8_t const   u8Ftw  = (uint8_t)pCtx->fpu.FTW;
     3861    uint16_t        u16Ftw = 0;
     3862    unsigned const  iTop   = X86_FSW_TOP_GET(pCtx->fpu.FSW);
     3863    for (unsigned iSt = 0; iSt < 8; iSt++)
     3864    {
     3865        unsigned const iReg = (iSt + iTop) & 7;
     3866        if (!(u8Ftw & RT_BIT(iReg)))
     3867            u16Ftw |= 3 << (iReg * 2); /* empty */
     3868        else
     3869        {
     3870            uint16_t uTag;
     3871            PCRTFLOAT80U const pr80Reg = &pCtx->fpu.aRegs[iSt].r80;
     3872            if (pr80Reg->s.uExponent == 0x7fff)
     3873                uTag = 2; /* Exponent is all 1's => Special. */
     3874            else if (pr80Reg->s.uExponent == 0x0000)
     3875            {
     3876                if (pr80Reg->s.u64Mantissa == 0x0000)
     3877                    uTag = 1; /* All bits are zero => Zero. */
     3878                else
     3879                    uTag = 2; /* Must be special. */
     3880            }
     3881            else if (pr80Reg->s.u64Mantissa & RT_BIT_64(63)) /* The J bit. */
     3882                uTag = 0; /* Valid. */
     3883            else
     3884                uTag = 2; /* Must be special. */
     3885
     3886            u16Ftw |= uTag << (iReg * 2); /* empty */
     3887        }
     3888    }
     3889
     3890    return u16Ftw;
     3891}
     3892
     3893
     3894/**
     3895 * Converts a full FTW to a compressed one (for use in FLDENV and FRSTOR).
     3896 *
     3897 * @returns The compressed FTW.
     3898 * @param   u16FullFtw      The full FTW to convert.
     3899 */
     3900static uint16_t iemFpuCompressFtw(uint16_t u16FullFtw)
     3901{
     3902    uint8_t u8Ftw = 0;
     3903    for (unsigned i = 0; i < 8; i++)
     3904    {
     3905        if ((u16FullFtw & 3) != 3 /*empty*/)
     3906            u8Ftw |= RT_BIT(i);
     3907        u16FullFtw >>= 2;
     3908    }
     3909
     3910    return u8Ftw;
    38353911}
    38363912
     
    55745650#define IEM_MC_MAYBE_RAISE_FPU_XCPT() \
    55755651    do { \
    5576         if (iemFRegFetchFsw(pIemCpu) & X86_FSW_ES) \
     5652        if ((pIemCpu)->CTX_SUFF(pCtx)->fpu.FSW & X86_FSW_ES) \
    55775653            return iemRaiseMathFault(pIemCpu); \
    55785654    } while (0)
     
    56245700#define IEM_MC_FETCH_EFLAGS(a_EFlags)                   (a_EFlags) = (pIemCpu)->CTX_SUFF(pCtx)->eflags.u
    56255701#define IEM_MC_FETCH_EFLAGS_U8(a_EFlags)                (a_EFlags) = (uint8_t)(pIemCpu)->CTX_SUFF(pCtx)->eflags.u
    5626 #define IEM_MC_FETCH_FSW(a_u16Fsw)                      (a_u16Fsw) = iemFRegFetchFsw(pIemCpu)
     5702#define IEM_MC_FETCH_FSW(a_u16Fsw)                      (a_u16Fsw) = pIemCpu->CTX_SUFF(pCtx)->fpu.FSW
     5703#define IEM_MC_FETCH_FCW(a_u16Fcw)                      (a_u16Fcw) = pIemCpu->CTX_SUFF(pCtx)->fpu.FCW
    56275704
    56285705#define IEM_MC_STORE_GREG_U8(a_iGReg, a_u8Value)        *iemGRegRefU8(pIemCpu, (a_iGReg)) = (a_u8Value)
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r40187 r40222  
    132132        iemHlpLoadNullDataSelectorProt(puSel, pHid);
    133133}
    134 
    135134
    136135/** @} */
     
    40604059}
    40614060
     4061
     4062/**
     4063 * Commmon routine for fnstenv and fnsave.
     4064 *
     4065 * @param   uPtr                Where to store the state.
     4066 * @param   pCtx                The CPU context.
     4067 */
     4068static void iemCImplCommonFpuStoreEnv(PIEMCPU pIemCpu, IEMMODE enmEffOpSize, RTPTRUNION uPtr, PCCPUMCTX pCtx)
     4069{
     4070    if (enmEffOpSize == IEMMODE_16BIT)
     4071    {
     4072        uPtr.pu16[0] = pCtx->fpu.FCW;
     4073        uPtr.pu16[1] = pCtx->fpu.FSW;
     4074        uPtr.pu16[2] = iemFpuCalcFullFtw(pCtx);
     4075        if (IEM_IS_REAL_OR_V86_MODE(pIemCpu))
     4076        {
     4077            /** @todo Testcase: How does this work when the FPUIP/CS was saved in
     4078             *        protected mode or long mode and we save it in real mode?  And vice
     4079             *        versa?  And with 32-bit operand size?  I think CPU is storing the
     4080             *        effective address ((CS << 4) + IP) in the offset register and not
     4081             *        doing any address calculations here. */
     4082            uPtr.pu16[3] = (uint16_t)pCtx->fpu.FPUIP;
     4083            uPtr.pu16[4] = ((pCtx->fpu.FPUIP >> 4) & UINT16_C(0xf000)) | pCtx->fpu.FOP;
     4084            uPtr.pu16[5] = (uint16_t)pCtx->fpu.FPUDP;
     4085            uPtr.pu16[6] = (pCtx->fpu.FPUDP  >> 4) & UINT16_C(0xf000);
     4086        }
     4087        else
     4088        {
     4089            uPtr.pu16[3] = pCtx->fpu.FPUIP;
     4090            uPtr.pu16[4] = pCtx->fpu.CS;
     4091            uPtr.pu16[5] = pCtx->fpu.FPUDP;
     4092            uPtr.pu16[6] = pCtx->fpu.DS;
     4093        }
     4094    }
     4095    else
     4096    {
     4097        /** @todo Testcase: what is stored in the "gray" areas? (figure 8-9 and 8-10) */
     4098        uPtr.pu16[0*2] = pCtx->fpu.FCW;
     4099        uPtr.pu16[1*2] = pCtx->fpu.FSW;
     4100        uPtr.pu16[2*2] = iemFpuCalcFullFtw(pCtx);
     4101        if (IEM_IS_REAL_OR_V86_MODE(pIemCpu))
     4102        {
     4103            uPtr.pu16[3*2]  = (uint16_t)pCtx->fpu.FPUIP;
     4104            uPtr.pu32[4]    = ((pCtx->fpu.FPUIP & UINT32_C(0xffff0000)) >> 4) | pCtx->fpu.FOP;
     4105            uPtr.pu16[5*2]  = (uint16_t)pCtx->fpu.FPUDP;
     4106            uPtr.pu32[6]    = (pCtx->fpu.FPUDP  & UINT32_C(0xffff0000)) >> 4;
     4107        }
     4108        else
     4109        {
     4110            uPtr.pu32[3]    = pCtx->fpu.FPUIP;
     4111            uPtr.pu16[4*2]  = pCtx->fpu.CS;
     4112            uPtr.pu16[4*2+1]= pCtx->fpu.FOP;
     4113            uPtr.pu32[5]    = pCtx->fpu.FPUDP;
     4114            uPtr.pu16[6*2]  = pCtx->fpu.DS;
     4115        }
     4116    }
     4117}
     4118
     4119
     4120/**
     4121 * Commmon routine for fnstenv and fnsave.
     4122 *
     4123 * @param   uPtr                Where to store the state.
     4124 * @param   pCtx                The CPU context.
     4125 */
     4126static void iemCImplCommonFpuRestoreEnv(PIEMCPU pIemCpu, IEMMODE enmEffOpSize, RTCPTRUNION uPtr, PCPUMCTX pCtx)
     4127{
     4128    if (enmEffOpSize == IEMMODE_16BIT)
     4129    {
     4130        pCtx->fpu.FCW = uPtr.pu16[0];
     4131        pCtx->fpu.FSW = uPtr.pu16[1];
     4132        pCtx->fpu.FTW = uPtr.pu16[2];
     4133        if (IEM_IS_REAL_OR_V86_MODE(pIemCpu))
     4134        {
     4135            pCtx->fpu.FPUIP = uPtr.pu16[3] | ((uint32_t)(uPtr.pu16[4] & UINT16_C(0xf000)) << 4);
     4136            pCtx->fpu.FPUDP = uPtr.pu16[5] | ((uint32_t)(uPtr.pu16[6] & UINT16_C(0xf000)) << 4);
     4137            pCtx->fpu.FOP   = uPtr.pu16[4] & UINT16_C(0x07ff);
     4138            pCtx->fpu.CS    = 0;
     4139            pCtx->fpu.DS    = 0;
     4140        }
     4141        else
     4142        {
     4143            pCtx->fpu.FPUIP = uPtr.pu16[3];
     4144            pCtx->fpu.CS    = uPtr.pu16[4];
     4145            pCtx->fpu.FPUDP = uPtr.pu16[5];
     4146            pCtx->fpu.DS    = uPtr.pu16[6];
     4147            /** @todo Testcase: Is FOP cleared when doing 16-bit protected mode fldenv? */
     4148        }
     4149    }
     4150    else
     4151    {
     4152        pCtx->fpu.FCW = uPtr.pu16[0*2];
     4153        pCtx->fpu.FSW = uPtr.pu16[1*2];
     4154        pCtx->fpu.FTW = uPtr.pu16[2*2];
     4155        if (IEM_IS_REAL_OR_V86_MODE(pIemCpu))
     4156        {
     4157            pCtx->fpu.FPUIP = uPtr.pu16[3*2] | ((uPtr.pu32[4] & UINT32_C(0x0ffff000)) << 4);
     4158            pCtx->fpu.FOP   = uPtr.pu32[4] & UINT16_C(0x07ff);
     4159            pCtx->fpu.FPUDP = uPtr.pu16[5*2] | ((uPtr.pu32[6] & UINT32_C(0x0ffff000)) << 4);
     4160            pCtx->fpu.CS    = 0;
     4161            pCtx->fpu.DS    = 0;
     4162        }
     4163        else
     4164        {
     4165            pCtx->fpu.FPUIP = uPtr.pu32[3];
     4166            pCtx->fpu.CS    = uPtr.pu16[4*2];
     4167            pCtx->fpu.FOP   = uPtr.pu16[4*2+1];
     4168            pCtx->fpu.FPUDP = uPtr.pu32[5];
     4169            pCtx->fpu.DS    = uPtr.pu16[6*2];
     4170        }
     4171    }
     4172
     4173    /* Make adjustments. */
     4174    pCtx->fpu.FTW = iemFpuCompressFtw(pCtx->fpu.FTW);
     4175    pCtx->fpu.FCW &= ~X86_FCW_ZERO_MASK;
     4176    iemFpuRecalcExceptionStatus(pCtx);
     4177    /** @todo Testcase: Check if ES and/or B are automatically cleared if no
     4178     *        exceptions are pending after loading the saved state? */
     4179}
     4180
     4181
     4182/**
     4183 * Implements 'FNSTENV'.
     4184 *
     4185 * @param   enmEffOpSize    The operand size (only REX.W really matters).
     4186 * @param   iEffSeg         The effective segment register for @a GCPtrEff.
     4187 * @param   GCPtrEffDst     The address of the image.
     4188 */
     4189IEM_CIMPL_DEF_3(iemCImpl_fnstenv, IEMMODE, enmEffOpSize, uint8_t, iEffSeg, RTGCPTR, GCPtrEffDst)
     4190{
     4191    PCPUMCTX     pCtx = pIemCpu->CTX_SUFF(pCtx);
     4192    RTPTRUNION   uPtr;
     4193    VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, &uPtr.pv, enmEffOpSize == IEMMODE_16BIT ? 14 : 28,
     4194                                      iEffSeg, GCPtrEffDst, IEM_ACCESS_DATA_W | IEM_ACCESS_PARTIAL_WRITE);
     4195    if (rcStrict != VINF_SUCCESS)
     4196        return rcStrict;
     4197
     4198    iemCImplCommonFpuStoreEnv(pIemCpu, enmEffOpSize, uPtr, pCtx);
     4199
     4200    rcStrict = iemMemCommitAndUnmap(pIemCpu, uPtr.pv, IEM_ACCESS_DATA_W | IEM_ACCESS_PARTIAL_WRITE);
     4201    if (rcStrict != VINF_SUCCESS)
     4202        return rcStrict;
     4203
     4204    /* Note: C0, C1, C2 and C3 are documented as undefined, we leave them untouched! */
     4205    iemRegAddToRip(pIemCpu, cbInstr);
     4206    return VINF_SUCCESS;
     4207}
     4208
     4209
     4210/**
     4211 * Implements 'FLDENV'.
     4212 *
     4213 * @param   enmEffOpSize    The operand size (only REX.W really matters).
     4214 * @param   iEffSeg         The effective segment register for @a GCPtrEff.
     4215 * @param   GCPtrEffSrc     The address of the image.
     4216 */
     4217IEM_CIMPL_DEF_3(iemCImpl_fldenv, IEMMODE, enmEffOpSize, uint8_t, iEffSeg, RTGCPTR, GCPtrEffSrc)
     4218{
     4219    PCPUMCTX     pCtx = pIemCpu->CTX_SUFF(pCtx);
     4220    RTCPTRUNION  uPtr;
     4221    VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, (void **)&uPtr.pv, enmEffOpSize == IEMMODE_16BIT ? 14 : 28,
     4222                                      iEffSeg, GCPtrEffSrc, IEM_ACCESS_DATA_R);
     4223    if (rcStrict != VINF_SUCCESS)
     4224        return rcStrict;
     4225
     4226    iemCImplCommonFpuRestoreEnv(pIemCpu, enmEffOpSize, uPtr, pCtx);
     4227
     4228    rcStrict = iemMemCommitAndUnmap(pIemCpu, (void *)uPtr.pv, IEM_ACCESS_DATA_R);
     4229    if (rcStrict != VINF_SUCCESS)
     4230        return rcStrict;
     4231
     4232    iemRegAddToRip(pIemCpu, cbInstr);
     4233    return VINF_SUCCESS;
     4234}
     4235
     4236
     4237/**
     4238 * Implements 'FLDCW'.
     4239 *
     4240 * @param   u16Fcw          The new FCW.
     4241 */
     4242IEM_CIMPL_DEF_1(iemCImpl_fldcw, uint16_t, u16Fcw)
     4243{
     4244    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
     4245
     4246    /** @todo Testcase: Check what happens when trying to load X86_FCW_PC_RSVD. */
     4247    /** @todo Testcase: Try see what happens when trying to set undefined bits
     4248     *        (other than 6 and 7).  Currently ignoring them. */
     4249    /** @todo Testcase: Test that it raises and loweres the FPU exception bits
     4250     *        according to FSW. (This is was is currently implemented.) */
     4251    pCtx->fpu.FCW = u16Fcw & ~X86_FCW_ZERO_MASK;
     4252    iemFpuRecalcExceptionStatus(pCtx);
     4253
     4254    /* Note: C0, C1, C2 and C3 are documented as undefined, we leave them untouched! */
     4255    iemRegAddToRip(pIemCpu, cbInstr);
     4256    return VINF_SUCCESS;
     4257}
     4258
     4259
    40624260/** @} */
    40634261
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h

    r40210 r40222  
    1069610696
    1069710697/** Opcode 0xd9 !11/4 */
    10698 FNIEMOP_STUB_1(iemOp_fldenv, uint8_t, bRm);
     10698FNIEMOP_DEF_1(iemOp_fldenv, uint8_t, bRm)
     10699{
     10700    IEMOP_MNEMONIC("fldenv m14/28byte");
     10701    IEM_MC_BEGIN(3, 0);
     10702    IEM_MC_ARG_CONST(IEMMODE,           enmEffOpSize, /*=*/ pIemCpu->enmEffOpSize,  0);
     10703    IEM_MC_ARG_CONST(uint8_t,           iEffSeg,      /*=*/ pIemCpu->iEffSeg,       1);
     10704    IEM_MC_ARG(RTGCPTR,                 GCPtrEffSrc,                                2);
     10705    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
     10706    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     10707    IEM_MC_CALL_CIMPL_3(iemCImpl_fldenv, enmEffOpSize, iEffSeg, GCPtrEffSrc);
     10708    IEM_MC_END();
     10709    return VINF_SUCCESS;
     10710}
     10711
    1069910712
    1070010713/** Opcode 0xd9 !11/5 */
    10701 FNIEMOP_STUB_1(iemOp_fldcw, uint8_t, bRm);
     10714FNIEMOP_DEF_1(iemOp_fldcw, uint8_t, bRm)
     10715{
     10716    IEMOP_MNEMONIC("fldcw m2byte");
     10717    IEM_MC_BEGIN(1, 1);
     10718    IEM_MC_LOCAL(RTGCPTR,               GCPtrEffSrc);
     10719    IEM_MC_ARG(uint16_t,                u16Fsw,                                     0);
     10720    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm);
     10721    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     10722    IEM_MC_FETCH_MEM_U16(u16Fsw, pIemCpu->iEffSeg, GCPtrEffSrc);
     10723    IEM_MC_CALL_CIMPL_1(iemCImpl_fldcw, u16Fsw);
     10724    IEM_MC_END();
     10725    return VINF_SUCCESS;
     10726}
     10727
    1070210728
    1070310729/** Opcode 0xd9 !11/6 */
    10704 FNIEMOP_STUB_1(iemOp_fstenv, uint8_t, bRm);
     10730FNIEMOP_DEF_1(iemOp_fnstenv, uint8_t, bRm)
     10731{
     10732    IEMOP_MNEMONIC("fstenv m14/28byte");
     10733    IEM_MC_BEGIN(3, 0);
     10734    IEM_MC_ARG_CONST(IEMMODE,           enmEffOpSize, /*=*/ pIemCpu->enmEffOpSize,  0);
     10735    IEM_MC_ARG_CONST(uint8_t,           iEffSeg,      /*=*/ pIemCpu->iEffSeg,       1);
     10736    IEM_MC_ARG(RTGCPTR,                 GCPtrEffDst,                                2);
     10737    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
     10738    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     10739    IEM_MC_CALL_CIMPL_3(iemCImpl_fnstenv, enmEffOpSize, iEffSeg, GCPtrEffDst);
     10740    IEM_MC_END();
     10741    return VINF_SUCCESS;
     10742}
     10743
    1070510744
    1070610745/** Opcode 0xd9 !11/7 */
    10707 FNIEMOP_STUB_1(iemOp_fstcw, uint8_t, bRm);
     10746FNIEMOP_DEF_1(iemOp_fnstcw, uint8_t, bRm)
     10747{
     10748    IEMOP_MNEMONIC("fnstcw m2byte");
     10749    IEM_MC_BEGIN(2, 0);
     10750    IEM_MC_LOCAL(RTGCPTR,               GCPtrEffDst);
     10751    IEM_MC_LOCAL(uint16_t,              u16Fcw);
     10752    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm);
     10753    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     10754    IEM_MC_FETCH_FSW(u16Fcw);
     10755    IEM_MC_STORE_MEM_U16(pIemCpu->iEffSeg, GCPtrEffDst, u16Fcw);
     10756    IEM_MC_ADVANCE_RIP(); /* C0-C3 are documented as undefined, we leave them unmodified. */
     10757    IEM_MC_END();
     10758    return VINF_SUCCESS;
     10759}
     10760
    1070810761
    1070910762/** Opcode 0xd9 0xc9, 0xd9 0xd8-0xdf, ++?.  */
     
    1091710970            case 4: return FNIEMOP_CALL_1(iemOp_fldenv,    bRm);
    1091810971            case 5: return FNIEMOP_CALL_1(iemOp_fldcw,     bRm);
    10919             case 6: return FNIEMOP_CALL_1(iemOp_fstenv,    bRm);
    10920             case 7: return FNIEMOP_CALL_1(iemOp_fstcw,     bRm);
     10972            case 6: return FNIEMOP_CALL_1(iemOp_fnstenv,    bRm);
     10973            case 7: return FNIEMOP_CALL_1(iemOp_fnstcw,     bRm);
    1092110974            IEM_NOT_REACHED_DEFAULT_CASE_RET();
    1092210975        }
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