VirtualBox

Ignore:
Timestamp:
Jul 4, 2018 3:37:03 PM (6 years ago)
Author:
vboxsync
Message:

EMAll.cpp: flushed out unused code.

File:
1 edited

Legend:

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

    r72884 r72885  
    2020*   Header Files                                                                                                                 *
    2121*********************************************************************************************************************************/
    22 #define VBOX_WITH_IEM
    2322#define LOG_GROUP LOG_GROUP_EM
    2423#include <VBox/vmm/em.h>
     
    2625#include <VBox/vmm/selm.h>
    2726#include <VBox/vmm/patm.h>
    28 #include <VBox/vmm/csam.h>
    2927#include <VBox/vmm/pgm.h>
    30 #ifdef VBOX_WITH_IEM
    31 # include <VBox/vmm/iem.h>
    32 #endif
     28#include <VBox/vmm/iem.h>
    3329#include <VBox/vmm/iom.h>
     30#include <VBox/vmm/hm.h>
     31#include <VBox/vmm/pdmapi.h>
     32#include <VBox/vmm/vmm.h>
    3433#include <VBox/vmm/stam.h>
    3534#include "EMInternal.h"
    3635#include <VBox/vmm/vm.h>
    37 #include <VBox/vmm/vmm.h>
    38 #include <VBox/vmm/hm.h>
    39 #include <VBox/vmm/tm.h>
    40 #include <VBox/vmm/pdmapi.h>
    4136#include <VBox/param.h>
    4237#include <VBox/err.h>
     
    4540#include <VBox/log.h>
    4641#include <iprt/assert.h>
    47 #include <iprt/asm.h>
    4842#include <iprt/string.h>
    4943
    50 #ifdef VBOX_WITH_IEM
    51 //# define VBOX_COMPARE_IEM_AND_EM /* debugging... */
    52 //# define VBOX_SAME_AS_EM
    53 //# define VBOX_COMPARE_IEM_LAST
    54 #endif
    55 
    56 #ifdef VBOX_WITH_RAW_RING1
    57 # define EM_EMULATE_SMSW
    58 #endif
    59 
    60 
    61 /*********************************************************************************************************************************
    62 *   Defined Constants And Macros                                                                                                 *
    63 *********************************************************************************************************************************/
    64 /** @def EM_ASSERT_FAULT_RETURN
    65  * Safety check.
    66  *
    67  * Could in theory misfire on a cross page boundary access...
    68  *
    69  * Currently disabled because the CSAM (+ PATM) patch monitoring occasionally
    70  * turns up an alias page instead of the original faulting one and annoying the
    71  * heck out of anyone running a debug build. See @bugref{2609} and @bugref{1931}.
    72  */
    73 #if 0
    74 # define EM_ASSERT_FAULT_RETURN(expr, rc) AssertReturn(expr, rc)
    75 #else
    76 # define EM_ASSERT_FAULT_RETURN(expr, rc) do { } while (0)
    77 #endif
    78 
    79 
    80 /*********************************************************************************************************************************
    81 *   Internal Functions                                                                                                           *
    82 *********************************************************************************************************************************/
    83 #if !defined(VBOX_WITH_IEM) || defined(VBOX_COMPARE_IEM_AND_EM)
    84 DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPUOuter(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
    85                                                         RTGCPTR pvFault, EMCODETYPE enmCodeType, uint32_t *pcbSize);
    86 #endif
    87 
    88 
    89 /*********************************************************************************************************************************
    90 *   Global Variables                                                                                                             *
    91 *********************************************************************************************************************************/
    92 #ifdef VBOX_COMPARE_IEM_AND_EM
    93 static const uint32_t g_fInterestingFFs = VMCPU_FF_TO_R3
    94     | VMCPU_FF_CSAM_PENDING_ACTION | VMCPU_FF_CSAM_SCAN_PAGE | VMCPU_FF_INHIBIT_INTERRUPTS
    95     | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT
    96     | VMCPU_FF_TLB_FLUSH | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL;
    97 static uint32_t g_fIncomingFFs;
    98 static CPUMCTX g_IncomingCtx;
    99 static bool    g_fIgnoreRaxRdx = false;
    100 
    101 static uint32_t g_fEmFFs;
    102 static CPUMCTX g_EmCtx;
    103 static uint8_t g_abEmWrote[256];
    104 static size_t  g_cbEmWrote;
    105 
    106 static uint32_t g_fIemFFs;
    107 static CPUMCTX g_IemCtx;
    108 extern uint8_t g_abIemWrote[256];
    109 #if defined(VBOX_COMPARE_IEM_FIRST) || defined(VBOX_COMPARE_IEM_LAST)
    110 extern size_t  g_cbIemWrote;
    111 #else
    112 static size_t  g_cbIemWrote;
    113 #endif
    114 #endif
     44
    11545
    11646
     
    10981028
    10991029
    1100 #if !defined(VBOX_WITH_IEM) || defined(VBOX_COMPARE_IEM_AND_EM)
    1101 DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    1102 {
    1103     NOREF(pVM);
    1104     return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, pVCpu, pDis, pOpsize);
    1105 }
    1106 #endif
    1107 
    11081030
    11091031/**
     
    11691091
    11701092
    1171 #if defined(VBOX_COMPARE_IEM_FIRST) || defined(VBOX_COMPARE_IEM_LAST)
    1172 static void emCompareWithIem(PVMCPU pVCpu, PCCPUMCTX pEmCtx, PCCPUMCTX pIemCtx,
    1173                              VBOXSTRICTRC rcEm, VBOXSTRICTRC rcIem,
    1174                              uint32_t cbEm, uint32_t cbIem)
    1175 {
    1176     /* Quick compare. */
    1177     if (   rcEm == rcIem
    1178         && cbEm == cbIem
    1179         && g_cbEmWrote == g_cbIemWrote
    1180         && memcmp(g_abIemWrote, g_abEmWrote, g_cbIemWrote) == 0
    1181         && memcmp(pIemCtx, pEmCtx, sizeof(*pIemCtx)) == 0
    1182         && (g_fEmFFs & g_fInterestingFFs) == (g_fIemFFs & g_fInterestingFFs)
    1183        )
    1184         return;
    1185 
    1186     /* Report exact differences. */
    1187     RTLogPrintf("! EM and IEM differs at %04x:%08RGv !\n", g_IncomingCtx.cs.Sel, g_IncomingCtx.rip);
    1188     if (rcEm != rcIem)
    1189         RTLogPrintf(" * rcIem=%Rrc rcEm=%Rrc\n", VBOXSTRICTRC_VAL(rcIem), VBOXSTRICTRC_VAL(rcEm));
    1190     else if (cbEm != cbIem)
    1191         RTLogPrintf(" * cbIem=%#x cbEm=%#x\n", cbIem, cbEm);
    1192 
    1193     if (RT_SUCCESS(rcEm) && RT_SUCCESS(rcIem))
    1194     {
    1195         if (g_cbIemWrote != g_cbEmWrote)
    1196             RTLogPrintf("!! g_cbIemWrote=%#x g_cbEmWrote=%#x\n", g_cbIemWrote, g_cbEmWrote);
    1197         else if (memcmp(g_abIemWrote, g_abEmWrote, g_cbIemWrote))
    1198         {
    1199             RTLogPrintf("!! IemWrote %.*Rhxs\n", RT_MIN(RT_MAX(1, g_cbIemWrote), 64), g_abIemWrote);
    1200             RTLogPrintf("!! EemWrote  %.*Rhxs\n", RT_MIN(RT_MAX(1, g_cbIemWrote), 64), g_abIemWrote);
    1201         }
    1202 
    1203         if ((g_fEmFFs & g_fInterestingFFs) != (g_fIemFFs & g_fInterestingFFs))
    1204             RTLogPrintf("!! g_fIemFFs=%#x  g_fEmFFs=%#x (diff=%#x)\n", g_fIemFFs & g_fInterestingFFs,
    1205                         g_fEmFFs & g_fInterestingFFs, (g_fIemFFs ^ g_fEmFFs) & g_fInterestingFFs);
    1206 
    1207 #  define CHECK_FIELD(a_Field) \
    1208         do \
    1209         { \
    1210             if (pEmCtx->a_Field != pIemCtx->a_Field) \
    1211             { \
    1212                 switch (sizeof(pEmCtx->a_Field)) \
    1213                 { \
    1214                     case 1: RTLogPrintf("!! %8s differs - iem=%02x - em=%02x\n", #a_Field, pIemCtx->a_Field, pEmCtx->a_Field); break; \
    1215                     case 2: RTLogPrintf("!! %8s differs - iem=%04x - em=%04x\n", #a_Field, pIemCtx->a_Field, pEmCtx->a_Field); break; \
    1216                     case 4: RTLogPrintf("!! %8s differs - iem=%08x - em=%08x\n", #a_Field, pIemCtx->a_Field, pEmCtx->a_Field); break; \
    1217                     case 8: RTLogPrintf("!! %8s differs - iem=%016llx - em=%016llx\n", #a_Field, pIemCtx->a_Field, pEmCtx->a_Field); break; \
    1218                     default: RTLogPrintf("!!  %8s differs\n", #a_Field); break; \
    1219                 } \
    1220                 cDiffs++; \
    1221             } \
    1222         } while (0)
    1223 
    1224 #  define CHECK_BIT_FIELD(a_Field) \
    1225         do \
    1226         { \
    1227             if (pEmCtx->a_Field != pIemCtx->a_Field) \
    1228             { \
    1229                 RTLogPrintf("!! %8s differs - iem=%02x - em=%02x\n", #a_Field, pIemCtx->a_Field, pEmCtx->a_Field); \
    1230                 cDiffs++; \
    1231             } \
    1232         } while (0)
    1233 
    1234 #  define CHECK_SEL(a_Sel) \
    1235         do \
    1236         { \
    1237             CHECK_FIELD(a_Sel.Sel); \
    1238             CHECK_FIELD(a_Sel.Attr.u); \
    1239             CHECK_FIELD(a_Sel.u64Base); \
    1240             CHECK_FIELD(a_Sel.u32Limit); \
    1241             CHECK_FIELD(a_Sel.fFlags); \
    1242         } while (0)
    1243 
    1244         unsigned cDiffs = 0;
    1245         if (memcmp(&pEmCtx->fpu, &pIemCtx->fpu, sizeof(pIemCtx->fpu)))
    1246         {
    1247             RTLogPrintf("  the FPU state differs\n");
    1248             cDiffs++;
    1249             CHECK_FIELD(fpu.FCW);
    1250             CHECK_FIELD(fpu.FSW);
    1251             CHECK_FIELD(fpu.FTW);
    1252             CHECK_FIELD(fpu.FOP);
    1253             CHECK_FIELD(fpu.FPUIP);
    1254             CHECK_FIELD(fpu.CS);
    1255             CHECK_FIELD(fpu.Rsrvd1);
    1256             CHECK_FIELD(fpu.FPUDP);
    1257             CHECK_FIELD(fpu.DS);
    1258             CHECK_FIELD(fpu.Rsrvd2);
    1259             CHECK_FIELD(fpu.MXCSR);
    1260             CHECK_FIELD(fpu.MXCSR_MASK);
    1261             CHECK_FIELD(fpu.aRegs[0].au64[0]); CHECK_FIELD(fpu.aRegs[0].au64[1]);
    1262             CHECK_FIELD(fpu.aRegs[1].au64[0]); CHECK_FIELD(fpu.aRegs[1].au64[1]);
    1263             CHECK_FIELD(fpu.aRegs[2].au64[0]); CHECK_FIELD(fpu.aRegs[2].au64[1]);
    1264             CHECK_FIELD(fpu.aRegs[3].au64[0]); CHECK_FIELD(fpu.aRegs[3].au64[1]);
    1265             CHECK_FIELD(fpu.aRegs[4].au64[0]); CHECK_FIELD(fpu.aRegs[4].au64[1]);
    1266             CHECK_FIELD(fpu.aRegs[5].au64[0]); CHECK_FIELD(fpu.aRegs[5].au64[1]);
    1267             CHECK_FIELD(fpu.aRegs[6].au64[0]); CHECK_FIELD(fpu.aRegs[6].au64[1]);
    1268             CHECK_FIELD(fpu.aRegs[7].au64[0]); CHECK_FIELD(fpu.aRegs[7].au64[1]);
    1269             CHECK_FIELD(fpu.aXMM[ 0].au64[0]);  CHECK_FIELD(fpu.aXMM[ 0].au64[1]);
    1270             CHECK_FIELD(fpu.aXMM[ 1].au64[0]);  CHECK_FIELD(fpu.aXMM[ 1].au64[1]);
    1271             CHECK_FIELD(fpu.aXMM[ 2].au64[0]);  CHECK_FIELD(fpu.aXMM[ 2].au64[1]);
    1272             CHECK_FIELD(fpu.aXMM[ 3].au64[0]);  CHECK_FIELD(fpu.aXMM[ 3].au64[1]);
    1273             CHECK_FIELD(fpu.aXMM[ 4].au64[0]);  CHECK_FIELD(fpu.aXMM[ 4].au64[1]);
    1274             CHECK_FIELD(fpu.aXMM[ 5].au64[0]);  CHECK_FIELD(fpu.aXMM[ 5].au64[1]);
    1275             CHECK_FIELD(fpu.aXMM[ 6].au64[0]);  CHECK_FIELD(fpu.aXMM[ 6].au64[1]);
    1276             CHECK_FIELD(fpu.aXMM[ 7].au64[0]);  CHECK_FIELD(fpu.aXMM[ 7].au64[1]);
    1277             CHECK_FIELD(fpu.aXMM[ 8].au64[0]);  CHECK_FIELD(fpu.aXMM[ 8].au64[1]);
    1278             CHECK_FIELD(fpu.aXMM[ 9].au64[0]);  CHECK_FIELD(fpu.aXMM[ 9].au64[1]);
    1279             CHECK_FIELD(fpu.aXMM[10].au64[0]);  CHECK_FIELD(fpu.aXMM[10].au64[1]);
    1280             CHECK_FIELD(fpu.aXMM[11].au64[0]);  CHECK_FIELD(fpu.aXMM[11].au64[1]);
    1281             CHECK_FIELD(fpu.aXMM[12].au64[0]);  CHECK_FIELD(fpu.aXMM[12].au64[1]);
    1282             CHECK_FIELD(fpu.aXMM[13].au64[0]);  CHECK_FIELD(fpu.aXMM[13].au64[1]);
    1283             CHECK_FIELD(fpu.aXMM[14].au64[0]);  CHECK_FIELD(fpu.aXMM[14].au64[1]);
    1284             CHECK_FIELD(fpu.aXMM[15].au64[0]);  CHECK_FIELD(fpu.aXMM[15].au64[1]);
    1285             for (unsigned i = 0; i < RT_ELEMENTS(pEmCtx->fpu.au32RsrvdRest); i++)
    1286                 CHECK_FIELD(fpu.au32RsrvdRest[i]);
    1287         }
    1288         CHECK_FIELD(rip);
    1289         if (pEmCtx->rflags.u != pIemCtx->rflags.u)
    1290         {
    1291             RTLogPrintf("!! rflags differs - iem=%08llx em=%08llx\n", pIemCtx->rflags.u, pEmCtx->rflags.u);
    1292             CHECK_BIT_FIELD(rflags.Bits.u1CF);
    1293             CHECK_BIT_FIELD(rflags.Bits.u1Reserved0);
    1294             CHECK_BIT_FIELD(rflags.Bits.u1PF);
    1295             CHECK_BIT_FIELD(rflags.Bits.u1Reserved1);
    1296             CHECK_BIT_FIELD(rflags.Bits.u1AF);
    1297             CHECK_BIT_FIELD(rflags.Bits.u1Reserved2);
    1298             CHECK_BIT_FIELD(rflags.Bits.u1ZF);
    1299             CHECK_BIT_FIELD(rflags.Bits.u1SF);
    1300             CHECK_BIT_FIELD(rflags.Bits.u1TF);
    1301             CHECK_BIT_FIELD(rflags.Bits.u1IF);
    1302             CHECK_BIT_FIELD(rflags.Bits.u1DF);
    1303             CHECK_BIT_FIELD(rflags.Bits.u1OF);
    1304             CHECK_BIT_FIELD(rflags.Bits.u2IOPL);
    1305             CHECK_BIT_FIELD(rflags.Bits.u1NT);
    1306             CHECK_BIT_FIELD(rflags.Bits.u1Reserved3);
    1307             CHECK_BIT_FIELD(rflags.Bits.u1RF);
    1308             CHECK_BIT_FIELD(rflags.Bits.u1VM);
    1309             CHECK_BIT_FIELD(rflags.Bits.u1AC);
    1310             CHECK_BIT_FIELD(rflags.Bits.u1VIF);
    1311             CHECK_BIT_FIELD(rflags.Bits.u1VIP);
    1312             CHECK_BIT_FIELD(rflags.Bits.u1ID);
    1313         }
    1314 
    1315         if (!g_fIgnoreRaxRdx)
    1316             CHECK_FIELD(rax);
    1317         CHECK_FIELD(rcx);
    1318         if (!g_fIgnoreRaxRdx)
    1319             CHECK_FIELD(rdx);
    1320         CHECK_FIELD(rbx);
    1321         CHECK_FIELD(rsp);
    1322         CHECK_FIELD(rbp);
    1323         CHECK_FIELD(rsi);
    1324         CHECK_FIELD(rdi);
    1325         CHECK_FIELD(r8);
    1326         CHECK_FIELD(r9);
    1327         CHECK_FIELD(r10);
    1328         CHECK_FIELD(r11);
    1329         CHECK_FIELD(r12);
    1330         CHECK_FIELD(r13);
    1331         CHECK_SEL(cs);
    1332         CHECK_SEL(ss);
    1333         CHECK_SEL(ds);
    1334         CHECK_SEL(es);
    1335         CHECK_SEL(fs);
    1336         CHECK_SEL(gs);
    1337         CHECK_FIELD(cr0);
    1338         CHECK_FIELD(cr2);
    1339         CHECK_FIELD(cr3);
    1340         CHECK_FIELD(cr4);
    1341         CHECK_FIELD(dr[0]);
    1342         CHECK_FIELD(dr[1]);
    1343         CHECK_FIELD(dr[2]);
    1344         CHECK_FIELD(dr[3]);
    1345         CHECK_FIELD(dr[6]);
    1346         CHECK_FIELD(dr[7]);
    1347         CHECK_FIELD(gdtr.cbGdt);
    1348         CHECK_FIELD(gdtr.pGdt);
    1349         CHECK_FIELD(idtr.cbIdt);
    1350         CHECK_FIELD(idtr.pIdt);
    1351         CHECK_SEL(ldtr);
    1352         CHECK_SEL(tr);
    1353         CHECK_FIELD(SysEnter.cs);
    1354         CHECK_FIELD(SysEnter.eip);
    1355         CHECK_FIELD(SysEnter.esp);
    1356         CHECK_FIELD(msrEFER);
    1357         CHECK_FIELD(msrSTAR);
    1358         CHECK_FIELD(msrPAT);
    1359         CHECK_FIELD(msrLSTAR);
    1360         CHECK_FIELD(msrCSTAR);
    1361         CHECK_FIELD(msrSFMASK);
    1362         CHECK_FIELD(msrKERNELGSBASE);
    1363 
    1364 #  undef CHECK_FIELD
    1365 #  undef CHECK_BIT_FIELD
    1366     }
    1367 }
    1368 #endif /* VBOX_COMPARE_IEM_AND_EM */
    1369 
    1370 
    13711093/**
    13721094 * Interprets the current instruction.
     
    13901112    Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    13911113    LogFlow(("EMInterpretInstruction %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
    1392 #ifdef VBOX_WITH_IEM
    13931114    NOREF(pvFault);
    13941115
    1395 # ifdef VBOX_COMPARE_IEM_AND_EM
    1396     PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
    1397     g_IncomingCtx = *pCtx;
    1398     g_fIncomingFFs = pVCpu->fLocalForcedActions;
    1399     g_cbEmWrote = g_cbIemWrote = 0;
    1400 
    1401 #  ifdef VBOX_COMPARE_IEM_FIRST
    1402     /* IEM */
    1403     VBOXSTRICTRC rcIem = IEMExecOneBypassEx(pVCpu, pRegFrame, NULL);
    1404     if (RT_UNLIKELY(   rcIem == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    1405                     || rcIem == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    1406         rcIem = VERR_EM_INTERPRETER;
    1407     g_IemCtx = *pCtx;
    1408     g_fIemFFs = pVCpu->fLocalForcedActions;
    1409     pVCpu->fLocalForcedActions = (pVCpu->fLocalForcedActions & ~g_fInterestingFFs) | (g_fIncomingFFs & g_fInterestingFFs);
    1410     *pCtx = g_IncomingCtx;
    1411 #  endif
    1412 
    1413     /* EM */
    1414     RTGCPTR pbCode;
    1415     VBOXSTRICTRC rcEm = SELMToFlatEx(pVCpu, DISSELREG_CS, pRegFrame, pRegFrame->rip, 0, &pbCode);
    1416     if (RT_SUCCESS(rcEm))
    1417     {
    1418         uint32_t     cbOp;
    1419         PDISCPUSTATE pDis = &pVCpu->em.s.DisState;
    1420         pDis->uCpuMode = CPUMGetGuestDisMode(pVCpu);
    1421         rcEm = emDisCoreOne(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, (RTGCUINTPTR)pbCode, &cbOp);
    1422         if (RT_SUCCESS(rcEm))
    1423         {
    1424             Assert(cbOp == pDis->cbInstr);
    1425             uint32_t cbIgnored;
    1426             rcEm = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, EMCODETYPE_SUPERVISOR, &cbIgnored);
    1427             if (RT_SUCCESS(rcEm))
    1428                 pRegFrame->rip += cbOp; /* Move on to the next instruction. */
    1429 
    1430         }
    1431         rcEm = VERR_EM_INTERPRETER;
    1432     }
    1433     else
    1434         rcEm = VERR_EM_INTERPRETER;
    1435 #  ifdef VBOX_SAME_AS_EM
    1436     if (rcEm == VERR_EM_INTERPRETER)
    1437     {
    1438         Log(("EMInterpretInstruction: returns %Rrc\n", VBOXSTRICTRC_VAL(rcEm)));
    1439         return rcEm;
    1440     }
    1441 #  endif
    1442     g_EmCtx = *pCtx;
    1443     g_fEmFFs = pVCpu->fLocalForcedActions;
    1444     VBOXSTRICTRC rc = rcEm;
    1445 
    1446 #  ifdef VBOX_COMPARE_IEM_LAST
    1447     /* IEM */
    1448     pVCpu->fLocalForcedActions = (pVCpu->fLocalForcedActions & ~g_fInterestingFFs) | (g_fIncomingFFs & g_fInterestingFFs);
    1449     *pCtx = g_IncomingCtx;
    1450     VBOXSTRICTRC rcIem = IEMExecOneBypassEx(pVCpu, pRegFrame, NULL);
    1451     if (RT_UNLIKELY(   rcIem == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    1452                     || rcIem == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    1453         rcIem = VERR_EM_INTERPRETER;
    1454     g_IemCtx = *pCtx;
    1455     g_fIemFFs = pVCpu->fLocalForcedActions;
    1456     rc = rcIem;
    1457 #  endif
    1458 
    1459 #  if defined(VBOX_COMPARE_IEM_LAST) || defined(VBOX_COMPARE_IEM_FIRST)
    1460     emCompareWithIem(pVCpu, &g_EmCtx, &g_IemCtx, rcEm, rcIem, 0, 0);
    1461 #  endif
    1462 
    1463 # else
    14641116    VBOXSTRICTRC rc = IEMExecOneBypassEx(pVCpu, pRegFrame, NULL);
    14651117    if (RT_UNLIKELY(   rc == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    14661118                    || rc == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    14671119        rc = VERR_EM_INTERPRETER;
    1468 # endif
    14691120    if (rc != VINF_SUCCESS)
    14701121        Log(("EMInterpretInstruction: returns %Rrc\n", VBOXSTRICTRC_VAL(rc)));
    14711122
    14721123    return rc;
    1473 #else
    1474     RTGCPTR pbCode;
    1475     VBOXSTRICTRC rc = SELMToFlatEx(pVCpu, DISSELREG_CS, pRegFrame, pRegFrame->rip, 0, &pbCode);
    1476     if (RT_SUCCESS(rc))
    1477     {
    1478         uint32_t     cbOp;
    1479         PDISCPUSTATE pDis = &pVCpu->em.s.DisState;
    1480         pDis->uCpuMode = CPUMGetGuestDisMode(pVCpu);
    1481         rc = emDisCoreOne(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, (RTGCUINTPTR)pbCode, &cbOp);
    1482         if (RT_SUCCESS(rc))
    1483         {
    1484             Assert(cbOp == pDis->cbInstr);
    1485             uint32_t cbIgnored;
    1486             rc = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, EMCODETYPE_SUPERVISOR, &cbIgnored);
    1487             if (RT_SUCCESS(rc))
    1488                 pRegFrame->rip += cbOp; /* Move on to the next instruction. */
    1489 
    1490             return rc;
    1491         }
    1492     }
    1493     return VERR_EM_INTERPRETER;
    1494 #endif
    14951124}
    14961125
     
    15181147    LogFlow(("EMInterpretInstructionEx %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
    15191148    Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    1520 #ifdef VBOX_WITH_IEM
    15211149    NOREF(pvFault);
    15221150
    1523 # ifdef VBOX_COMPARE_IEM_AND_EM
    1524     PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
    1525     g_IncomingCtx = *pCtx;
    1526     g_fIncomingFFs = pVCpu->fLocalForcedActions;
    1527     g_cbEmWrote = g_cbIemWrote = 0;
    1528 
    1529 #  ifdef VBOX_COMPARE_IEM_FIRST
    1530     /* IEM */
    1531     uint32_t cbIemWritten = 0;
    1532     VBOXSTRICTRC rcIem = IEMExecOneBypassEx(pVCpu, pRegFrame, &cbIemWritten);
    1533     if (RT_UNLIKELY(   rcIem == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    1534                     || rcIem == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    1535         rcIem = VERR_EM_INTERPRETER;
    1536     g_IemCtx = *pCtx;
    1537     g_fIemFFs = pVCpu->fLocalForcedActions;
    1538     pVCpu->fLocalForcedActions = (pVCpu->fLocalForcedActions & ~g_fInterestingFFs) | (g_fIncomingFFs & g_fInterestingFFs);
    1539     *pCtx = g_IncomingCtx;
    1540 #  endif
    1541 
    1542     /* EM */
    1543     uint32_t cbEmWritten = 0;
    1544     RTGCPTR pbCode;
    1545     VBOXSTRICTRC rcEm = SELMToFlatEx(pVCpu, DISSELREG_CS, pRegFrame, pRegFrame->rip, 0, &pbCode);
    1546     if (RT_SUCCESS(rcEm))
    1547     {
    1548         uint32_t     cbOp;
    1549         PDISCPUSTATE pDis = &pVCpu->em.s.DisState;
    1550         pDis->uCpuMode = CPUMGetGuestDisMode(pVCpu);
    1551         rcEm = emDisCoreOne(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, (RTGCUINTPTR)pbCode, &cbOp);
    1552         if (RT_SUCCESS(rcEm))
    1553         {
    1554             Assert(cbOp == pDis->cbInstr);
    1555             rcEm = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, EMCODETYPE_SUPERVISOR, &cbEmWritten);
    1556             if (RT_SUCCESS(rcEm))
    1557                 pRegFrame->rip += cbOp; /* Move on to the next instruction. */
    1558 
    1559         }
    1560         else
    1561             rcEm = VERR_EM_INTERPRETER;
    1562     }
    1563     else
    1564         rcEm = VERR_EM_INTERPRETER;
    1565 #  ifdef VBOX_SAME_AS_EM
    1566     if (rcEm == VERR_EM_INTERPRETER)
    1567     {
    1568         Log(("EMInterpretInstruction: returns %Rrc\n", VBOXSTRICTRC_VAL(rcEm)));
    1569         return rcEm;
    1570     }
    1571 #  endif
    1572     g_EmCtx = *pCtx;
    1573     g_fEmFFs = pVCpu->fLocalForcedActions;
    1574     *pcbWritten = cbEmWritten;
    1575     VBOXSTRICTRC rc = rcEm;
    1576 
    1577 #  ifdef VBOX_COMPARE_IEM_LAST
    1578     /* IEM */
    1579     pVCpu->fLocalForcedActions = (pVCpu->fLocalForcedActions & ~g_fInterestingFFs) | (g_fIncomingFFs & g_fInterestingFFs);
    1580     *pCtx = g_IncomingCtx;
    1581     uint32_t cbIemWritten = 0;
    1582     VBOXSTRICTRC rcIem = IEMExecOneBypassEx(pVCpu, pRegFrame, &cbIemWritten);
    1583     if (RT_UNLIKELY(   rcIem == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    1584                     || rcIem == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    1585         rcIem = VERR_EM_INTERPRETER;
    1586     g_IemCtx = *pCtx;
    1587     g_fIemFFs = pVCpu->fLocalForcedActions;
    1588     *pcbWritten = cbIemWritten;
    1589     rc = rcIem;
    1590 #  endif
    1591 
    1592 #  if defined(VBOX_COMPARE_IEM_LAST) || defined(VBOX_COMPARE_IEM_FIRST)
    1593     emCompareWithIem(pVCpu, &g_EmCtx, &g_IemCtx, rcEm, rcIem, cbEmWritten, cbIemWritten);
    1594 #  endif
    1595 
    1596 # else
    15971151    VBOXSTRICTRC rc = IEMExecOneBypassEx(pVCpu, pRegFrame, pcbWritten);
    15981152    if (RT_UNLIKELY(   rc == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    15991153                    || rc == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    16001154        rc = VERR_EM_INTERPRETER;
    1601 # endif
    16021155    if (rc != VINF_SUCCESS)
    16031156        Log(("EMInterpretInstructionEx: returns %Rrc\n", VBOXSTRICTRC_VAL(rc)));
    16041157
    16051158    return rc;
    1606 #else
    1607     RTGCPTR pbCode;
    1608     VBOXSTRICTRC rc = SELMToFlatEx(pVCpu, DISSELREG_CS, pRegFrame, pRegFrame->rip, 0, &pbCode);
    1609     if (RT_SUCCESS(rc))
    1610     {
    1611         uint32_t     cbOp;
    1612         PDISCPUSTATE pDis = &pVCpu->em.s.DisState;
    1613         pDis->uCpuMode = CPUMGetGuestDisMode(pVCpu);
    1614         rc = emDisCoreOne(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, (RTGCUINTPTR)pbCode, &cbOp);
    1615         if (RT_SUCCESS(rc))
    1616         {
    1617             Assert(cbOp == pDis->cbInstr);
    1618             rc = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, EMCODETYPE_SUPERVISOR, pcbWritten);
    1619             if (RT_SUCCESS(rc))
    1620                 pRegFrame->rip += cbOp; /* Move on to the next instruction. */
    1621 
    1622             return rc;
    1623         }
    1624     }
    1625     return VERR_EM_INTERPRETER;
    1626 #endif
    16271159}
    16281160
     
    16591191    LogFlow(("EMInterpretInstructionDisasState %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
    16601192    Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    1661 #ifdef VBOX_WITH_IEM
    16621193    NOREF(pDis); NOREF(pvFault); NOREF(enmCodeType);
    16631194
    1664 # ifdef VBOX_COMPARE_IEM_AND_EM
    1665     PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
    1666     g_IncomingCtx = *pCtx;
    1667     g_fIncomingFFs = pVCpu->fLocalForcedActions;
    1668     g_cbEmWrote = g_cbIemWrote = 0;
    1669 
    1670 #  ifdef VBOX_COMPARE_IEM_FIRST
    1671     VBOXSTRICTRC rcIem = IEMExecOneBypassWithPrefetchedByPC(pVCpu, pRegFrame, pRegFrame->rip, pDis->abInstr, pDis->cbCachedInstr);
    1672     if (RT_UNLIKELY(   rcIem == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    1673                     || rcIem == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    1674         rcIem = VERR_EM_INTERPRETER;
    1675     g_IemCtx = *pCtx;
    1676     g_fIemFFs = pVCpu->fLocalForcedActions;
    1677     pVCpu->fLocalForcedActions = (pVCpu->fLocalForcedActions & ~g_fInterestingFFs) | (g_fIncomingFFs & g_fInterestingFFs);
    1678     *pCtx = g_IncomingCtx;
    1679 #  endif
    1680 
    1681     /* EM */
    1682     uint32_t cbIgnored;
    1683     VBOXSTRICTRC rcEm = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, enmCodeType, &cbIgnored);
    1684     if (RT_SUCCESS(rcEm))
    1685         pRegFrame->rip += pDis->cbInstr; /* Move on to the next instruction. */
    1686 #  ifdef VBOX_SAME_AS_EM
    1687     if (rcEm == VERR_EM_INTERPRETER)
    1688     {
    1689         Log(("EMInterpretInstruction: returns %Rrc\n", VBOXSTRICTRC_VAL(rcEm)));
    1690         return rcEm;
    1691     }
    1692 #  endif
    1693     g_EmCtx = *pCtx;
    1694     g_fEmFFs = pVCpu->fLocalForcedActions;
    1695     VBOXSTRICTRC rc = rcEm;
    1696 
    1697 #  ifdef VBOX_COMPARE_IEM_LAST
    1698     /* IEM */
    1699     pVCpu->fLocalForcedActions = (pVCpu->fLocalForcedActions & ~g_fInterestingFFs) | (g_fIncomingFFs & g_fInterestingFFs);
    1700     *pCtx = g_IncomingCtx;
    1701     VBOXSTRICTRC rcIem = IEMExecOneBypassWithPrefetchedByPC(pVCpu, pRegFrame, pRegFrame->rip, pDis->abInstr, pDis->cbCachedInstr);
    1702     if (RT_UNLIKELY(   rcIem == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    1703                     || rcIem == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    1704         rcIem = VERR_EM_INTERPRETER;
    1705     g_IemCtx = *pCtx;
    1706     g_fIemFFs = pVCpu->fLocalForcedActions;
    1707     rc = rcIem;
    1708 #  endif
    1709 
    1710 #  if defined(VBOX_COMPARE_IEM_LAST) || defined(VBOX_COMPARE_IEM_FIRST)
    1711     emCompareWithIem(pVCpu, &g_EmCtx, &g_IemCtx, rcEm, rcIem, 0, 0);
    1712 #  endif
    1713 
    1714 # else
    17151195    VBOXSTRICTRC rc = IEMExecOneBypassWithPrefetchedByPC(pVCpu, pRegFrame, pRegFrame->rip, pDis->abInstr, pDis->cbCachedInstr);
    17161196    if (RT_UNLIKELY(   rc == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    17171197                    || rc == VERR_IEM_INSTR_NOT_IMPLEMENTED))
    17181198        rc = VERR_EM_INTERPRETER;
    1719 # endif
    17201199
    17211200    if (rc != VINF_SUCCESS)
     
    17231202
    17241203    return rc;
    1725 #else
    1726     uint32_t cbIgnored;
    1727     VBOXSTRICTRC rc = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, enmCodeType, &cbIgnored);
    1728     if (RT_SUCCESS(rc))
    1729         pRegFrame->rip += pDis->cbInstr; /* Move on to the next instruction. */
    1730     return rc;
    1731 #endif
    17321204}
    17331205
     
    17981270}
    17991271
    1800 # ifndef VBOX_WITH_IEM
    1801 /**
    1802  * IRET Emulation.
    1803  */
    1804 static int emInterpretIret(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    1805 {
    1806 #ifdef VBOX_WITH_RAW_RING1
    1807     NOREF(pvFault); NOREF(pcbSize); NOREF(pDis);
    1808     if (EMIsRawRing1Enabled(pVM))
    1809     {
    1810         RTGCUINTPTR pIretStack = (RTGCUINTPTR)pRegFrame->esp;
    1811         RTGCUINTPTR eip, cs, esp, ss, eflags, uMask;
    1812         int         rc;
    1813         uint32_t    cpl, rpl;
    1814 
    1815         /* We only execute 32-bits protected mode code in raw mode, so no need to bother to check for 16-bits code here. */
    1816         /** @todo we don't verify all the edge cases that generate #GP faults */
    1817 
    1818         Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    1819         Assert(!CPUMIsGuestIn64BitCode(pVCpu));
    1820         /** @todo Rainy day: Test what happens when VERR_EM_INTERPRETER is returned by
    1821          *        this function.  Fear that it may guru on us, thus not converted to
    1822          *        IEM. */
    1823 
    1824         rc  = emRCStackRead(pVM, pVCpu, pRegFrame, &eip,      (RTGCPTR)pIretStack      , 4);
    1825         rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &cs,       (RTGCPTR)(pIretStack + 4), 4);
    1826         rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
    1827         AssertRCReturn(rc, VERR_EM_INTERPRETER);
    1828         AssertReturn(eflags & X86_EFL_VM, VERR_EM_INTERPRETER);
    1829 
    1830         /* Deal with V86 above. */
    1831         if (eflags & X86_EFL_VM)
    1832             return EMInterpretIretV86ForPatm(pVM, pVCpu, pRegFrame);
    1833 
    1834         cpl = CPUMRCGetGuestCPL(pVCpu, pRegFrame);
    1835         rpl = cs & X86_SEL_RPL;
    1836 
    1837         Log(("emInterpretIret: iret to CS:EIP=%04X:%08X eflags=%x\n", cs, eip, eflags));
    1838         if (rpl != cpl)
    1839         {
    1840             rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &esp,      (RTGCPTR)(pIretStack + 12), 4);
    1841             rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &ss,       (RTGCPTR)(pIretStack + 16), 4);
    1842             AssertRCReturn(rc, VERR_EM_INTERPRETER);
    1843             Log(("emInterpretIret: return to different privilege level (rpl=%d cpl=%d)\n", rpl, cpl));
    1844             Log(("emInterpretIret: SS:ESP=%04x:%08x\n", ss, esp));
    1845             pRegFrame->ss.Sel = ss;
    1846             pRegFrame->esp    = esp;
    1847         }
    1848         pRegFrame->cs.Sel = cs;
    1849         pRegFrame->eip    = eip;
    1850 
    1851         /* Adjust CS & SS as required. */
    1852         CPUMRCRecheckRawState(pVCpu, pRegFrame);
    1853 
    1854         /* Mask away all reserved bits */
    1855         uMask = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM | X86_EFL_AC | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_ID;
    1856         eflags &= uMask;
    1857 
    1858         CPUMRawSetEFlags(pVCpu, eflags);
    1859         Assert((pRegFrame->eflags.u32 & (X86_EFL_IF|X86_EFL_IOPL)) == X86_EFL_IF);
    1860         return VINF_SUCCESS;
    1861     }
    1862 #else
    1863     NOREF(pVM); NOREF(pVCpu); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
    1864 #endif
    1865     return VERR_EM_INTERPRETER;
    1866 }
    1867 # endif /* !VBOX_WITH_IEM */
    18681272
    18691273#endif /* IN_RC */
     
    21241528}
    21251529
    2126 
    2127 #if !defined(VBOX_WITH_IEM) || defined(VBOX_COMPARE_IEM_AND_EM)
    2128 
    2129 
    2130 
    2131 
    2132 
    2133 
    2134 /*
    2135  *
    2136  * The old interpreter.
    2137  * The old interpreter.
    2138  * The old interpreter.
    2139  * The old interpreter.
    2140  * The old interpreter.
    2141  *
    2142  */
    2143 
    2144 DECLINLINE(int) emRamRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb)
    2145 {
    2146 #ifdef IN_RC
    2147     int rc = MMGCRamRead(pVM, pvDst, (void *)(uintptr_t)GCPtrSrc, cb);
    2148     if (RT_LIKELY(rc != VERR_ACCESS_DENIED))
    2149         return rc;
    2150     /*
    2151      * The page pool cache may end up here in some cases because it
    2152      * flushed one of the shadow mappings used by the trapping
    2153      * instruction and it either flushed the TLB or the CPU reused it.
    2154      */
    2155 #else
    2156     NOREF(pVM);
    2157 #endif
    2158     return PGMPhysInterpretedReadNoHandlers(pVCpu, pCtxCore, pvDst, GCPtrSrc, cb, /*fMayTrap*/ false);
    2159 }
    2160 
    2161 
    2162 DECLINLINE(int) emRamWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, uint32_t cb)
    2163 {
    2164     /* Don't use MMGCRamWrite here as it does not respect zero pages, shared
    2165        pages or write monitored pages. */
    2166     NOREF(pVM);
    2167 #if !defined(VBOX_COMPARE_IEM_AND_EM) || !defined(VBOX_COMPARE_IEM_LAST)
    2168     int rc = PGMPhysInterpretedWriteNoHandlers(pVCpu, pCtxCore, GCPtrDst, pvSrc, cb, /*fMayTrap*/ false);
    2169 #else
    2170     int rc = VINF_SUCCESS;
    2171 #endif
    2172 #ifdef VBOX_COMPARE_IEM_AND_EM
    2173     Log(("EM Wrote: %RGv %.*Rhxs rc=%Rrc\n", GCPtrDst, RT_MAX(RT_MIN(cb, 64), 1), pvSrc, rc));
    2174     g_cbEmWrote = cb;
    2175     memcpy(g_abEmWrote, pvSrc, RT_MIN(cb, sizeof(g_abEmWrote)));
    2176 #endif
    2177     return rc;
    2178 }
    2179 
    2180 
    2181 /** Convert sel:addr to a flat GC address. */
    2182 DECLINLINE(RTGCPTR) emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pDis, PDISOPPARAM pParam, RTGCPTR pvAddr)
    2183 {
    2184     DISSELREG enmPrefixSeg = DISDetectSegReg(pDis, pParam);
    2185     return SELMToFlat(pVM, enmPrefixSeg, pRegFrame, pvAddr);
    2186 }
    2187 
    2188 
    2189 #if defined(VBOX_STRICT) || defined(LOG_ENABLED)
    2190 /**
    2191  * Get the mnemonic for the disassembled instruction.
    2192  *
    2193  * GC/R0 doesn't include the strings in the DIS tables because
    2194  * of limited space.
    2195  */
    2196 static const char *emGetMnemonic(PDISCPUSTATE pDis)
    2197 {
    2198     switch (pDis->pCurInstr->uOpcode)
    2199     {
    2200         case OP_XCHG:       return "Xchg";
    2201         case OP_DEC:        return "Dec";
    2202         case OP_INC:        return "Inc";
    2203         case OP_POP:        return "Pop";
    2204         case OP_OR:         return "Or";
    2205         case OP_AND:        return "And";
    2206         case OP_MOV:        return "Mov";
    2207         case OP_INVLPG:     return "InvlPg";
    2208         case OP_CPUID:      return "CpuId";
    2209         case OP_MOV_CR:     return "MovCRx";
    2210         case OP_MOV_DR:     return "MovDRx";
    2211         case OP_LLDT:       return "LLdt";
    2212         case OP_LGDT:       return "LGdt";
    2213         case OP_LIDT:       return "LIdt";
    2214         case OP_CLTS:       return "Clts";
    2215         case OP_MONITOR:    return "Monitor";
    2216         case OP_MWAIT:      return "MWait";
    2217         case OP_RDMSR:      return "Rdmsr";
    2218         case OP_WRMSR:      return "Wrmsr";
    2219         case OP_ADD:        return "Add";
    2220         case OP_ADC:        return "Adc";
    2221         case OP_SUB:        return "Sub";
    2222         case OP_SBB:        return "Sbb";
    2223         case OP_RDTSC:      return "Rdtsc";
    2224         case OP_STI:        return "Sti";
    2225         case OP_CLI:        return "Cli";
    2226         case OP_XADD:       return "XAdd";
    2227         case OP_HLT:        return "Hlt";
    2228         case OP_IRET:       return "Iret";
    2229         case OP_MOVNTPS:    return "MovNTPS";
    2230         case OP_STOSWD:     return "StosWD";
    2231         case OP_WBINVD:     return "WbInvd";
    2232         case OP_XOR:        return "Xor";
    2233         case OP_BTR:        return "Btr";
    2234         case OP_BTS:        return "Bts";
    2235         case OP_BTC:        return "Btc";
    2236         case OP_LMSW:       return "Lmsw";
    2237         case OP_SMSW:       return "Smsw";
    2238         case OP_CMPXCHG:    return pDis->fPrefix & DISPREFIX_LOCK ? "Lock CmpXchg"   : "CmpXchg";
    2239         case OP_CMPXCHG8B:  return pDis->fPrefix & DISPREFIX_LOCK ? "Lock CmpXchg8b" : "CmpXchg8b";
    2240 
    2241         default:
    2242             Log(("Unknown opcode %d\n", pDis->pCurInstr->uOpcode));
    2243             return "???";
    2244     }
    2245 }
    2246 #endif /* VBOX_STRICT || LOG_ENABLED */
    2247 
    2248 
    2249 /**
    2250  * XCHG instruction emulation.
    2251  */
    2252 static int emInterpretXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    2253 {
    2254     DISQPVPARAMVAL param1, param2;
    2255     NOREF(pvFault);
    2256 
    2257     /* Source to make DISQueryParamVal read the register value - ugly hack */
    2258     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    2259     if(RT_FAILURE(rc))
    2260         return VERR_EM_INTERPRETER;
    2261 
    2262     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2263     if(RT_FAILURE(rc))
    2264         return VERR_EM_INTERPRETER;
    2265 
    2266 #ifdef IN_RC
    2267     if (TRPMHasTrap(pVCpu))
    2268     {
    2269         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    2270         {
    2271 #endif
    2272             RTGCPTR pParam1 = 0, pParam2 = 0;
    2273             uint64_t valpar1, valpar2;
    2274 
    2275             AssertReturn(pDis->Param1.cb == pDis->Param2.cb, VERR_EM_INTERPRETER);
    2276             switch(param1.type)
    2277             {
    2278             case DISQPV_TYPE_IMMEDIATE: /* register type is translated to this one too */
    2279                 valpar1 = param1.val.val64;
    2280                 break;
    2281 
    2282             case DISQPV_TYPE_ADDRESS:
    2283                 pParam1 = (RTGCPTR)param1.val.val64;
    2284                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    2285                 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    2286                 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
    2287                 if (RT_FAILURE(rc))
    2288                 {
    2289                     AssertMsgFailed(("MMGCRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2290                     return VERR_EM_INTERPRETER;
    2291                 }
    2292                 break;
    2293 
    2294             default:
    2295                 AssertFailed();
    2296                 return VERR_EM_INTERPRETER;
    2297             }
    2298 
    2299             switch(param2.type)
    2300             {
    2301             case DISQPV_TYPE_ADDRESS:
    2302                 pParam2 = (RTGCPTR)param2.val.val64;
    2303                 pParam2 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param2, pParam2);
    2304                 EM_ASSERT_FAULT_RETURN(pParam2 == pvFault, VERR_EM_INTERPRETER);
    2305                 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar2, pParam2, param2.size);
    2306                 if (RT_FAILURE(rc))
    2307                 {
    2308                     AssertMsgFailed(("MMGCRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2309                 }
    2310                 break;
    2311 
    2312             case DISQPV_TYPE_IMMEDIATE:
    2313                 valpar2 = param2.val.val64;
    2314                 break;
    2315 
    2316             default:
    2317                 AssertFailed();
    2318                 return VERR_EM_INTERPRETER;
    2319             }
    2320 
    2321             /* Write value of parameter 2 to parameter 1 (reg or memory address) */
    2322             if (pParam1 == 0)
    2323             {
    2324                 Assert(param1.type == DISQPV_TYPE_IMMEDIATE); /* register actually */
    2325                 switch(param1.size)
    2326                 {
    2327                 case 1: //special case for AH etc
    2328                         rc = DISWriteReg8(pRegFrame, pDis->Param1.Base.idxGenReg,  (uint8_t )valpar2); break;
    2329                 case 2: rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, (uint16_t)valpar2); break;
    2330                 case 4: rc = DISWriteReg32(pRegFrame, pDis->Param1.Base.idxGenReg, (uint32_t)valpar2); break;
    2331                 case 8: rc = DISWriteReg64(pRegFrame, pDis->Param1.Base.idxGenReg, valpar2); break;
    2332                 default: AssertFailedReturn(VERR_EM_INTERPRETER);
    2333                 }
    2334                 if (RT_FAILURE(rc))
    2335                     return VERR_EM_INTERPRETER;
    2336             }
    2337             else
    2338             {
    2339                 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar2, param1.size);
    2340                 if (RT_FAILURE(rc))
    2341                 {
    2342                     AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2343                     return VERR_EM_INTERPRETER;
    2344                 }
    2345             }
    2346 
    2347             /* Write value of parameter 1 to parameter 2 (reg or memory address) */
    2348             if (pParam2 == 0)
    2349             {
    2350                 Assert(param2.type == DISQPV_TYPE_IMMEDIATE); /* register actually */
    2351                 switch(param2.size)
    2352                 {
    2353                 case 1: //special case for AH etc
    2354                         rc = DISWriteReg8(pRegFrame, pDis->Param2.Base.idxGenReg,  (uint8_t )valpar1);    break;
    2355                 case 2: rc = DISWriteReg16(pRegFrame, pDis->Param2.Base.idxGenReg, (uint16_t)valpar1);    break;
    2356                 case 4: rc = DISWriteReg32(pRegFrame, pDis->Param2.Base.idxGenReg, (uint32_t)valpar1);    break;
    2357                 case 8: rc = DISWriteReg64(pRegFrame, pDis->Param2.Base.idxGenReg, valpar1);              break;
    2358                 default: AssertFailedReturn(VERR_EM_INTERPRETER);
    2359                 }
    2360                 if (RT_FAILURE(rc))
    2361                     return VERR_EM_INTERPRETER;
    2362             }
    2363             else
    2364             {
    2365                 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam2, &valpar1, param2.size);
    2366                 if (RT_FAILURE(rc))
    2367                 {
    2368                     AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2369                     return VERR_EM_INTERPRETER;
    2370                 }
    2371             }
    2372 
    2373             *pcbSize = param2.size;
    2374             return VINF_SUCCESS;
    2375 #ifdef IN_RC
    2376         }
    2377     }
    2378     return VERR_EM_INTERPRETER;
    2379 #endif
    2380 }
    2381 
    2382 
    2383 /**
    2384  * INC and DEC emulation.
    2385  */
    2386 static int emInterpretIncDec(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
    2387                              PFNEMULATEPARAM2 pfnEmulate)
    2388 {
    2389     DISQPVPARAMVAL param1;
    2390     NOREF(pvFault);
    2391 
    2392     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2393     if(RT_FAILURE(rc))
    2394         return VERR_EM_INTERPRETER;
    2395 
    2396 #ifdef IN_RC
    2397     if (TRPMHasTrap(pVCpu))
    2398     {
    2399         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    2400         {
    2401 #endif
    2402             RTGCPTR pParam1 = 0;
    2403             uint64_t valpar1;
    2404 
    2405             if (param1.type == DISQPV_TYPE_ADDRESS)
    2406             {
    2407                 pParam1 = (RTGCPTR)param1.val.val64;
    2408                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    2409 #ifdef IN_RC
    2410                 /* Safety check (in theory it could cross a page boundary and fault there though) */
    2411                 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    2412 #endif
    2413                 rc = emRamRead(pVM, pVCpu, pRegFrame,  &valpar1, pParam1, param1.size);
    2414                 if (RT_FAILURE(rc))
    2415                 {
    2416                     AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2417                     return VERR_EM_INTERPRETER;
    2418                 }
    2419             }
    2420             else
    2421             {
    2422                 AssertFailed();
    2423                 return VERR_EM_INTERPRETER;
    2424             }
    2425 
    2426             uint32_t eflags;
    2427 
    2428             eflags = pfnEmulate(&valpar1, param1.size);
    2429 
    2430             /* Write result back */
    2431             rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
    2432             if (RT_FAILURE(rc))
    2433             {
    2434                 AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2435                 return VERR_EM_INTERPRETER;
    2436             }
    2437 
    2438             /* Update guest's eflags and finish. */
    2439             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32   & ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    2440                                   | (eflags & (X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    2441 
    2442             /* All done! */
    2443             *pcbSize = param1.size;
    2444             return VINF_SUCCESS;
    2445 #ifdef IN_RC
    2446         }
    2447     }
    2448     return VERR_EM_INTERPRETER;
    2449 #endif
    2450 }
    2451 
    2452 
    2453 /**
    2454  * POP Emulation.
    2455  */
    2456 static int emInterpretPop(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    2457 {
    2458     Assert(pDis->uCpuMode != DISCPUMODE_64BIT);    /** @todo check */
    2459     DISQPVPARAMVAL param1;
    2460     NOREF(pvFault);
    2461 
    2462     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2463     if(RT_FAILURE(rc))
    2464         return VERR_EM_INTERPRETER;
    2465 
    2466 #ifdef IN_RC
    2467     if (TRPMHasTrap(pVCpu))
    2468     {
    2469         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    2470         {
    2471 #endif
    2472             RTGCPTR pParam1 = 0;
    2473             uint32_t valpar1;
    2474             RTGCPTR pStackVal;
    2475 
    2476             /* Read stack value first */
    2477             if (CPUMGetGuestCodeBits(pVCpu) == 16)
    2478                 return VERR_EM_INTERPRETER; /* No legacy 16 bits stuff here, please. */
    2479 
    2480             /* Convert address; don't bother checking limits etc, as we only read here */
    2481             pStackVal = SELMToFlat(pVM, DISSELREG_SS, pRegFrame, (RTGCPTR)pRegFrame->esp);
    2482             if (pStackVal == 0)
    2483                 return VERR_EM_INTERPRETER;
    2484 
    2485             rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pStackVal, param1.size);
    2486             if (RT_FAILURE(rc))
    2487             {
    2488                 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2489                 return VERR_EM_INTERPRETER;
    2490             }
    2491 
    2492             if (param1.type == DISQPV_TYPE_ADDRESS)
    2493             {
    2494                 pParam1 = (RTGCPTR)param1.val.val64;
    2495 
    2496                 /* pop [esp+xx] uses esp after the actual pop! */
    2497                 AssertCompile(DISGREG_ESP == DISGREG_SP);
    2498                 if (    (pDis->Param1.fUse & DISUSE_BASE)
    2499                     &&  (pDis->Param1.fUse & (DISUSE_REG_GEN16|DISUSE_REG_GEN32))
    2500                     &&  pDis->Param1.Base.idxGenReg == DISGREG_ESP
    2501                    )
    2502                    pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + param1.size);
    2503 
    2504                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    2505                 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, VERR_EM_INTERPRETER);
    2506                 rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
    2507                 if (RT_FAILURE(rc))
    2508                 {
    2509                     AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2510                     return VERR_EM_INTERPRETER;
    2511                 }
    2512 
    2513                 /* Update ESP as the last step */
    2514                 pRegFrame->esp += param1.size;
    2515             }
    2516             else
    2517             {
    2518 #ifndef DEBUG_bird // annoying assertion.
    2519                 AssertFailed();
    2520 #endif
    2521                 return VERR_EM_INTERPRETER;
    2522             }
    2523 
    2524             /* All done! */
    2525             *pcbSize = param1.size;
    2526             return VINF_SUCCESS;
    2527 #ifdef IN_RC
    2528         }
    2529     }
    2530     return VERR_EM_INTERPRETER;
    2531 #endif
    2532 }
    2533 
    2534 
    2535 /**
    2536  * XOR/OR/AND Emulation.
    2537  */
    2538 static int emInterpretOrXorAnd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
    2539                                PFNEMULATEPARAM3 pfnEmulate)
    2540 {
    2541     DISQPVPARAMVAL param1, param2;
    2542     NOREF(pvFault);
    2543 
    2544     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2545     if(RT_FAILURE(rc))
    2546         return VERR_EM_INTERPRETER;
    2547 
    2548     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2549     if(RT_FAILURE(rc))
    2550         return VERR_EM_INTERPRETER;
    2551 
    2552 #ifdef IN_RC
    2553     if (TRPMHasTrap(pVCpu))
    2554     {
    2555         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    2556         {
    2557 #endif
    2558             RTGCPTR  pParam1;
    2559             uint64_t valpar1, valpar2;
    2560 
    2561             if (pDis->Param1.cb != pDis->Param2.cb)
    2562             {
    2563                 if (pDis->Param1.cb < pDis->Param2.cb)
    2564                 {
    2565                     AssertMsgFailed(("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip, pDis->Param1.cb, pDis->Param2.cb)); /* should never happen! */
    2566                     return VERR_EM_INTERPRETER;
    2567                 }
    2568                 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    2569                 pDis->Param2.cb = pDis->Param1.cb;
    2570                 param2.size     = param1.size;
    2571             }
    2572 
    2573             /* The destination is always a virtual address */
    2574             if (param1.type == DISQPV_TYPE_ADDRESS)
    2575             {
    2576                 pParam1 = (RTGCPTR)param1.val.val64;
    2577                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    2578                 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    2579                 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
    2580                 if (RT_FAILURE(rc))
    2581                 {
    2582                     AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2583                     return VERR_EM_INTERPRETER;
    2584                 }
    2585             }
    2586             else
    2587             {
    2588                 AssertFailed();
    2589                 return VERR_EM_INTERPRETER;
    2590             }
    2591 
    2592             /* Register or immediate data */
    2593             switch(param2.type)
    2594             {
    2595             case DISQPV_TYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    2596                 valpar2 = param2.val.val64;
    2597                 break;
    2598 
    2599             default:
    2600                 AssertFailed();
    2601                 return VERR_EM_INTERPRETER;
    2602             }
    2603 
    2604             LogFlow(("emInterpretOrXorAnd %s %RGv %RX64 - %RX64 size %d (%d)\n", emGetMnemonic(pDis), pParam1, valpar1, valpar2, param2.size, param1.size));
    2605 
    2606             /* Data read, emulate instruction. */
    2607             uint32_t eflags = pfnEmulate(&valpar1, valpar2, param2.size);
    2608 
    2609             LogFlow(("emInterpretOrXorAnd %s result %RX64\n", emGetMnemonic(pDis), valpar1));
    2610 
    2611             /* Update guest's eflags and finish. */
    2612             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    2613                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    2614 
    2615             /* And write it back */
    2616             rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
    2617             if (RT_SUCCESS(rc))
    2618             {
    2619                 /* All done! */
    2620                 *pcbSize = param2.size;
    2621                 return VINF_SUCCESS;
    2622             }
    2623 #ifdef IN_RC
    2624         }
    2625     }
    2626 #endif
    2627     return VERR_EM_INTERPRETER;
    2628 }
    2629 
    2630 
    2631 #ifndef VBOX_COMPARE_IEM_AND_EM
    2632 /**
    2633  * LOCK XOR/OR/AND Emulation.
    2634  */
    2635 static int emInterpretLockOrXorAnd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
    2636                                    uint32_t *pcbSize, PFNEMULATELOCKPARAM3 pfnEmulate)
    2637 {
    2638     void *pvParam1;
    2639     DISQPVPARAMVAL param1, param2;
    2640     NOREF(pvFault);
    2641 
    2642 #if HC_ARCH_BITS == 32
    2643     Assert(pDis->Param1.cb <= 4);
    2644 #endif
    2645 
    2646     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2647     if(RT_FAILURE(rc))
    2648         return VERR_EM_INTERPRETER;
    2649 
    2650     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2651     if(RT_FAILURE(rc))
    2652         return VERR_EM_INTERPRETER;
    2653 
    2654     if (pDis->Param1.cb != pDis->Param2.cb)
    2655     {
    2656         AssertMsgReturn(pDis->Param1.cb >= pDis->Param2.cb, /* should never happen! */
    2657                         ("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip, pDis->Param1.cb, pDis->Param2.cb),
    2658                         VERR_EM_INTERPRETER);
    2659 
    2660         /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    2661         pDis->Param2.cb = pDis->Param1.cb;
    2662         param2.size       = param1.size;
    2663     }
    2664 
    2665 #ifdef IN_RC
    2666     /* Safety check (in theory it could cross a page boundary and fault there though) */
    2667     Assert(   TRPMHasTrap(pVCpu)
    2668            && (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW));
    2669     EM_ASSERT_FAULT_RETURN(GCPtrPar1 == pvFault, VERR_EM_INTERPRETER);
    2670 #endif
    2671 
    2672     /* Register and immediate data == DISQPV_TYPE_IMMEDIATE */
    2673     AssertReturn(param2.type == DISQPV_TYPE_IMMEDIATE, VERR_EM_INTERPRETER);
    2674     RTGCUINTREG ValPar2 = param2.val.val64;
    2675 
    2676     /* The destination is always a virtual address */
    2677     AssertReturn(param1.type == DISQPV_TYPE_ADDRESS, VERR_EM_INTERPRETER);
    2678 
    2679     RTGCPTR GCPtrPar1 = param1.val.val64;
    2680     GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, GCPtrPar1);
    2681     PGMPAGEMAPLOCK Lock;
    2682     rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
    2683     AssertRCReturn(rc, VERR_EM_INTERPRETER);
    2684 
    2685     /* Try emulate it with a one-shot #PF handler in place. (RC) */
    2686     Log2(("%s %RGv imm%d=%RX64\n", emGetMnemonic(pDis), GCPtrPar1, pDis->Param2.cb*8, ValPar2));
    2687 
    2688     RTGCUINTREG32 eflags = 0;
    2689     rc = pfnEmulate(pvParam1, ValPar2, pDis->Param2.cb, &eflags);
    2690     PGMPhysReleasePageMappingLock(pVM, &Lock);
    2691     if (RT_FAILURE(rc))
    2692     {
    2693         Log(("%s %RGv imm%d=%RX64-> emulation failed due to page fault!\n", emGetMnemonic(pDis), GCPtrPar1, pDis->Param2.cb*8, ValPar2));
    2694         return VERR_EM_INTERPRETER;
    2695     }
    2696 
    2697     /* Update guest's eflags and finish. */
    2698     pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    2699                           | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    2700 
    2701     *pcbSize = param2.size;
    2702     return VINF_SUCCESS;
    2703 }
    2704 #endif /* !VBOX_COMPARE_IEM_AND_EM */
    2705 
    2706 
    2707 /**
    2708  * ADD, ADC & SUB Emulation.
    2709  */
    2710 static int emInterpretAddSub(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
    2711                              PFNEMULATEPARAM3 pfnEmulate)
    2712 {
    2713     NOREF(pvFault);
    2714     DISQPVPARAMVAL param1, param2;
    2715     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2716     if(RT_FAILURE(rc))
    2717         return VERR_EM_INTERPRETER;
    2718 
    2719     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2720     if(RT_FAILURE(rc))
    2721         return VERR_EM_INTERPRETER;
    2722 
    2723 #ifdef IN_RC
    2724     if (TRPMHasTrap(pVCpu))
    2725     {
    2726         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    2727         {
    2728 #endif
    2729             RTGCPTR  pParam1;
    2730             uint64_t valpar1, valpar2;
    2731 
    2732             if (pDis->Param1.cb != pDis->Param2.cb)
    2733             {
    2734                 if (pDis->Param1.cb < pDis->Param2.cb)
    2735                 {
    2736                     AssertMsgFailed(("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip, pDis->Param1.cb, pDis->Param2.cb)); /* should never happen! */
    2737                     return VERR_EM_INTERPRETER;
    2738                 }
    2739                 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    2740                 pDis->Param2.cb = pDis->Param1.cb;
    2741                 param2.size     = param1.size;
    2742             }
    2743 
    2744             /* The destination is always a virtual address */
    2745             if (param1.type == DISQPV_TYPE_ADDRESS)
    2746             {
    2747                 pParam1 = (RTGCPTR)param1.val.val64;
    2748                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    2749                 EM_ASSERT_FAULT_RETURN(pParam1 == pvFault, VERR_EM_INTERPRETER);
    2750                 rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, param1.size);
    2751                 if (RT_FAILURE(rc))
    2752                 {
    2753                     AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2754                     return VERR_EM_INTERPRETER;
    2755                 }
    2756             }
    2757             else
    2758             {
    2759 #ifndef DEBUG_bird
    2760                 AssertFailed();
    2761 #endif
    2762                 return VERR_EM_INTERPRETER;
    2763             }
    2764 
    2765             /* Register or immediate data */
    2766             switch(param2.type)
    2767             {
    2768             case DISQPV_TYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    2769                 valpar2 = param2.val.val64;
    2770                 break;
    2771 
    2772             default:
    2773                 AssertFailed();
    2774                 return VERR_EM_INTERPRETER;
    2775             }
    2776 
    2777             /* Data read, emulate instruction. */
    2778             uint32_t eflags = pfnEmulate(&valpar1, valpar2, param2.size);
    2779 
    2780             /* Update guest's eflags and finish. */
    2781             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    2782                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    2783 
    2784             /* And write it back */
    2785             rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, param1.size);
    2786             if (RT_SUCCESS(rc))
    2787             {
    2788                 /* All done! */
    2789                 *pcbSize = param2.size;
    2790                 return VINF_SUCCESS;
    2791             }
    2792 #ifdef IN_RC
    2793         }
    2794     }
    2795 #endif
    2796     return VERR_EM_INTERPRETER;
    2797 }
    2798 
    2799 
    2800 /**
    2801  * ADC Emulation.
    2802  */
    2803 static int emInterpretAdc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    2804 {
    2805     if (pRegFrame->eflags.Bits.u1CF)
    2806         return emInterpretAddSub(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize, EMEmulateAdcWithCarrySet);
    2807     else
    2808         return emInterpretAddSub(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize, EMEmulateAdd);
    2809 }
    2810 
    2811 
    2812 /**
    2813  * BTR/C/S Emulation.
    2814  */
    2815 static int emInterpretBitTest(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
    2816                               PFNEMULATEPARAM2UINT32 pfnEmulate)
    2817 {
    2818     DISQPVPARAMVAL param1, param2;
    2819     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2820     if(RT_FAILURE(rc))
    2821         return VERR_EM_INTERPRETER;
    2822 
    2823     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2824     if(RT_FAILURE(rc))
    2825         return VERR_EM_INTERPRETER;
    2826 
    2827 #ifdef IN_RC
    2828     if (TRPMHasTrap(pVCpu))
    2829     {
    2830         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    2831         {
    2832 #endif
    2833             RTGCPTR  pParam1;
    2834             uint64_t valpar1 = 0, valpar2;
    2835             uint32_t eflags;
    2836 
    2837             /* The destination is always a virtual address */
    2838             if (param1.type != DISQPV_TYPE_ADDRESS)
    2839                 return VERR_EM_INTERPRETER;
    2840 
    2841             pParam1 = (RTGCPTR)param1.val.val64;
    2842             pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    2843 
    2844             /* Register or immediate data */
    2845             switch(param2.type)
    2846             {
    2847             case DISQPV_TYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    2848                 valpar2 = param2.val.val64;
    2849                 break;
    2850 
    2851             default:
    2852                 AssertFailed();
    2853                 return VERR_EM_INTERPRETER;
    2854             }
    2855 
    2856             Log2(("emInterpret%s: pvFault=%RGv pParam1=%RGv val2=%x\n", emGetMnemonic(pDis), pvFault, pParam1, valpar2));
    2857             pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + valpar2/8);
    2858             EM_ASSERT_FAULT_RETURN((RTGCPTR)((RTGCUINTPTR)pParam1 & ~3) == pvFault, VERR_EM_INTERPRETER); NOREF(pvFault);
    2859             rc = emRamRead(pVM, pVCpu, pRegFrame, &valpar1, pParam1, 1);
    2860             if (RT_FAILURE(rc))
    2861             {
    2862                 AssertMsgFailed(("emRamRead %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    2863                 return VERR_EM_INTERPRETER;
    2864             }
    2865 
    2866             Log2(("emInterpretBtx: val=%x\n", valpar1));
    2867             /* Data read, emulate bit test instruction. */
    2868             eflags = pfnEmulate(&valpar1, valpar2 & 0x7);
    2869 
    2870             Log2(("emInterpretBtx: val=%x CF=%d\n", valpar1, !!(eflags & X86_EFL_CF)));
    2871 
    2872             /* Update guest's eflags and finish. */
    2873             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    2874                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    2875 
    2876             /* And write it back */
    2877             rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &valpar1, 1);
    2878             if (RT_SUCCESS(rc))
    2879             {
    2880                 /* All done! */
    2881                 *pcbSize = 1;
    2882                 return VINF_SUCCESS;
    2883             }
    2884 #ifdef IN_RC
    2885         }
    2886     }
    2887 #endif
    2888     return VERR_EM_INTERPRETER;
    2889 }
    2890 
    2891 
    2892 #ifndef VBOX_COMPARE_IEM_AND_EM
    2893 /**
    2894  * LOCK BTR/C/S Emulation.
    2895  */
    2896 static int emInterpretLockBitTest(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
    2897                                   uint32_t *pcbSize, PFNEMULATELOCKPARAM2 pfnEmulate)
    2898 {
    2899     void *pvParam1;
    2900 
    2901     DISQPVPARAMVAL param1, param2;
    2902     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2903     if(RT_FAILURE(rc))
    2904         return VERR_EM_INTERPRETER;
    2905 
    2906     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2907     if(RT_FAILURE(rc))
    2908         return VERR_EM_INTERPRETER;
    2909 
    2910     /* The destination is always a virtual address */
    2911     if (param1.type != DISQPV_TYPE_ADDRESS)
    2912         return VERR_EM_INTERPRETER;
    2913 
    2914     /* Register and immediate data == DISQPV_TYPE_IMMEDIATE */
    2915     AssertReturn(param2.type == DISQPV_TYPE_IMMEDIATE, VERR_EM_INTERPRETER);
    2916     uint64_t ValPar2 = param2.val.val64;
    2917 
    2918     /* Adjust the parameters so what we're dealing with is a bit within the byte pointed to. */
    2919     RTGCPTR GCPtrPar1 = param1.val.val64;
    2920     GCPtrPar1 = (GCPtrPar1 + ValPar2 / 8);
    2921     ValPar2 &= 7;
    2922 
    2923     GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, GCPtrPar1);
    2924 #ifdef IN_RC
    2925     Assert(TRPMHasTrap(pVCpu));
    2926     EM_ASSERT_FAULT_RETURN((RTGCPTR)((RTGCUINTPTR)GCPtrPar1 & ~(RTGCUINTPTR)3) == pvFault, VERR_EM_INTERPRETER);
    2927 #endif
    2928 
    2929     PGMPAGEMAPLOCK Lock;
    2930     rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
    2931     AssertRCReturn(rc, VERR_EM_INTERPRETER);
    2932 
    2933     Log2(("emInterpretLockBitTest %s: pvFault=%RGv GCPtrPar1=%RGv imm=%RX64\n", emGetMnemonic(pDis), pvFault, GCPtrPar1, ValPar2));
    2934     NOREF(pvFault);
    2935 
    2936     /* Try emulate it with a one-shot #PF handler in place. (RC) */
    2937     RTGCUINTREG32 eflags = 0;
    2938     rc = pfnEmulate(pvParam1, ValPar2, &eflags);
    2939     PGMPhysReleasePageMappingLock(pVM, &Lock);
    2940     if (RT_FAILURE(rc))
    2941     {
    2942         Log(("emInterpretLockBitTest %s: %RGv imm%d=%RX64 -> emulation failed due to page fault!\n",
    2943              emGetMnemonic(pDis), GCPtrPar1, pDis->Param2.cb*8, ValPar2));
    2944         return VERR_EM_INTERPRETER;
    2945     }
    2946 
    2947     Log2(("emInterpretLockBitTest %s: GCPtrPar1=%RGv imm=%RX64 CF=%d\n", emGetMnemonic(pDis), GCPtrPar1, ValPar2, !!(eflags & X86_EFL_CF)));
    2948 
    2949     /* Update guest's eflags and finish. */
    2950     pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    2951                           | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    2952 
    2953     *pcbSize = 1;
    2954     return VINF_SUCCESS;
    2955 }
    2956 #endif /* !VBOX_COMPARE_IEM_AND_EM */
    2957 
    2958 
    2959 /**
    2960  * MOV emulation.
    2961  */
    2962 static int emInterpretMov(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    2963 {
    2964     NOREF(pvFault);
    2965     DISQPVPARAMVAL param1, param2;
    2966     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_DST);
    2967     if(RT_FAILURE(rc))
    2968         return VERR_EM_INTERPRETER;
    2969 
    2970     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    2971     if(RT_FAILURE(rc))
    2972         return VERR_EM_INTERPRETER;
    2973 
    2974     /* If destination is a segment register, punt. We can't handle it here.
    2975      * NB: Source can be a register and still trigger a #PF!
    2976      */
    2977     if (RT_UNLIKELY(pDis->Param1.fUse == DISUSE_REG_SEG))
    2978         return VERR_EM_INTERPRETER;
    2979 
    2980     if (param1.type == DISQPV_TYPE_ADDRESS)
    2981     {
    2982         RTGCPTR pDest;
    2983         uint64_t val64;
    2984 
    2985         switch(param1.type)
    2986         {
    2987         case DISQPV_TYPE_IMMEDIATE:
    2988             if(!(param1.flags  & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
    2989                 return VERR_EM_INTERPRETER;
    2990             RT_FALL_THRU();
    2991 
    2992         case DISQPV_TYPE_ADDRESS:
    2993             pDest = (RTGCPTR)param1.val.val64;
    2994             pDest = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pDest);
    2995             break;
    2996 
    2997         default:
    2998             AssertFailed();
    2999             return VERR_EM_INTERPRETER;
    3000         }
    3001 
    3002         switch(param2.type)
    3003         {
    3004         case DISQPV_TYPE_IMMEDIATE: /* register type is translated to this one too */
    3005             val64 = param2.val.val64;
    3006             break;
    3007 
    3008         default:
    3009             Log(("emInterpretMov: unexpected type=%d rip=%RGv\n", param2.type, (RTGCPTR)pRegFrame->rip));
    3010             return VERR_EM_INTERPRETER;
    3011         }
    3012 #ifdef LOG_ENABLED
    3013         if (pDis->uCpuMode == DISCPUMODE_64BIT)
    3014             LogFlow(("EMInterpretInstruction at %RGv: OP_MOV %RGv <- %RX64 (%d) &val64=%RHv\n", (RTGCPTR)pRegFrame->rip, pDest, val64, param2.size, &val64));
    3015         else
    3016             LogFlow(("EMInterpretInstruction at %08RX64: OP_MOV %RGv <- %08X  (%d) &val64=%RHv\n", pRegFrame->rip, pDest, (uint32_t)val64, param2.size, &val64));
    3017 #endif
    3018 
    3019         Assert(param2.size <= 8 && param2.size > 0);
    3020         EM_ASSERT_FAULT_RETURN(pDest == pvFault, VERR_EM_INTERPRETER);
    3021         rc = emRamWrite(pVM, pVCpu, pRegFrame, pDest, &val64, param2.size);
    3022         if (RT_FAILURE(rc))
    3023             return VERR_EM_INTERPRETER;
    3024 
    3025         *pcbSize = param2.size;
    3026     }
    3027 #if defined(IN_RC) && defined(VBOX_WITH_RAW_RING1)
    3028     /* mov xx, cs instruction is dangerous in raw mode and replaced by an 'int3' by csam/patm. */
    3029     else if (   param1.type == DISQPV_TYPE_REGISTER
    3030              && param2.type == DISQPV_TYPE_REGISTER)
    3031     {
    3032         AssertReturn((pDis->Param1.fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32)), VERR_EM_INTERPRETER);
    3033         AssertReturn(pDis->Param2.fUse == DISUSE_REG_SEG, VERR_EM_INTERPRETER);
    3034         AssertReturn(pDis->Param2.Base.idxSegReg == DISSELREG_CS, VERR_EM_INTERPRETER);
    3035 
    3036         uint32_t u32Cpl = CPUMRCGetGuestCPL(pVCpu, pRegFrame);
    3037         uint32_t uValCS = (pRegFrame->cs.Sel & ~X86_SEL_RPL) | u32Cpl;
    3038 
    3039         Log(("EMInterpretInstruction: OP_MOV cs=%x->%x\n", pRegFrame->cs.Sel, uValCS));
    3040         switch (param1.size)
    3041         {
    3042         case 1: rc = DISWriteReg8(pRegFrame, pDis->Param1.Base.idxGenReg,  (uint8_t) uValCS); break;
    3043         case 2: rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, (uint16_t)uValCS); break;
    3044         case 4: rc = DISWriteReg32(pRegFrame, pDis->Param1.Base.idxGenReg, (uint32_t)uValCS); break;
    3045         default:
    3046             AssertFailed();
    3047             return VERR_EM_INTERPRETER;
    3048         }
    3049         AssertRCReturn(rc, rc);
    3050     }
    3051 #endif
    3052     else
    3053     { /* read fault */
    3054         RTGCPTR pSrc;
    3055         uint64_t val64;
    3056 
    3057         /* Source */
    3058         switch(param2.type)
    3059         {
    3060         case DISQPV_TYPE_IMMEDIATE:
    3061             if(!(param2.flags & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
    3062                 return VERR_EM_INTERPRETER;
    3063             RT_FALL_THRU();
    3064 
    3065         case DISQPV_TYPE_ADDRESS:
    3066             pSrc = (RTGCPTR)param2.val.val64;
    3067             pSrc = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param2, pSrc);
    3068             break;
    3069 
    3070         default:
    3071             return VERR_EM_INTERPRETER;
    3072         }
    3073 
    3074         Assert(param1.size <= 8 && param1.size > 0);
    3075         EM_ASSERT_FAULT_RETURN(pSrc == pvFault, VERR_EM_INTERPRETER);
    3076         rc = emRamRead(pVM, pVCpu, pRegFrame, &val64, pSrc, param1.size);
    3077         if (RT_FAILURE(rc))
    3078             return VERR_EM_INTERPRETER;
    3079 
    3080         /* Destination */
    3081         switch(param1.type)
    3082         {
    3083         case DISQPV_TYPE_REGISTER:
    3084             switch(param1.size)
    3085             {
    3086             case 1: rc = DISWriteReg8(pRegFrame, pDis->Param1.Base.idxGenReg,  (uint8_t) val64); break;
    3087             case 2: rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, (uint16_t)val64); break;
    3088             case 4: rc = DISWriteReg32(pRegFrame, pDis->Param1.Base.idxGenReg, (uint32_t)val64); break;
    3089             case 8: rc = DISWriteReg64(pRegFrame, pDis->Param1.Base.idxGenReg, val64); break;
    3090             default:
    3091                 return VERR_EM_INTERPRETER;
    3092             }
    3093             if (RT_FAILURE(rc))
    3094                 return rc;
    3095             break;
    3096 
    3097         default:
    3098             return VERR_EM_INTERPRETER;
    3099         }
    3100 #ifdef LOG_ENABLED
    3101         if (pDis->uCpuMode == DISCPUMODE_64BIT)
    3102             LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %RX64 (%d)\n", pSrc, val64, param1.size));
    3103         else
    3104             LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %08X (%d)\n", pSrc, (uint32_t)val64, param1.size));
    3105 #endif
    3106     }
    3107     return VINF_SUCCESS;
    3108 }
    3109 
    3110 
    3111 #ifndef IN_RC
    3112 /**
    3113  * [REP] STOSWD emulation
    3114  */
    3115 static int emInterpretStosWD(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3116 {
    3117     int      rc;
    3118     RTGCPTR  GCDest, GCOffset;
    3119     uint32_t cbSize;
    3120     uint64_t cTransfers;
    3121     int      offIncrement;
    3122     NOREF(pvFault);
    3123 
    3124     /* Don't support any but these three prefix bytes. */
    3125     if ((pDis->fPrefix & ~(DISPREFIX_ADDRSIZE|DISPREFIX_OPSIZE|DISPREFIX_REP|DISPREFIX_REX)))
    3126         return VERR_EM_INTERPRETER;
    3127 
    3128     switch (pDis->uAddrMode)
    3129     {
    3130     case DISCPUMODE_16BIT:
    3131         GCOffset   = pRegFrame->di;
    3132         cTransfers = pRegFrame->cx;
    3133         break;
    3134     case DISCPUMODE_32BIT:
    3135         GCOffset   = pRegFrame->edi;
    3136         cTransfers = pRegFrame->ecx;
    3137         break;
    3138     case DISCPUMODE_64BIT:
    3139         GCOffset   = pRegFrame->rdi;
    3140         cTransfers = pRegFrame->rcx;
    3141         break;
    3142     default:
    3143         AssertFailed();
    3144         return VERR_EM_INTERPRETER;
    3145     }
    3146 
    3147     GCDest = SELMToFlat(pVM, DISSELREG_ES, pRegFrame, GCOffset);
    3148     switch (pDis->uOpMode)
    3149     {
    3150     case DISCPUMODE_16BIT:
    3151         cbSize = 2;
    3152         break;
    3153     case DISCPUMODE_32BIT:
    3154         cbSize = 4;
    3155         break;
    3156     case DISCPUMODE_64BIT:
    3157         cbSize = 8;
    3158         break;
    3159     default:
    3160         AssertFailed();
    3161         return VERR_EM_INTERPRETER;
    3162     }
    3163 
    3164     offIncrement = pRegFrame->eflags.Bits.u1DF ? -(signed)cbSize : (signed)cbSize;
    3165 
    3166     if (!(pDis->fPrefix & DISPREFIX_REP))
    3167     {
    3168         LogFlow(("emInterpretStosWD dest=%04X:%RGv (%RGv) cbSize=%d\n", pRegFrame->es.Sel, GCOffset, GCDest, cbSize));
    3169 
    3170         rc = emRamWrite(pVM, pVCpu, pRegFrame, GCDest, &pRegFrame->rax, cbSize);
    3171         if (RT_FAILURE(rc))
    3172             return VERR_EM_INTERPRETER;
    3173         Assert(rc == VINF_SUCCESS);
    3174 
    3175         /* Update (e/r)di. */
    3176         switch (pDis->uAddrMode)
    3177         {
    3178         case DISCPUMODE_16BIT:
    3179             pRegFrame->di  += offIncrement;
    3180             break;
    3181         case DISCPUMODE_32BIT:
    3182             pRegFrame->edi += offIncrement;
    3183             break;
    3184         case DISCPUMODE_64BIT:
    3185             pRegFrame->rdi += offIncrement;
    3186             break;
    3187         default:
    3188             AssertFailed();
    3189             return VERR_EM_INTERPRETER;
    3190         }
    3191 
    3192     }
    3193     else
    3194     {
    3195         if (!cTransfers)
    3196             return VINF_SUCCESS;
    3197 
    3198         /*
    3199          * Do *not* try emulate cross page stuff here because we don't know what might
    3200          * be waiting for us on the subsequent pages. The caller has only asked us to
    3201          * ignore access handlers fro the current page.
    3202          * This also fends off big stores which would quickly kill PGMR0DynMap.
    3203          */
    3204         if (    cbSize > PAGE_SIZE
    3205             ||  cTransfers > PAGE_SIZE
    3206             ||  (GCDest >> PAGE_SHIFT) != ((GCDest + offIncrement * cTransfers) >> PAGE_SHIFT))
    3207         {
    3208             Log(("STOSWD is crosses pages, chicken out to the recompiler; GCDest=%RGv cbSize=%#x offIncrement=%d cTransfers=%#x\n",
    3209                  GCDest, cbSize, offIncrement, cTransfers));
    3210             return VERR_EM_INTERPRETER;
    3211         }
    3212 
    3213         LogFlow(("emInterpretStosWD dest=%04X:%RGv (%RGv) cbSize=%d cTransfers=%x DF=%d\n", pRegFrame->es.Sel, GCOffset, GCDest, cbSize, cTransfers, pRegFrame->eflags.Bits.u1DF));
    3214         /* Access verification first; we currently can't recover properly from traps inside this instruction */
    3215         rc = PGMVerifyAccess(pVCpu, GCDest - ((offIncrement > 0) ? 0 : ((cTransfers-1) * cbSize)),
    3216                              cTransfers * cbSize,
    3217                              X86_PTE_RW | (CPUMGetGuestCPL(pVCpu) == 3 ? X86_PTE_US : 0));
    3218         if (rc != VINF_SUCCESS)
    3219         {
    3220             Log(("STOSWD will generate a trap -> recompiler, rc=%d\n", rc));
    3221             return VERR_EM_INTERPRETER;
    3222         }
    3223 
    3224         /* REP case */
    3225         while (cTransfers)
    3226         {
    3227             rc = emRamWrite(pVM, pVCpu, pRegFrame, GCDest, &pRegFrame->rax, cbSize);
    3228             if (RT_FAILURE(rc))
    3229             {
    3230                 rc = VERR_EM_INTERPRETER;
    3231                 break;
    3232             }
    3233 
    3234             Assert(rc == VINF_SUCCESS);
    3235             GCOffset += offIncrement;
    3236             GCDest   += offIncrement;
    3237             cTransfers--;
    3238         }
    3239 
    3240         /* Update the registers. */
    3241         switch (pDis->uAddrMode)
    3242         {
    3243         case DISCPUMODE_16BIT:
    3244             pRegFrame->di = GCOffset;
    3245             pRegFrame->cx = cTransfers;
    3246             break;
    3247         case DISCPUMODE_32BIT:
    3248             pRegFrame->edi = GCOffset;
    3249             pRegFrame->ecx = cTransfers;
    3250             break;
    3251         case DISCPUMODE_64BIT:
    3252             pRegFrame->rdi = GCOffset;
    3253             pRegFrame->rcx = cTransfers;
    3254             break;
    3255         default:
    3256             AssertFailed();
    3257             return VERR_EM_INTERPRETER;
    3258         }
    3259     }
    3260 
    3261     *pcbSize = cbSize;
    3262     return rc;
    3263 }
    3264 #endif /* !IN_RC */
    3265 
    3266 
    3267 /**
    3268  * [LOCK] CMPXCHG emulation.
    3269  */
    3270 static int emInterpretCmpXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3271 {
    3272     DISQPVPARAMVAL param1, param2;
    3273     NOREF(pvFault);
    3274 
    3275 #if HC_ARCH_BITS == 32
    3276     Assert(pDis->Param1.cb <= 4);
    3277 #endif
    3278 
    3279     /* Source to make DISQueryParamVal read the register value - ugly hack */
    3280     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3281     if(RT_FAILURE(rc))
    3282         return VERR_EM_INTERPRETER;
    3283 
    3284     rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param2, &param2, DISQPVWHICH_SRC);
    3285     if(RT_FAILURE(rc))
    3286         return VERR_EM_INTERPRETER;
    3287 
    3288     uint64_t valpar;
    3289     switch(param2.type)
    3290     {
    3291     case DISQPV_TYPE_IMMEDIATE: /* register actually */
    3292         valpar = param2.val.val64;
    3293         break;
    3294 
    3295     default:
    3296         return VERR_EM_INTERPRETER;
    3297     }
    3298 
    3299     PGMPAGEMAPLOCK Lock;
    3300     RTGCPTR  GCPtrPar1;
    3301     void    *pvParam1;
    3302     uint64_t eflags;
    3303 
    3304     AssertReturn(pDis->Param1.cb == pDis->Param2.cb, VERR_EM_INTERPRETER);
    3305     switch(param1.type)
    3306     {
    3307     case DISQPV_TYPE_ADDRESS:
    3308         GCPtrPar1 = param1.val.val64;
    3309         GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, GCPtrPar1);
    3310 
    3311         rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
    3312         AssertRCReturn(rc, VERR_EM_INTERPRETER);
    3313         break;
    3314 
    3315     default:
    3316         return VERR_EM_INTERPRETER;
    3317     }
    3318 
    3319     LogFlow(("%s %RGv rax=%RX64 %RX64\n", emGetMnemonic(pDis), GCPtrPar1, pRegFrame->rax, valpar));
    3320 
    3321 #ifndef VBOX_COMPARE_IEM_AND_EM
    3322     if (pDis->fPrefix & DISPREFIX_LOCK)
    3323         eflags = EMEmulateLockCmpXchg(pvParam1, &pRegFrame->rax, valpar, pDis->Param2.cb);
    3324     else
    3325         eflags = EMEmulateCmpXchg(pvParam1, &pRegFrame->rax, valpar, pDis->Param2.cb);
    3326 #else  /* VBOX_COMPARE_IEM_AND_EM */
    3327     uint64_t u64;
    3328     switch (pDis->Param2.cb)
    3329     {
    3330         case 1: u64 = *(uint8_t  *)pvParam1; break;
    3331         case 2: u64 = *(uint16_t *)pvParam1; break;
    3332         case 4: u64 = *(uint32_t *)pvParam1; break;
    3333         default:
    3334         case 8: u64 = *(uint64_t *)pvParam1; break;
    3335     }
    3336     eflags = EMEmulateCmpXchg(&u64, &pRegFrame->rax, valpar, pDis->Param2.cb);
    3337     int rc2 = emRamWrite(pVM, pVCpu, pRegFrame, GCPtrPar1, &u64, pDis->Param2.cb); AssertRCSuccess(rc2);
    3338 #endif /* VBOX_COMPARE_IEM_AND_EM */
    3339 
    3340     LogFlow(("%s %RGv rax=%RX64 %RX64 ZF=%d\n", emGetMnemonic(pDis), GCPtrPar1, pRegFrame->rax, valpar, !!(eflags & X86_EFL_ZF)));
    3341 
    3342     /* Update guest's eflags and finish. */
    3343     pRegFrame->eflags.u32 =   (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    3344                             | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    3345 
    3346     *pcbSize = param2.size;
    3347     PGMPhysReleasePageMappingLock(pVM, &Lock);
    3348     return VINF_SUCCESS;
    3349 }
    3350 
    3351 
    3352 /**
    3353  * [LOCK] CMPXCHG8B emulation.
    3354  */
    3355 static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3356 {
    3357     DISQPVPARAMVAL param1;
    3358     NOREF(pvFault);
    3359 
    3360     /* Source to make DISQueryParamVal read the register value - ugly hack */
    3361     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3362     if(RT_FAILURE(rc))
    3363         return VERR_EM_INTERPRETER;
    3364 
    3365     RTGCPTR  GCPtrPar1;
    3366     void    *pvParam1;
    3367     uint64_t eflags;
    3368     PGMPAGEMAPLOCK Lock;
    3369 
    3370     AssertReturn(pDis->Param1.cb == 8, VERR_EM_INTERPRETER);
    3371     switch(param1.type)
    3372     {
    3373     case DISQPV_TYPE_ADDRESS:
    3374         GCPtrPar1 = param1.val.val64;
    3375         GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, GCPtrPar1);
    3376 
    3377         rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
    3378         AssertRCReturn(rc, VERR_EM_INTERPRETER);
    3379         break;
    3380 
    3381     default:
    3382         return VERR_EM_INTERPRETER;
    3383     }
    3384 
    3385     LogFlow(("%s %RGv=%p eax=%08x\n", emGetMnemonic(pDis), GCPtrPar1, pvParam1, pRegFrame->eax));
    3386 
    3387 #ifndef VBOX_COMPARE_IEM_AND_EM
    3388     if (pDis->fPrefix & DISPREFIX_LOCK)
    3389         eflags = EMEmulateLockCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
    3390     else
    3391         eflags = EMEmulateCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
    3392 #else  /* VBOX_COMPARE_IEM_AND_EM */
    3393     uint64_t u64 = *(uint64_t *)pvParam1;
    3394     eflags = EMEmulateCmpXchg8b(&u64, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
    3395     int rc2 = emRamWrite(pVM, pVCpu, pRegFrame, GCPtrPar1, &u64, sizeof(u64)); AssertRCSuccess(rc2);
    3396 #endif /* VBOX_COMPARE_IEM_AND_EM */
    3397 
    3398     LogFlow(("%s %RGv=%p eax=%08x ZF=%d\n", emGetMnemonic(pDis), GCPtrPar1, pvParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
    3399 
    3400     /* Update guest's eflags and finish; note that *only* ZF is affected. */
    3401     pRegFrame->eflags.u32 =   (pRegFrame->eflags.u32 & ~(X86_EFL_ZF))
    3402                             | (eflags                &  (X86_EFL_ZF));
    3403 
    3404     *pcbSize = 8;
    3405     PGMPhysReleasePageMappingLock(pVM, &Lock);
    3406     return VINF_SUCCESS;
    3407 }
    3408 
    3409 
    3410 #ifdef IN_RC /** @todo test+enable for HM as well. */
    3411 /**
    3412  * [LOCK] XADD emulation.
    3413  */
    3414 static int emInterpretXAdd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3415 {
    3416     Assert(pDis->uCpuMode != DISCPUMODE_64BIT);    /** @todo check */
    3417     DISQPVPARAMVAL param1;
    3418     void *pvParamReg2;
    3419     size_t cbParamReg2;
    3420     NOREF(pvFault);
    3421 
    3422     /* Source to make DISQueryParamVal read the register value - ugly hack */
    3423     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3424     if(RT_FAILURE(rc))
    3425         return VERR_EM_INTERPRETER;
    3426 
    3427     rc = DISQueryParamRegPtr(pRegFrame, pDis, &pDis->Param2, &pvParamReg2, &cbParamReg2);
    3428     Assert(cbParamReg2 <= 4);
    3429     if(RT_FAILURE(rc))
    3430         return VERR_EM_INTERPRETER;
    3431 
    3432 #ifdef IN_RC
    3433     if (TRPMHasTrap(pVCpu))
    3434     {
    3435         if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
    3436         {
    3437 #endif
    3438             RTGCPTR         GCPtrPar1;
    3439             void           *pvParam1;
    3440             uint32_t        eflags;
    3441             PGMPAGEMAPLOCK  Lock;
    3442 
    3443             AssertReturn(pDis->Param1.cb == pDis->Param2.cb, VERR_EM_INTERPRETER);
    3444             switch(param1.type)
    3445             {
    3446             case DISQPV_TYPE_ADDRESS:
    3447                 GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, (RTRCUINTPTR)param1.val.val64);
    3448 #ifdef IN_RC
    3449                 EM_ASSERT_FAULT_RETURN(GCPtrPar1 == pvFault, VERR_EM_INTERPRETER);
    3450 #endif
    3451 
    3452                 rc = PGMPhysGCPtr2CCPtr(pVCpu, GCPtrPar1, &pvParam1, &Lock);
    3453                 AssertRCReturn(rc, VERR_EM_INTERPRETER);
    3454                 break;
    3455 
    3456             default:
    3457                 return VERR_EM_INTERPRETER;
    3458             }
    3459 
    3460             LogFlow(("XAdd %RGv=%p reg=%08llx\n", GCPtrPar1, pvParam1, *(uint64_t *)pvParamReg2));
    3461 
    3462 #ifndef VBOX_COMPARE_IEM_AND_EM
    3463             if (pDis->fPrefix & DISPREFIX_LOCK)
    3464                 eflags = EMEmulateLockXAdd(pvParam1, pvParamReg2, cbParamReg2);
    3465             else
    3466                 eflags = EMEmulateXAdd(pvParam1, pvParamReg2, cbParamReg2);
    3467 #else  /* VBOX_COMPARE_IEM_AND_EM */
    3468             uint64_t u64;
    3469             switch (cbParamReg2)
    3470             {
    3471                 case 1: u64 = *(uint8_t  *)pvParam1; break;
    3472                 case 2: u64 = *(uint16_t *)pvParam1; break;
    3473                 case 4: u64 = *(uint32_t *)pvParam1; break;
    3474                 default:
    3475                 case 8: u64 = *(uint64_t *)pvParam1; break;
    3476             }
    3477             eflags = EMEmulateXAdd(&u64, pvParamReg2, cbParamReg2);
    3478             int rc2 = emRamWrite(pVM, pVCpu, pRegFrame, GCPtrPar1, &u64, pDis->Param2.cb); AssertRCSuccess(rc2);
    3479 #endif /* VBOX_COMPARE_IEM_AND_EM */
    3480 
    3481             LogFlow(("XAdd %RGv=%p reg=%08llx ZF=%d\n", GCPtrPar1, pvParam1, *(uint64_t *)pvParamReg2, !!(eflags & X86_EFL_ZF) ));
    3482 
    3483             /* Update guest's eflags and finish. */
    3484             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    3485                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    3486 
    3487             *pcbSize = cbParamReg2;
    3488             PGMPhysReleasePageMappingLock(pVM, &Lock);
    3489             return VINF_SUCCESS;
    3490 #ifdef IN_RC
    3491         }
    3492     }
    3493 
    3494     return VERR_EM_INTERPRETER;
    3495 #endif
    3496 }
    3497 #endif /* IN_RC */
    3498 
    3499 
    3500 /**
    3501  * WBINVD Emulation.
    3502  */
    3503 static int emInterpretWbInvd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3504 {
    3505     /* Nothing to do. */
    3506     NOREF(pVM); NOREF(pVCpu); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
    3507     return VINF_SUCCESS;
    3508 }
    3509 
    3510 
    3511 /**
    3512  * INVLPG Emulation.
    3513  */
    3514 static VBOXSTRICTRC emInterpretInvlPg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3515 {
    3516     DISQPVPARAMVAL param1;
    3517     RTGCPTR     addr;
    3518     NOREF(pvFault); NOREF(pVM); NOREF(pcbSize);
    3519 
    3520     VBOXSTRICTRC rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3521     if(RT_FAILURE(rc))
    3522         return VERR_EM_INTERPRETER;
    3523 
    3524     switch(param1.type)
    3525     {
    3526     case DISQPV_TYPE_IMMEDIATE:
    3527     case DISQPV_TYPE_ADDRESS:
    3528         if(!(param1.flags  & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
    3529             return VERR_EM_INTERPRETER;
    3530         addr = (RTGCPTR)param1.val.val64;
    3531         break;
    3532 
    3533     default:
    3534         return VERR_EM_INTERPRETER;
    3535     }
    3536 
    3537     /** @todo is addr always a flat linear address or ds based
    3538      * (in absence of segment override prefixes)????
    3539      */
    3540 #ifdef IN_RC
    3541     LogFlow(("RC: EMULATE: invlpg %RGv\n", addr));
    3542 #endif
    3543     rc = PGMInvalidatePage(pVCpu, addr);
    3544     if (    rc == VINF_SUCCESS
    3545         ||  rc == VINF_PGM_SYNC_CR3 /* we can rely on the FF */)
    3546         return VINF_SUCCESS;
    3547     AssertMsgReturn(rc == VINF_EM_RAW_EMULATE_INSTR,
    3548                     ("%Rrc addr=%RGv\n", VBOXSTRICTRC_VAL(rc), addr),
    3549                     VERR_EM_INTERPRETER);
    3550     return rc;
    3551 }
    3552 
    3553 /** @todo change all these EMInterpretXXX methods to VBOXSTRICTRC. */
    3554 
    3555 /**
    3556  * CPUID Emulation.
    3557  */
    3558 static int emInterpretCpuId(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3559 {
    3560     NOREF(pVM); NOREF(pVCpu); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
    3561     int rc = EMInterpretCpuId(pVM, pVCpu, pRegFrame);
    3562     return rc;
    3563 }
    3564 
    3565 
    3566 /**
    3567  * CLTS Emulation.
    3568  */
    3569 static int emInterpretClts(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3570 {
    3571     NOREF(pVM); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
    3572 
    3573     uint64_t cr0 = CPUMGetGuestCR0(pVCpu);
    3574     if (!(cr0 & X86_CR0_TS))
    3575         return VINF_SUCCESS;
    3576     return CPUMSetGuestCR0(pVCpu, cr0 & ~X86_CR0_TS);
    3577 }
    3578 
    3579 
    3580 /**
    3581  * Update CRx.
    3582  *
    3583  * @returns VBox status code.
    3584  * @param   pVM         The cross context VM structure.
    3585  * @param   pVCpu       The cross context virtual CPU structure.
    3586  * @param   pRegFrame   The register frame.
    3587  * @param   DestRegCrx  CRx register index (DISUSE_REG_CR*)
    3588  * @param   val         New CRx value
    3589  *
    3590  */
    3591 static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint64_t val)
    3592 {
    3593     uint64_t oldval;
    3594     uint64_t msrEFER;
    3595     uint32_t fValid;
    3596     int      rc, rc2;
    3597     NOREF(pVM);
    3598 
    3599     /** @todo Clean up this mess. */
    3600     LogFlow(("emInterpretCRxWrite at %RGv CR%d <- %RX64\n", (RTGCPTR)pRegFrame->rip, DestRegCrx, val));
    3601     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    3602     switch (DestRegCrx)
    3603     {
    3604     case DISCREG_CR0:
    3605         oldval = CPUMGetGuestCR0(pVCpu);
    3606 #ifdef IN_RC
    3607         /* CR0.WP and CR0.AM changes require a reschedule run in ring 3. */
    3608         if (    (val    & (X86_CR0_WP | X86_CR0_AM))
    3609             !=  (oldval & (X86_CR0_WP | X86_CR0_AM)))
    3610             return VERR_EM_INTERPRETER;
    3611 #endif
    3612         rc = VINF_SUCCESS;
    3613 #if !defined(VBOX_COMPARE_IEM_AND_EM) || !defined(VBOX_COMPARE_IEM_LAST)
    3614         CPUMSetGuestCR0(pVCpu, val);
    3615 #else
    3616         CPUMQueryGuestCtxPtr(pVCpu)->cr0 = val | X86_CR0_ET;
    3617 #endif
    3618         val = CPUMGetGuestCR0(pVCpu);
    3619         if (    (oldval & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE))
    3620             !=  (val    & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE)))
    3621         {
    3622             /* global flush */
    3623             rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true /* global */);
    3624             AssertRCReturn(rc, rc);
    3625         }
    3626 
    3627         /* Deal with long mode enabling/disabling. */
    3628         msrEFER = CPUMGetGuestEFER(pVCpu);
    3629         if (msrEFER & MSR_K6_EFER_LME)
    3630         {
    3631             if (    !(oldval & X86_CR0_PG)
    3632                 &&  (val & X86_CR0_PG))
    3633             {
    3634                 /* Illegal to have an active 64 bits CS selector (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
    3635                 if (pRegFrame->cs.Attr.n.u1Long)
    3636                 {
    3637                     AssertMsgFailed(("Illegal enabling of paging with CS.u1Long = 1!!\n"));
    3638                     return VERR_EM_INTERPRETER; /** @todo generate \#GP(0) */
    3639                 }
    3640 
    3641                 /* Illegal to switch to long mode before activating PAE first (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
    3642                 if (!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PAE))
    3643                 {
    3644                     AssertMsgFailed(("Illegal enabling of paging with PAE disabled!!\n"));
    3645                     return VERR_EM_INTERPRETER; /** @todo generate \#GP(0) */
    3646                 }
    3647                 msrEFER |= MSR_K6_EFER_LMA;
    3648             }
    3649             else
    3650             if (    (oldval & X86_CR0_PG)
    3651                 &&  !(val & X86_CR0_PG))
    3652             {
    3653                 msrEFER &= ~MSR_K6_EFER_LMA;
    3654                 /** @todo Do we need to cut off rip here? High dword of rip is undefined, so it shouldn't really matter. */
    3655             }
    3656             CPUMSetGuestEFER(pVCpu, msrEFER);
    3657         }
    3658         rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
    3659         return rc2 == VINF_SUCCESS ? rc : rc2;
    3660 
    3661     case DISCREG_CR2:
    3662         rc = CPUMSetGuestCR2(pVCpu, val); AssertRC(rc);
    3663         return VINF_SUCCESS;
    3664 
    3665     case DISCREG_CR3:
    3666         /* Reloading the current CR3 means the guest just wants to flush the TLBs */
    3667         rc = CPUMSetGuestCR3(pVCpu, val); AssertRC(rc);
    3668         if (CPUMGetGuestCR0(pVCpu) & X86_CR0_PG)
    3669         {
    3670             /* flush */
    3671             rc = PGMFlushTLB(pVCpu, val, !(CPUMGetGuestCR4(pVCpu) & X86_CR4_PGE));
    3672             AssertRC(rc);
    3673         }
    3674         return rc;
    3675 
    3676     case DISCREG_CR4:
    3677         oldval = CPUMGetGuestCR4(pVCpu);
    3678         rc = CPUMSetGuestCR4(pVCpu, val); AssertRC(rc);
    3679         val = CPUMGetGuestCR4(pVCpu);
    3680 
    3681         /* Illegal to disable PAE when long mode is active. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
    3682         msrEFER = CPUMGetGuestEFER(pVCpu);
    3683         if (    (msrEFER & MSR_K6_EFER_LMA)
    3684             &&  (oldval & X86_CR4_PAE)
    3685             &&  !(val & X86_CR4_PAE))
    3686         {
    3687             return VERR_EM_INTERPRETER; /** @todo generate \#GP(0) */
    3688         }
    3689 
    3690         /* From IEM iemCImpl_load_CrX. */
    3691         /** @todo Check guest CPUID bits for determining corresponding valid bits. */
    3692         fValid = X86_CR4_VME | X86_CR4_PVI
    3693                | X86_CR4_TSD | X86_CR4_DE
    3694                | X86_CR4_PSE | X86_CR4_PAE
    3695                | X86_CR4_MCE | X86_CR4_PGE
    3696                | X86_CR4_PCE | X86_CR4_OSFXSR
    3697                | X86_CR4_OSXMMEEXCPT;
    3698         //if (xxx)
    3699         //    fValid |= X86_CR4_VMXE;
    3700         //if (xxx)
    3701         //    fValid |= X86_CR4_OSXSAVE;
    3702         if (val & ~(uint64_t)fValid)
    3703         {
    3704             Log(("Trying to set reserved CR4 bits: NewCR4=%#llx InvalidBits=%#llx\n", val, val & ~(uint64_t)fValid));
    3705             return VERR_EM_INTERPRETER; /** @todo generate \#GP(0) */
    3706         }
    3707 
    3708         rc = VINF_SUCCESS;
    3709         if (    (oldval & (X86_CR4_PGE|X86_CR4_PAE|X86_CR4_PSE))
    3710             !=  (val    & (X86_CR4_PGE|X86_CR4_PAE|X86_CR4_PSE)))
    3711         {
    3712             /* global flush */
    3713             rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true /* global */);
    3714             AssertRCReturn(rc, rc);
    3715         }
    3716 
    3717         /* Feeling extremely lazy. */
    3718 # ifdef IN_RC
    3719         if (    (oldval & (X86_CR4_OSFXSR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME))
    3720             !=  (val    & (X86_CR4_OSFXSR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME)))
    3721         {
    3722             Log(("emInterpretMovCRx: CR4: %#RX64->%#RX64 => R3\n", oldval, val));
    3723             VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3);
    3724         }
    3725 # endif
    3726 # ifdef VBOX_WITH_RAW_MODE
    3727         if (((val ^ oldval) & X86_CR4_VME) && VM_IS_RAW_MODE_ENABLED(pVM))
    3728             VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
    3729 # endif
    3730 
    3731         rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
    3732         return rc2 == VINF_SUCCESS ? rc : rc2;
    3733 
    3734     case DISCREG_CR8:
    3735         return APICSetTpr(pVCpu, val << 4);  /* cr8 bits 3-0 correspond to bits 7-4 of the task priority mmio register. */
    3736 
    3737     default:
    3738         AssertFailed();
    3739     case DISCREG_CR1: /* illegal op */
    3740         break;
    3741     }
    3742     return VERR_EM_INTERPRETER;
    3743 }
    3744 
    3745 
    3746 /**
    3747  * LMSW Emulation.
    3748  */
    3749 static int emInterpretLmsw(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3750 {
    3751     DISQPVPARAMVAL param1;
    3752     uint32_t    val;
    3753     NOREF(pvFault); NOREF(pcbSize);
    3754     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    3755 
    3756     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3757     if(RT_FAILURE(rc))
    3758         return VERR_EM_INTERPRETER;
    3759 
    3760     switch(param1.type)
    3761     {
    3762     case DISQPV_TYPE_IMMEDIATE:
    3763     case DISQPV_TYPE_ADDRESS:
    3764         if(!(param1.flags  & DISQPV_FLAG_16))
    3765             return VERR_EM_INTERPRETER;
    3766         val = param1.val.val32;
    3767         break;
    3768 
    3769     default:
    3770         return VERR_EM_INTERPRETER;
    3771     }
    3772 
    3773     LogFlow(("emInterpretLmsw %x\n", val));
    3774     uint64_t OldCr0 = CPUMGetGuestCR0(pVCpu);
    3775 
    3776     /* Only PE, MP, EM and TS can be changed; note that PE can't be cleared by this instruction. */
    3777     uint64_t NewCr0 = ( OldCr0 & ~(             X86_CR0_MP | X86_CR0_EM | X86_CR0_TS))
    3778                     | (val     &  (X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS));
    3779 
    3780     return emUpdateCRx(pVM, pVCpu, pRegFrame, DISCREG_CR0, NewCr0);
    3781 
    3782 }
    3783 
    3784 #ifdef EM_EMULATE_SMSW
    3785 /**
    3786  * SMSW Emulation.
    3787  */
    3788 static int emInterpretSmsw(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3789 {
    3790     NOREF(pvFault); NOREF(pcbSize);
    3791     DISQPVPARAMVAL param1;
    3792     uint64_t    cr0 = CPUMGetGuestCR0(pVCpu);
    3793 
    3794     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3795     if(RT_FAILURE(rc))
    3796         return VERR_EM_INTERPRETER;
    3797 
    3798     switch(param1.type)
    3799     {
    3800     case DISQPV_TYPE_IMMEDIATE:
    3801         if(param1.size != sizeof(uint16_t))
    3802             return VERR_EM_INTERPRETER;
    3803         LogFlow(("emInterpretSmsw %d <- cr0 (%x)\n", pDis->Param1.Base.idxGenReg, cr0));
    3804         rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, cr0);
    3805         break;
    3806 
    3807     case DISQPV_TYPE_ADDRESS:
    3808     {
    3809         RTGCPTR pParam1;
    3810 
    3811         /* Actually forced to 16 bits regardless of the operand size. */
    3812         if(param1.size != sizeof(uint16_t))
    3813             return VERR_EM_INTERPRETER;
    3814 
    3815         pParam1 = (RTGCPTR)param1.val.val64;
    3816         pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pParam1);
    3817         LogFlow(("emInterpretSmsw %RGv <- cr0 (%x)\n", pParam1, cr0));
    3818 
    3819         rc = emRamWrite(pVM, pVCpu, pRegFrame, pParam1, &cr0, sizeof(uint16_t));
    3820         if (RT_FAILURE(rc))
    3821         {
    3822             AssertMsgFailed(("emRamWrite %RGv size=%d failed with %Rrc\n", pParam1, param1.size, rc));
    3823             return VERR_EM_INTERPRETER;
    3824         }
    3825         break;
    3826     }
    3827 
    3828     default:
    3829         return VERR_EM_INTERPRETER;
    3830     }
    3831 
    3832     LogFlow(("emInterpretSmsw %x\n", cr0));
    3833     return rc;
    3834 }
    3835 #endif
    3836 
    3837 
    3838 /**
    3839  * Interpret CRx read.
    3840  *
    3841  * @returns VBox status code.
    3842  * @param   pVM         The cross context VM structure.
    3843  * @param   pVCpu       The cross context virtual CPU structure.
    3844  * @param   pRegFrame   The register frame.
    3845  * @param   DestRegGen  General purpose register index (USE_REG_E**))
    3846  * @param   SrcRegCrx   CRx register index (DISUSE_REG_CR*)
    3847  *
    3848  */
    3849 static int emInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
    3850 {
    3851     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    3852     uint64_t val64;
    3853     int rc = CPUMGetGuestCRx(pVCpu, SrcRegCrx, &val64);
    3854     AssertMsgRCReturn(rc, ("CPUMGetGuestCRx %d failed\n", SrcRegCrx), VERR_EM_INTERPRETER);
    3855     NOREF(pVM);
    3856 
    3857     if (CPUMIsGuestIn64BitCode(pVCpu))
    3858         rc = DISWriteReg64(pRegFrame, DestRegGen, val64);
    3859     else
    3860         rc = DISWriteReg32(pRegFrame, DestRegGen, val64);
    3861 
    3862     if (RT_SUCCESS(rc))
    3863     {
    3864         LogFlow(("MOV_CR: gen32=%d CR=%d val=%RX64\n", DestRegGen, SrcRegCrx, val64));
    3865         return VINF_SUCCESS;
    3866     }
    3867     return VERR_EM_INTERPRETER;
    3868 }
    3869 
    3870 
    3871 /**
    3872  * Interpret CRx write.
    3873  *
    3874  * @returns VBox status code.
    3875  * @param   pVM         The cross context VM structure.
    3876  * @param   pVCpu       The cross context virtual CPU structure.
    3877  * @param   pRegFrame   The register frame.
    3878  * @param   DestRegCrx  CRx register index (DISUSE_REG_CR*)
    3879  * @param   SrcRegGen   General purpose register index (USE_REG_E**))
    3880  *
    3881  */
    3882 static int emInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
    3883 {
    3884     uint64_t val;
    3885     int      rc;
    3886     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    3887 
    3888     if (CPUMIsGuestIn64BitCode(pVCpu))
    3889         rc = DISFetchReg64(pRegFrame, SrcRegGen, &val);
    3890     else
    3891     {
    3892         uint32_t val32;
    3893         rc = DISFetchReg32(pRegFrame, SrcRegGen, &val32);
    3894         val = val32;
    3895     }
    3896 
    3897     if (RT_SUCCESS(rc))
    3898         return emUpdateCRx(pVM, pVCpu, pRegFrame, DestRegCrx, val);
    3899 
    3900     return VERR_EM_INTERPRETER;
    3901 }
    3902 
    3903 
    3904 /**
    3905  * MOV CRx
    3906  */
    3907 static int emInterpretMovCRx(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3908 {
    3909     NOREF(pvFault); NOREF(pcbSize);
    3910     if ((pDis->Param1.fUse == DISUSE_REG_GEN32 || pDis->Param1.fUse == DISUSE_REG_GEN64) && pDis->Param2.fUse == DISUSE_REG_CR)
    3911         return emInterpretCRxRead(pVM, pVCpu, pRegFrame, pDis->Param1.Base.idxGenReg, pDis->Param2.Base.idxCtrlReg);
    3912 
    3913     if (pDis->Param1.fUse == DISUSE_REG_CR && (pDis->Param2.fUse == DISUSE_REG_GEN32 || pDis->Param2.fUse == DISUSE_REG_GEN64))
    3914         return emInterpretCRxWrite(pVM, pVCpu, pRegFrame, pDis->Param1.Base.idxCtrlReg, pDis->Param2.Base.idxGenReg);
    3915 
    3916     AssertMsgFailedReturn(("Unexpected control register move\n"), VERR_EM_INTERPRETER);
    3917 }
    3918 
    3919 
    3920 /**
    3921  * MOV DRx
    3922  */
    3923 static int emInterpretMovDRx(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3924 {
    3925     int rc = VERR_EM_INTERPRETER;
    3926     NOREF(pvFault); NOREF(pcbSize);
    3927 
    3928     if((pDis->Param1.fUse == DISUSE_REG_GEN32 || pDis->Param1.fUse == DISUSE_REG_GEN64) && pDis->Param2.fUse == DISUSE_REG_DBG)
    3929     {
    3930         rc = EMInterpretDRxRead(pVM, pVCpu, pRegFrame, pDis->Param1.Base.idxGenReg, pDis->Param2.Base.idxDbgReg);
    3931     }
    3932     else
    3933     if(pDis->Param1.fUse == DISUSE_REG_DBG && (pDis->Param2.fUse == DISUSE_REG_GEN32 || pDis->Param2.fUse == DISUSE_REG_GEN64))
    3934     {
    3935         rc = EMInterpretDRxWrite(pVM, pVCpu, pRegFrame, pDis->Param1.Base.idxDbgReg, pDis->Param2.Base.idxGenReg);
    3936     }
    3937     else
    3938         AssertMsgFailed(("Unexpected debug register move\n"));
    3939 
    3940     return rc;
    3941 }
    3942 
    3943 
    3944 /**
    3945  * LLDT Emulation.
    3946  */
    3947 static int emInterpretLLdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3948 {
    3949     DISQPVPARAMVAL param1;
    3950     RTSEL       sel;
    3951     NOREF(pVM); NOREF(pvFault); NOREF(pcbSize);
    3952 
    3953     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    3954     if(RT_FAILURE(rc))
    3955         return VERR_EM_INTERPRETER;
    3956 
    3957     switch(param1.type)
    3958     {
    3959     case DISQPV_TYPE_ADDRESS:
    3960         return VERR_EM_INTERPRETER; //feeling lazy right now
    3961 
    3962     case DISQPV_TYPE_IMMEDIATE:
    3963         if(!(param1.flags  & DISQPV_FLAG_16))
    3964             return VERR_EM_INTERPRETER;
    3965         sel = (RTSEL)param1.val.val16;
    3966         break;
    3967 
    3968     default:
    3969         return VERR_EM_INTERPRETER;
    3970     }
    3971 
    3972 #ifdef IN_RING0
    3973     /* Only for the VT-x real-mode emulation case. */
    3974     AssertReturn(CPUMIsGuestInRealMode(pVCpu), VERR_EM_INTERPRETER);
    3975     CPUMSetGuestLDTR(pVCpu, sel);
    3976     return VINF_SUCCESS;
    3977 #else
    3978     if (sel == 0)
    3979     {
    3980         if (CPUMGetHyperLDTR(pVCpu) == 0)
    3981         {
    3982             // this simple case is most frequent in Windows 2000 (31k - boot & shutdown)
    3983             return VINF_SUCCESS;
    3984         }
    3985     }
    3986     //still feeling lazy
    3987     return VERR_EM_INTERPRETER;
    3988 #endif
    3989 }
    3990 
    3991 #ifdef IN_RING0
    3992 /**
    3993  * LIDT/LGDT Emulation.
    3994  */
    3995 static int emInterpretLIGdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    3996 {
    3997     DISQPVPARAMVAL param1;
    3998     RTGCPTR     pParam1;
    3999     X86XDTR32   dtr32;
    4000     NOREF(pvFault); NOREF(pcbSize);
    4001 
    4002     Log(("Emulate %s at %RGv\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip));
    4003 
    4004     /* Only for the VT-x real-mode emulation case. */
    4005     AssertReturn(CPUMIsGuestInRealMode(pVCpu), VERR_EM_INTERPRETER);
    4006 
    4007     int rc = DISQueryParamVal(pRegFrame, pDis, &pDis->Param1, &param1, DISQPVWHICH_SRC);
    4008     if(RT_FAILURE(rc))
    4009         return VERR_EM_INTERPRETER;
    4010 
    4011     switch(param1.type)
    4012     {
    4013     case DISQPV_TYPE_ADDRESS:
    4014         pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, param1.val.val16);
    4015         break;
    4016 
    4017     default:
    4018         return VERR_EM_INTERPRETER;
    4019     }
    4020 
    4021     rc = emRamRead(pVM, pVCpu, pRegFrame, &dtr32, pParam1, sizeof(dtr32));
    4022     AssertRCReturn(rc, VERR_EM_INTERPRETER);
    4023 
    4024     if (!(pDis->fPrefix & DISPREFIX_OPSIZE))
    4025         dtr32.uAddr &= 0xffffff; /* 16 bits operand size */
    4026 
    4027     if (pDis->pCurInstr->uOpcode == OP_LIDT)
    4028         CPUMSetGuestIDTR(pVCpu, dtr32.uAddr, dtr32.cb);
    4029     else
    4030         CPUMSetGuestGDTR(pVCpu, dtr32.uAddr, dtr32.cb);
    4031 
    4032     return VINF_SUCCESS;
    4033 }
    4034 #endif
    4035 
    4036 
    4037 #ifdef IN_RC
    4038 /**
    4039  * STI Emulation.
    4040  *
    4041  * @remark the instruction following sti is guaranteed to be executed before any interrupts are dispatched
    4042  */
    4043 static int emInterpretSti(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4044 {
    4045     NOREF(pcbSize);
    4046     PPATMGCSTATE pGCState = PATMGetGCState(pVM);
    4047 
    4048     if(!pGCState)
    4049     {
    4050         Assert(pGCState);
    4051         return VERR_EM_INTERPRETER;
    4052     }
    4053     pGCState->uVMFlags |= X86_EFL_IF;
    4054 
    4055     Assert(pRegFrame->eflags.u32 & X86_EFL_IF);
    4056     Assert(pvFault == SELMToFlat(pVM, DISSELREG_CS, pRegFrame, (RTGCPTR)pRegFrame->rip));
    4057 
    4058     pVCpu->em.s.GCPtrInhibitInterrupts = pRegFrame->eip + pDis->cbInstr;
    4059     VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    4060 
    4061     return VINF_SUCCESS;
    4062 }
    4063 #endif /* IN_RC */
    4064 
    4065 
    4066 /**
    4067  * HLT Emulation.
    4068  */
    4069 static VBOXSTRICTRC
    4070 emInterpretHlt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4071 {
    4072     NOREF(pVM); NOREF(pVCpu); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
    4073     return VINF_EM_HALT;
    4074 }
    4075 
    4076 
    4077 /**
    4078  * RDTSC Emulation.
    4079  */
    4080 static int emInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4081 {
    4082     NOREF(pDis); NOREF(pvFault); NOREF(pcbSize);
    4083     return EMInterpretRdtsc(pVM, pVCpu, pRegFrame);
    4084 }
    4085 
    4086 /**
    4087  * RDPMC Emulation
    4088  */
    4089 static int emInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4090 {
    4091     NOREF(pDis); NOREF(pvFault); NOREF(pcbSize);
    4092     return EMInterpretRdpmc(pVM, pVCpu, pRegFrame);
    4093 }
    4094 
    4095 
    4096 static int emInterpretMonitor(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4097 {
    4098     NOREF(pDis); NOREF(pvFault); NOREF(pcbSize);
    4099     return EMInterpretMonitor(pVM, pVCpu, pRegFrame);
    4100 }
    4101 
    4102 
    4103 static VBOXSTRICTRC emInterpretMWait(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4104 {
    4105     NOREF(pDis); NOREF(pvFault); NOREF(pcbSize);
    4106     return EMInterpretMWait(pVM, pVCpu, pRegFrame);
    4107 }
    4108 
    4109 
    4110 /**
    4111  * RDMSR Emulation.
    4112  */
    4113 static int emInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4114 {
    4115     /* Note: The Intel manual claims there's a REX version of RDMSR that's slightly
    4116              different, so we play safe by completely disassembling the instruction. */
    4117     Assert(!(pDis->fPrefix & DISPREFIX_REX));
    4118     NOREF(pDis); NOREF(pvFault); NOREF(pcbSize);
    4119 
    4120     /* Get the current privilege level. */
    4121     if (CPUMGetGuestCPL(pVCpu) != 0)
    4122     {
    4123         Log4(("EM: Refuse RDMSR: CPL != 0\n"));
    4124         return VERR_EM_INTERPRETER; /* supervisor only */
    4125     }
    4126 
    4127     uint64_t uValue;
    4128     VBOXSTRICTRC rcStrict = CPUMQueryGuestMsr(pVCpu, pRegFrame->ecx, &uValue);
    4129     if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
    4130     {
    4131         Log4(("EM: Refuse RDMSR: rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    4132         Assert(rcStrict == VERR_CPUM_RAISE_GP_0 || rcStrict == VERR_EM_INTERPRETER || rcStrict == VINF_CPUM_R3_MSR_READ);
    4133         return VERR_EM_INTERPRETER;
    4134     }
    4135     pRegFrame->rax = RT_LO_U32(uValue);
    4136     pRegFrame->rdx = RT_HI_U32(uValue);
    4137     LogFlow(("EMInterpretRdmsr %s (%x) -> %RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, uValue));
    4138     return VINF_SUCCESS;
    4139 }
    4140 
    4141 
    4142 /**
    4143  * WRMSR Emulation.
    4144  */
    4145 static int emInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    4146 {
    4147     NOREF(pDis); NOREF(pvFault); NOREF(pcbSize);
    4148     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    4149 
    4150     /* Check the current privilege level, this instruction is supervisor only. */
    4151     if (CPUMGetGuestCPL(pVCpu) != 0)
    4152     {
    4153         Log4(("EM: Refuse WRMSR: CPL != 0\n"));
    4154         return VERR_EM_INTERPRETER; /** @todo raise \#GP(0) */
    4155     }
    4156 
    4157     VBOXSTRICTRC rcStrict = CPUMSetGuestMsr(pVCpu, pRegFrame->ecx, RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx));
    4158     if (rcStrict != VINF_SUCCESS)
    4159     {
    4160         Log4(("EM: Refuse WRMSR: CPUMSetGuestMsr returned %Rrc\n",  VBOXSTRICTRC_VAL(rcStrict)));
    4161         Assert(rcStrict == VERR_CPUM_RAISE_GP_0 || rcStrict == VERR_EM_INTERPRETER || rcStrict == VINF_CPUM_R3_MSR_WRITE);
    4162         return VERR_EM_INTERPRETER;
    4163     }
    4164     LogFlow(("EMInterpretWrmsr %s (%x) val=%RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx,
    4165              RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx)));
    4166     NOREF(pVM);
    4167     return VINF_SUCCESS;
    4168 }
    4169 
    4170 
    4171 /**
    4172  * Internal worker.
    4173  * @copydoc emInterpretInstructionCPUOuter
    4174  * @param   pVM     The cross context VM structure.
    4175  */
    4176 DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
    4177                                                    RTGCPTR pvFault, EMCODETYPE enmCodeType, uint32_t *pcbSize)
    4178 {
    4179     Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
    4180     Assert(enmCodeType == EMCODETYPE_SUPERVISOR || enmCodeType == EMCODETYPE_ALL);
    4181     Assert(pcbSize);
    4182     *pcbSize = 0;
    4183 
    4184     if (enmCodeType == EMCODETYPE_SUPERVISOR)
    4185     {
    4186         /*
    4187          * Only supervisor guest code!!
    4188          * And no complicated prefixes.
    4189          */
    4190         /* Get the current privilege level. */
    4191         uint32_t cpl = CPUMGetGuestCPL(pVCpu);
    4192 #ifdef VBOX_WITH_RAW_RING1
    4193         if (   !EMIsRawRing1Enabled(pVM)
    4194             || cpl > 1
    4195             || pRegFrame->eflags.Bits.u2IOPL > cpl
    4196            )
    4197 #endif
    4198         {
    4199             if (    cpl != 0
    4200                 &&  pDis->pCurInstr->uOpcode != OP_RDTSC)    /* rdtsc requires emulation in ring 3 as well */
    4201             {
    4202                 Log(("WARNING: refusing instruction emulation for user-mode code!!\n"));
    4203                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedUserMode));
    4204                 return VERR_EM_INTERPRETER;
    4205             }
    4206         }
    4207     }
    4208     else
    4209         Log2(("emInterpretInstructionCPU allowed to interpret user-level code!!\n"));
    4210 
    4211 #ifdef IN_RC
    4212     if (    (pDis->fPrefix & (DISPREFIX_REPNE | DISPREFIX_REP))
    4213         ||  (   (pDis->fPrefix & DISPREFIX_LOCK)
    4214              && pDis->pCurInstr->uOpcode != OP_CMPXCHG
    4215              && pDis->pCurInstr->uOpcode != OP_CMPXCHG8B
    4216              && pDis->pCurInstr->uOpcode != OP_XADD
    4217              && pDis->pCurInstr->uOpcode != OP_OR
    4218              && pDis->pCurInstr->uOpcode != OP_AND
    4219              && pDis->pCurInstr->uOpcode != OP_XOR
    4220              && pDis->pCurInstr->uOpcode != OP_BTR
    4221             )
    4222        )
    4223 #else
    4224     if (    (pDis->fPrefix & DISPREFIX_REPNE)
    4225         ||  (   (pDis->fPrefix & DISPREFIX_REP)
    4226              && pDis->pCurInstr->uOpcode != OP_STOSWD
    4227             )
    4228         ||  (   (pDis->fPrefix & DISPREFIX_LOCK)
    4229              && pDis->pCurInstr->uOpcode != OP_OR
    4230              && pDis->pCurInstr->uOpcode != OP_AND
    4231              && pDis->pCurInstr->uOpcode != OP_XOR
    4232              && pDis->pCurInstr->uOpcode != OP_BTR
    4233              && pDis->pCurInstr->uOpcode != OP_CMPXCHG
    4234              && pDis->pCurInstr->uOpcode != OP_CMPXCHG8B
    4235             )
    4236        )
    4237 #endif
    4238     {
    4239         //Log(("EMInterpretInstruction: wrong prefix!!\n"));
    4240         STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedPrefix));
    4241         Log4(("EM: Refuse %u on REP/REPNE/LOCK prefix grounds\n", pDis->pCurInstr->uOpcode));
    4242         return VERR_EM_INTERPRETER;
    4243     }
    4244 
    4245 #if HC_ARCH_BITS == 32
    4246     /*
    4247      * Unable to emulate most >4 bytes accesses in 32 bits mode.
    4248      * Whitelisted instructions are safe.
    4249      */
    4250     if (    pDis->Param1.cb > 4
    4251         &&  CPUMIsGuestIn64BitCode(pVCpu))
    4252     {
    4253         uint32_t uOpCode = pDis->pCurInstr->uOpcode;
    4254         if (    uOpCode != OP_STOSWD
    4255             &&  uOpCode != OP_MOV
    4256             &&  uOpCode != OP_CMPXCHG8B
    4257             &&  uOpCode != OP_XCHG
    4258             &&  uOpCode != OP_BTS
    4259             &&  uOpCode != OP_BTR
    4260             &&  uOpCode != OP_BTC
    4261             )
    4262         {
    4263 # ifdef VBOX_WITH_STATISTICS
    4264             switch (pDis->pCurInstr->uOpcode)
    4265             {
    4266 #  define INTERPRET_FAILED_CASE(opcode, Instr) \
    4267                 case opcode: STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); break;
    4268                 INTERPRET_FAILED_CASE(OP_XCHG,Xchg);
    4269                 INTERPRET_FAILED_CASE(OP_DEC,Dec);
    4270                 INTERPRET_FAILED_CASE(OP_INC,Inc);
    4271                 INTERPRET_FAILED_CASE(OP_POP,Pop);
    4272                 INTERPRET_FAILED_CASE(OP_OR, Or);
    4273                 INTERPRET_FAILED_CASE(OP_XOR,Xor);
    4274                 INTERPRET_FAILED_CASE(OP_AND,And);
    4275                 INTERPRET_FAILED_CASE(OP_MOV,Mov);
    4276                 INTERPRET_FAILED_CASE(OP_STOSWD,StosWD);
    4277                 INTERPRET_FAILED_CASE(OP_INVLPG,InvlPg);
    4278                 INTERPRET_FAILED_CASE(OP_CPUID,CpuId);
    4279                 INTERPRET_FAILED_CASE(OP_MOV_CR,MovCRx);
    4280                 INTERPRET_FAILED_CASE(OP_MOV_DR,MovDRx);
    4281                 INTERPRET_FAILED_CASE(OP_LLDT,LLdt);
    4282                 INTERPRET_FAILED_CASE(OP_LIDT,LIdt);
    4283                 INTERPRET_FAILED_CASE(OP_LGDT,LGdt);
    4284                 INTERPRET_FAILED_CASE(OP_LMSW,Lmsw);
    4285                 INTERPRET_FAILED_CASE(OP_CLTS,Clts);
    4286                 INTERPRET_FAILED_CASE(OP_MONITOR,Monitor);
    4287                 INTERPRET_FAILED_CASE(OP_MWAIT,MWait);
    4288                 INTERPRET_FAILED_CASE(OP_RDMSR,Rdmsr);
    4289                 INTERPRET_FAILED_CASE(OP_WRMSR,Wrmsr);
    4290                 INTERPRET_FAILED_CASE(OP_ADD,Add);
    4291                 INTERPRET_FAILED_CASE(OP_SUB,Sub);
    4292                 INTERPRET_FAILED_CASE(OP_ADC,Adc);
    4293                 INTERPRET_FAILED_CASE(OP_BTR,Btr);
    4294                 INTERPRET_FAILED_CASE(OP_BTS,Bts);
    4295                 INTERPRET_FAILED_CASE(OP_BTC,Btc);
    4296                 INTERPRET_FAILED_CASE(OP_RDTSC,Rdtsc);
    4297                 INTERPRET_FAILED_CASE(OP_CMPXCHG, CmpXchg);
    4298                 INTERPRET_FAILED_CASE(OP_STI, Sti);
    4299                 INTERPRET_FAILED_CASE(OP_XADD,XAdd);
    4300                 INTERPRET_FAILED_CASE(OP_CMPXCHG8B,CmpXchg8b);
    4301                 INTERPRET_FAILED_CASE(OP_HLT, Hlt);
    4302                 INTERPRET_FAILED_CASE(OP_IRET,Iret);
    4303                 INTERPRET_FAILED_CASE(OP_WBINVD,WbInvd);
    4304                 INTERPRET_FAILED_CASE(OP_MOVNTPS,MovNTPS);
    4305 #  undef INTERPRET_FAILED_CASE
    4306                 default:
    4307                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedMisc));
    4308                     break;
    4309             }
    4310 # endif /* VBOX_WITH_STATISTICS */
    4311             Log4(("EM: Refuse %u on grounds of accessing %u bytes\n", pDis->pCurInstr->uOpcode, pDis->Param1.cb));
    4312             return VERR_EM_INTERPRETER;
    4313         }
    4314     }
    4315 #endif
    4316 
    4317     VBOXSTRICTRC rc;
    4318 #if (defined(VBOX_STRICT) || defined(LOG_ENABLED))
    4319     LogFlow(("emInterpretInstructionCPU %s\n", emGetMnemonic(pDis)));
    4320 #endif
    4321     switch (pDis->pCurInstr->uOpcode)
    4322     {
    4323         /*
    4324          * Macros for generating the right case statements.
    4325          */
    4326 # ifndef VBOX_COMPARE_IEM_AND_EM
    4327 #  define INTERPRET_CASE_EX_LOCK_PARAM3(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock) \
    4328         case opcode:\
    4329             if (pDis->fPrefix & DISPREFIX_LOCK) \
    4330                 rc = emInterpretLock##InstrFn(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize, pfnEmulateLock); \
    4331             else \
    4332                 rc = emInterpret##InstrFn(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize, pfnEmulate); \
    4333             if (RT_SUCCESS(rc)) \
    4334                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
    4335             else \
    4336                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
    4337             return rc
    4338 # else  /* VBOX_COMPARE_IEM_AND_EM */
    4339 #  define INTERPRET_CASE_EX_LOCK_PARAM3(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock) \
    4340         case opcode:\
    4341             rc = emInterpret##InstrFn(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize, pfnEmulate); \
    4342             if (RT_SUCCESS(rc)) \
    4343                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
    4344             else \
    4345                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
    4346             return rc
    4347 # endif /* VBOX_COMPARE_IEM_AND_EM */
    4348 
    4349 #define INTERPRET_CASE_EX_PARAM3(opcode, Instr, InstrFn, pfnEmulate) \
    4350         case opcode:\
    4351             rc = emInterpret##InstrFn(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize, pfnEmulate); \
    4352             if (RT_SUCCESS(rc)) \
    4353                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
    4354             else \
    4355                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
    4356             return rc
    4357 
    4358 #define INTERPRET_CASE_EX_PARAM2(opcode, Instr, InstrFn, pfnEmulate) \
    4359             INTERPRET_CASE_EX_PARAM3(opcode, Instr, InstrFn, pfnEmulate)
    4360 #define INTERPRET_CASE_EX_LOCK_PARAM2(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock) \
    4361             INTERPRET_CASE_EX_LOCK_PARAM3(opcode, Instr, InstrFn, pfnEmulate, pfnEmulateLock)
    4362 
    4363 #define INTERPRET_CASE(opcode, Instr) \
    4364         case opcode:\
    4365             rc = emInterpret##Instr(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize); \
    4366             if (RT_SUCCESS(rc)) \
    4367                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
    4368             else \
    4369                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
    4370             return rc
    4371 
    4372 #define INTERPRET_CASE_EX_DUAL_PARAM2(opcode, Instr, InstrFn) \
    4373         case opcode:\
    4374             rc = emInterpret##InstrFn(pVM, pVCpu, pDis, pRegFrame, pvFault, pcbSize); \
    4375             if (RT_SUCCESS(rc)) \
    4376                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Instr)); \
    4377             else \
    4378                 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); \
    4379             return rc
    4380 
    4381 #define INTERPRET_STAT_CASE(opcode, Instr) \
    4382         case opcode: STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); return VERR_EM_INTERPRETER;
    4383 
    4384         /*
    4385          * The actual case statements.
    4386          */
    4387         INTERPRET_CASE(OP_XCHG,Xchg);
    4388         INTERPRET_CASE_EX_PARAM2(OP_DEC,Dec, IncDec, EMEmulateDec);
    4389         INTERPRET_CASE_EX_PARAM2(OP_INC,Inc, IncDec, EMEmulateInc);
    4390         INTERPRET_CASE(OP_POP,Pop);
    4391         INTERPRET_CASE_EX_LOCK_PARAM3(OP_OR, Or,  OrXorAnd, EMEmulateOr, EMEmulateLockOr);
    4392         INTERPRET_CASE_EX_LOCK_PARAM3(OP_XOR,Xor, OrXorAnd, EMEmulateXor, EMEmulateLockXor);
    4393         INTERPRET_CASE_EX_LOCK_PARAM3(OP_AND,And, OrXorAnd, EMEmulateAnd, EMEmulateLockAnd);
    4394         INTERPRET_CASE(OP_MOV,Mov);
    4395 #ifndef IN_RC
    4396         INTERPRET_CASE(OP_STOSWD,StosWD);
    4397 #endif
    4398         INTERPRET_CASE(OP_INVLPG,InvlPg);
    4399         INTERPRET_CASE(OP_CPUID,CpuId);
    4400         INTERPRET_CASE(OP_MOV_CR,MovCRx);
    4401         INTERPRET_CASE(OP_MOV_DR,MovDRx);
    4402 #ifdef IN_RING0
    4403         INTERPRET_CASE_EX_DUAL_PARAM2(OP_LIDT, LIdt, LIGdt);
    4404         INTERPRET_CASE_EX_DUAL_PARAM2(OP_LGDT, LGdt, LIGdt);
    4405 #endif
    4406         INTERPRET_CASE(OP_LLDT,LLdt);
    4407         INTERPRET_CASE(OP_LMSW,Lmsw);
    4408 #ifdef EM_EMULATE_SMSW
    4409         INTERPRET_CASE(OP_SMSW,Smsw);
    4410 #endif
    4411         INTERPRET_CASE(OP_CLTS,Clts);
    4412         INTERPRET_CASE(OP_MONITOR, Monitor);
    4413         INTERPRET_CASE(OP_MWAIT, MWait);
    4414         INTERPRET_CASE(OP_RDMSR, Rdmsr);
    4415         INTERPRET_CASE(OP_WRMSR, Wrmsr);
    4416         INTERPRET_CASE_EX_PARAM3(OP_ADD,Add, AddSub, EMEmulateAdd);
    4417         INTERPRET_CASE_EX_PARAM3(OP_SUB,Sub, AddSub, EMEmulateSub);
    4418         INTERPRET_CASE(OP_ADC,Adc);
    4419         INTERPRET_CASE_EX_LOCK_PARAM2(OP_BTR,Btr, BitTest, EMEmulateBtr, EMEmulateLockBtr);
    4420         INTERPRET_CASE_EX_PARAM2(OP_BTS,Bts, BitTest, EMEmulateBts);
    4421         INTERPRET_CASE_EX_PARAM2(OP_BTC,Btc, BitTest, EMEmulateBtc);
    4422         INTERPRET_CASE(OP_RDPMC,Rdpmc);
    4423         INTERPRET_CASE(OP_RDTSC,Rdtsc);
    4424         INTERPRET_CASE(OP_CMPXCHG, CmpXchg);
    4425 #ifdef IN_RC
    4426         INTERPRET_CASE(OP_STI,Sti);
    4427         INTERPRET_CASE(OP_XADD, XAdd);
    4428         INTERPRET_CASE(OP_IRET,Iret);
    4429 #endif
    4430         INTERPRET_CASE(OP_CMPXCHG8B, CmpXchg8b);
    4431         INTERPRET_CASE(OP_HLT,Hlt);
    4432         INTERPRET_CASE(OP_WBINVD,WbInvd);
    4433 #ifdef VBOX_WITH_STATISTICS
    4434 # ifndef IN_RC
    4435         INTERPRET_STAT_CASE(OP_XADD, XAdd);
    4436 # endif
    4437         INTERPRET_STAT_CASE(OP_MOVNTPS,MovNTPS);
    4438 #endif
    4439 
    4440         default:
    4441             Log3(("emInterpretInstructionCPU: opcode=%d\n", pDis->pCurInstr->uOpcode));
    4442             STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedMisc));
    4443             return VERR_EM_INTERPRETER;
    4444 
    4445 #undef INTERPRET_CASE_EX_PARAM2
    4446 #undef INTERPRET_STAT_CASE
    4447 #undef INTERPRET_CASE_EX
    4448 #undef INTERPRET_CASE
    4449     } /* switch (opcode) */
    4450     /* not reached */
    4451 }
    4452 
    4453 /**
    4454  * Interprets the current instruction using the supplied DISCPUSTATE structure.
    4455  *
    4456  * EIP is *NOT* updated!
    4457  *
    4458  * @returns VBox strict status code.
    4459  * @retval  VINF_*                  Scheduling instructions. When these are returned, it
    4460  *                                  starts to get a bit tricky to know whether code was
    4461  *                                  executed or not... We'll address this when it becomes a problem.
    4462  * @retval  VERR_EM_INTERPRETER     Something we can't cope with.
    4463  * @retval  VERR_*                  Fatal errors.
    4464  *
    4465  * @param   pVCpu       The cross context virtual CPU structure.
    4466  * @param   pDis        The disassembler cpu state for the instruction to be
    4467  *                      interpreted.
    4468  * @param   pRegFrame   The register frame. EIP is *NOT* changed!
    4469  * @param   pvFault     The fault address (CR2).
    4470  * @param   pcbSize     Size of the write (if applicable).
    4471  * @param   enmCodeType Code type (user/supervisor)
    4472  *
    4473  * @remark  Invalid opcode exceptions have a higher priority than GP (see Intel
    4474  *          Architecture System Developers Manual, Vol 3, 5.5) so we don't need
    4475  *          to worry about e.g. invalid modrm combinations (!)
    4476  *
    4477  * @todo    At this time we do NOT check if the instruction overwrites vital information.
    4478  *          Make sure this can't happen!! (will add some assertions/checks later)
    4479  */
    4480 DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPUOuter(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
    4481                                                         RTGCPTR pvFault, EMCODETYPE enmCodeType, uint32_t *pcbSize)
    4482 {
    4483     STAM_PROFILE_START(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Emulate), a);
    4484     VBOXSTRICTRC rc = emInterpretInstructionCPU(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, pRegFrame, pvFault, enmCodeType, pcbSize);
    4485     STAM_PROFILE_STOP(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Emulate), a);
    4486     if (RT_SUCCESS(rc))
    4487         STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,InterpretSucceeded));
    4488     else
    4489         STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,InterpretFailed));
    4490     return rc;
    4491 }
    4492 
    4493 
    4494 #endif /* !VBOX_WITH_IEM */
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