EMAll.cpp revision 1f4220e809ec89a3ce306b5a8f5a12bba71dddda
10139N/A * available from http://www.virtualbox.org. This file is free software;
10139N/A#include "EMInternal.h"
10139N/ADECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize);
10139N/A#define EM_ALLOW_SEG_PREFIX
10139N/A * Read callback for disassembly function; supports reading bytes that cross a page boundary
10139N/ADECLCALLBACK(int32_t) EMReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, uint32_t size, RTHCUINTPTR dwUserdata)
10139N/A return VINF_SUCCESS;
10139N/AEMDECL(int) EMInterpretDisasOne(PVM pVM, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pCpu, unsigned *pcbInstr)
10139N/A int rc = SELMValidateAndConvertCSAddr(pVM, pCtxCore->eflags, pCtxCore->ss, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid, (RTGCPTR)pCtxCore->eip, &GCPtrInstr);
12586N/AEMDECL(int) EMInterpretDisasOneEx(PVM pVM, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pCpu, unsigned *pcbInstr)
12467N/A int rc = DISCoreOneEx(GCPtrInstr, SELMIsSelector32Bit(pVM, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid) ? CPUMODE_32BIT : CPUMODE_16BIT,
12147N/A return VINF_SUCCESS;
12094N/A return VERR_INTERNAL_ERROR;
10642N/AEMDECL(int) EMInterpretInstruction(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
10199N/A int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &pbCode);
10139N/A return VERR_EM_INTERPRETER;
10139N/A * Make sure this can't happen!! (will add some assertions/checks later)
10139N/AEMDECL(int) EMInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
10139N/AEMDECL(int) EMInterpretPortIO(PVM pVM, PCPUMCTXCORE pCtxCore, PDISCPUSTATE pCpu, uint32_t cbOp)
10139N/A return VERR_NOT_IMPLEMENTED;
10139N/A return VINF_SUCCESS;
10139N/A return VINF_SUCCESS;
10139N/Astatic RTGCPTR emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, POP_PARAMETER pParam, RTGCPTR pvAddr)
10139N/A#ifdef EM_ALLOW_SEG_PREFIX
10139N/Astatic int emInterpretXchg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
10139N/A return VERR_EM_INTERPRETER;
10139N/A return VERR_EM_INTERPRETER;
10139N/A case PARMTYPE_ADDRESS:
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
#ifdef IN_GC
case PARMTYPE_IMMEDIATE:
AssertFailed();
return VERR_EM_INTERPRETER;
if (pParam1 == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
if (pParam2 == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretIncDec(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
#ifdef IN_GC
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretPop(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
#ifdef IN_GC
pStackVal = SELMToFlat(pVM, pRegFrame->eflags, pRegFrame->ss, &pRegFrame->ssHid, (RTGCPTR)pRegFrame->esp);
if (pStackVal == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgReturn(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, ("%VGv != %VGv ss:esp=%04X:%VGv\n", pParam1, pvFault, pRegFrame->ss, pRegFrame->esp), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretOr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgFailed(("Or at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretXor(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgFailed(("Xor at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretAnd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgFailed(("And at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
AssertMsgReturn(pParam1 == pvFault, ("pParam1 = %VGv pvFault = %VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
#ifndef DEBUG_bird
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretAdd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgFailed(("Add at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
return VERR_EM_INTERPRETER;
#ifndef DEBUG_bird
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretAdc(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgFailed(("Adc at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
return VERR_EM_INTERPRETER;
#ifndef DEBUG_bird
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretSub(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgFailed(("Sub at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
return VERR_EM_INTERPRETER;
#ifndef DEBUG_bird
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretBtr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretMov(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
case PARMTYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
AssertFailed();
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
LogFlow(("EMInterpretInstruction at %08x: OP_MOV %08X <- %08X (%d) &val32=%08x\n", pRegFrame->eip, pDest, val32, param2.size, &val32));
#ifdef IN_GC
return VERR_EM_INTERPRETER;
case PARMTYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
case PARMTYPE_REGISTER:
return VERR_EM_INTERPRETER;
return rc;
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
int rc;
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;
#ifndef IN_RING0
return VINF_SUCCESS;
static int emInterpretIret(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
int rc;
#ifdef IN_GC
return VINF_SUCCESS;
/** @todo r=bird: we shouldn't ignore returns codes like this... I'm 99% sure the error is fatal. */
return VERR_EM_INTERPRETER;
static int emInterpretInvlPg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case PARMTYPE_IMMEDIATE:
case PARMTYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VINF_SUCCESS;
/** @todo r=bird: we shouldn't ignore returns codes like this... I'm 99% sure the error is fatal. */
return VERR_EM_INTERPRETER;
CPUMGetGuestCpuId(pVM, pRegFrame->eax, &pRegFrame->eax, &pRegFrame->ebx, &pRegFrame->ecx, &pRegFrame->edx);
return VINF_SUCCESS;
static int emInterpretCpuId(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
Log(("Emulate: CPUID %x -> %08x %08x %08x %08x\n", iLeaf, pRegFrame->eax, pRegFrame->ebx, pRegFrame->ecx, pRegFrame->edx));
return rc;
EMDECL(int) EMInterpretCRxRead(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VINF_SUCCESS;
#ifdef IN_GC
EMDECL(int) EMInterpretCRxWrite(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
switch (DestRegCrx)
case USE_REG_CR0:
#ifndef IN_RING3
return VERR_EM_INTERPRETER;
rc = CPUMSetGuestCR0(pVM, val32); AssertRC(rc); /** @todo CPUSetGuestCR0 stuff should be void, this is silly. */
# ifdef IN_GC
case USE_REG_CR2:
return VINF_SUCCESS;
case USE_REG_CR3:
return VINF_SUCCESS;
case USE_REG_CR4:
#ifndef IN_RING3
if ( (oldval & (X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME))
!= (val32 & (X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME)))
AssertFailed();
return VERR_EM_INTERPRETER;
static int emInterpretMovCRx(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return EMInterpretCRxWrite(pVM, pRegFrame, pCpu->param1.base.reg_ctrl, pCpu->param2.base.reg_gen32);
return VERR_EM_INTERPRETER;
EMDECL(int) EMInterpretDRxWrite(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
return rc;
return VERR_EM_INTERPRETER;
EMDECL(int) EMInterpretDRxRead(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
static int emInterpretMovDRx(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return rc;
static int emInterpretLLdt(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
case PARMTYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
if (sel == 0)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
* @remark the instruction following sti is guaranteed to be executed before any interrupts are dispatched
static int emInterpretSti(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if(!pGCState)
return VERR_EM_INTERPRETER;
Assert(pvFault == SELMToFlat(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip));
return VINF_SUCCESS;
static int emInterpretHlt(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VINF_EM_HALT;
#ifdef IN_GC
static int emInterpretRdtsc(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VINF_SUCCESS;
static int emInterpretMonitor(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if (cpl != 0)
return VINF_SUCCESS;
static int emInterpretMWait(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if (cpl != 0)
return VINF_EM_HALT;
DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
*pcbSize = 0;
if (cpl != 0)
return VERR_EM_INTERPRETER;
#ifdef EM_ALLOW_SEG_PREFIX
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
int rc;
case opcode:\
return rc
case opcode: STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Failed##Instr)); return VERR_EM_INTERPRETER;
#ifdef IN_GC
#ifdef VBOX_WITH_STATISTICS
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_INTERNAL_ERROR;