IEMAllCImpl.cpp.h revision 8ae783bf7da7b2f0abb7b8d243b79aaafa35aa73
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * IEM - Instruction Implementation in C/C++ (code include).
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Copyright (C) 2011-2012 Oracle Corporation
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * available from http://www.virtualbox.org. This file is free software;
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * General Public License (GPL) as published by the Free Software
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync/** @name Misc Helpers
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Checks if we are allowed to access the given I/O port, raising the
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * appropriate exceptions if we aren't (or if the I/O bitmap is not
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * accessible).
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @returns Strict VBox status code.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param pIemCpu The IEM per CPU data.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param pCtx The register context.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param u16Port The port number.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param cbOperand The operand size.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsyncDECLINLINE(VBOXSTRICTRC) iemHlpCheckPortIOPermission(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint16_t u16Port, uint8_t cbOperand)
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync NOREF(u16Port); NOREF(cbOperand); /** @todo I/O port permission bitmap check */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync AssertFailedReturn(VERR_IEM_ASPECT_NOT_IMPLEMENTED);
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Calculates the parity bit.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @returns true if the bit is set, false if not.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param u8Result The least significant byte of the result.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Parity is set if the number of bits in the least significant byte of
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * the result is even.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync#endif /* not used */
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Updates the specified flags according to a 8-bit result.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param pIemCpu The.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param u8Result The result to set the flags according to.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param fToUpdate The flags to update.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param fUndefined The flags that are specified as undefined.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsyncstatic void iemHlpUpdateArithEFlagsU8(PIEMCPU pIemCpu, uint8_t u8Result, uint32_t fToUpdate, uint32_t fUndefined)
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync pCtx->eflags.u |= (fToUpdate | fUndefined) & fEFlags;
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * Loads a NULL data selector into a selector register, both the hidden and
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * visible parts, in protected mode.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param puSel The selector register.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * @param pHid The hidden register part.
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsyncstatic void iemHlpLoadNullDataSelectorProt(PRTSEL puSel, PCPUMSELREGHID pHid)
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync /** @todo Testcase: write a testcase checking what happends when loading a NULL
a3f3701cea1ba388e7c877955252bb7375eedebdvboxsync * data selector in protected mode. */
return rcStrict;
return rcStrict;
GCPtrBottom--;
return rcStrict;
GCPtrBottom--;
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
return VINF_SUCCESS;
switch (enmEffOpSize)
case IEMMODE_16BIT:
return rcStrict;
case IEMMODE_32BIT:
return rcStrict;
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
return rcStrict;
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
IEM_CIMPL_DEF_4(iemCImpl_BranchTaskSegment, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
IEM_CIMPL_DEF_4(iemCImpl_BranchTaskGate, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
IEM_CIMPL_DEF_4(iemCImpl_BranchCallGate, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
IEM_CIMPL_DEF_4(iemCImpl_BranchSysSel, uint16_t, uSel, IEMBRANCH, enmBranch, IEMMODE, enmEffOpSize, PIEMSELDESC, pDesc)
case AMD64_SEL_TYPE_SYS_LDT:
case X86_SEL_TYPE_SYS_LDT:
#ifdef IEM_VERIFICATION_MODE
return VINF_SUCCESS;
return rcStrict;
Log(("jmpf %04x:%08RX64 -> not a code selector (u4Type=%#x).\n", uSel, offSeg, Desc.Legacy.Gen.u4Type));
Log(("jmpf %04x:%08RX64 -> CPL != DPL; DPL=%d CPL=%u\n", uSel, offSeg, Desc.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
Log(("jmpf %04x:%08RX64 -> RPL > DPL; RPL=%d CPL=%u\n", uSel, offSeg, (uSel & X86_SEL_RPL), pIemCpu->uCpl));
u64Base = 0;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
#ifdef IEM_VERIFICATION_MODE
return VINF_SUCCESS;
return rcStrict;
Log(("callf %04x:%08RX64 -> not a code selector (u4Type=%#x).\n", uSel, offSeg, Desc.Legacy.Gen.u4Type));
Log(("callf %04x:%08RX64 -> CPL != DPL; DPL=%d CPL=%u\n", uSel, offSeg, Desc.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
Log(("callf %04x:%08RX64 -> RPL > DPL; RPL=%d CPL=%u\n", uSel, offSeg, (uSel & X86_SEL_RPL), pIemCpu->uCpl));
return rcStrict;
u64Base = 0;
return rcStrict;
uPtrRet.pu32[1] = pCtx->cs; /** @todo Testcase: What is written to the high word when callf is pushing CS? */
uPtrRet.pu64[1] = pCtx->cs; /** @todo Testcase: What is written to the high words when callf is pushing CS? */
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
if (cbPop)
return VINF_SUCCESS;
return rcStrict;
if ( DescCs.Legacy.Gen.u1Long /** @todo Testcase: far return to a selector with both L and D set. */
return rcStrict;
return rcStrict;
Log(("retf %04x:%08RX64 %04x:%08RX64 - SS.RPL != CS.RPL -> #GP(SS)\n", uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp));
Log(("retf %04x:%08RX64 %04x:%08RX64 - SS not a writable data segment (u1DescType=%u u4Type=%#x) -> #GP(SS).\n",
uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp, DescSs.Legacy.Gen.u1DescType, DescSs.Legacy.Gen.u4Type));
if ( DescSs.Legacy.Gen.u1Long /** @todo Testcase: far return to a stack selector with both L and D set. */
uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp, DescSs.Legacy.Gen.u1DescType, DescSs.Legacy.Gen.u4Type));
Log(("retf %04x:%08RX64 %04x:%08RX64 - SS not present -> #NP(SS).\n", uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp));
Log(("retf %04x:%08RX64 %04x:%08RX64 - not canonical -> #GP.\n", uNewCs, uNewRip, uNewOuterSs, uNewOuterRsp));
u64Base = 0;
return rcStrict;
return rcStrict;
return rcStrict;
pCtx->rip = uNewRip & UINT16_MAX; /** @todo Testcase: When exactly does this occur? With call it happens prior to the limit check according to Intel... */
if (cbPop)
u64Base = 0;
return rcStrict;
return rcStrict;
pCtx->rip = uNewRip & UINT16_MAX; /** @todo Testcase: When exactly does this occur? With call it happens prior to the limit check according to Intel... */
if (cbPop)
return VINF_SUCCESS;
switch (enmEffOpSize)
case IEMMODE_16BIT:
NewRip.u = 0;
case IEMMODE_32BIT:
NewRip.u = 0;
case IEMMODE_64BIT:
return rcStrict;
if (cbPop)
return VINF_SUCCESS;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
NewRbp.u = 0;
case IEMMODE_64BIT:
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
| X86_EFL_ID;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return rcStrict;
rcStrict = iemMemCommitAndUnmap(pIemCpu, (void *)uFrame.pv, IEM_ACCESS_STACK_R); /* don't use iemMemStackPopCommitSpecial here. */
return rcStrict;
Log(("iret %04x:%08x - rcStrict=%Rrc when fetching CS\n", uNewCs, uNewEip, VBOXSTRICTRC_VAL(rcStrict)));
return rcStrict;
Log(("iret %04x:%08x - CS is system segment (%#x) -> #GP\n", uNewCs, uNewEip, DescCS.Legacy.Gen.u4Type));
Log(("iret %04x:%08x - not code segment (%#x) -> #GP\n", uNewCs, uNewEip, DescCS.Legacy.Gen.u4Type));
return rcStrict;
return rcStrict;
return rcStrict;
Log(("iret %04x:%08x/%04x:%08x -> invalid SS selector, #GP(0)\n", uNewCs, uNewEip, uNewSS, uNewESP));
return rcStrict;
return rcStrict;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rcStrict;
Log(("load sreg SS, %#x - DPL (%d) and CPL (%d) differs -> #GP\n", uSel, Desc.Legacy.Gen.u2Dpl, pIemCpu->uCpl));
u64Base = 0;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
switch (enmEffOpSize)
case IEMMODE_16BIT:
case IEMMODE_32BIT:
case IEMMODE_64BIT:
return rcStrict;
VBOXSTRICTRC rcStrict = iemMemFetchDataXdtr(pIemCpu, &cbLimit, &GCPtrBase, iEffSeg, GCPtrEffSrc, enmEffOpSize);
return rcStrict;
VBOXSTRICTRC rcStrict = iemMemFetchDataXdtr(pIemCpu, &cbLimit, &GCPtrBase, iEffSeg, GCPtrEffSrc, enmEffOpSize);
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
return VINF_SUCCESS;
return rcStrict;
if ( Desc.Legacy.Gen.u4Type != X86_SEL_TYPE_SYS_386_TSS_AVAIL /* same as AMD64_SEL_TYPE_SYS_TSS_AVAIL */
Log(("ltr %#x - not an available TSS selector (type %x) -> #GP\n", uNewTr, Desc.Legacy.Gen.u4Type));
void *pvDesc;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
switch (iCrReg)
AssertFailedReturn(VERR_IEM_ASPECT_NOT_IMPLEMENTED); /** @todo implement CR8 reading and writing. */
return VINF_SUCCESS;
int rc;
switch (iCrReg)
Log(("Trying to set reserved CR0 bits: NewCR0=%#llx InvalidBits=%#llx\n", uNewCrX, uNewCrX & ~(uint64_t)fValid));
Log(("Trying to set reserved CR4 bits: NewCR4=%#llx InvalidBits=%#llx\n", uNewCrX, uNewCrX & ~(uint64_t)fValid));
AssertFailedReturn(VERR_IEM_ASPECT_NOT_IMPLEMENTED); /** @todo implement CR8 reading and writing. */
return rcStrict;
switch (iDrReg)
return VINF_SUCCESS;
switch (iDrReg)
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
#ifdef IEM_VERIFICATION_MODE
return VINF_SUCCESS;
return VINF_SUCCESS;
return rcStrict;
switch (cbReg)
return rcStrict;
switch (cbReg)
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_EM_HALT;
CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), pCtx->eax, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx);
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
#include "IEMAllCImplStrInstr.cpp.h"
return VINF_SUCCESS;
void *pvMem512;
VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, &pvMem512, 512, iEffSeg, GCPtrEff, IEM_ACCESS_DATA_W | IEM_ACCESS_PARTIAL_WRITE);
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
void *pvMem512;
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
static void iemCImplCommonFpuStoreEnv(PIEMCPU pIemCpu, IEMMODE enmEffOpSize, RTPTRUNION uPtr, PCCPUMCTX pCtx)
static void iemCImplCommonFpuRestoreEnv(PIEMCPU pIemCpu, IEMMODE enmEffOpSize, RTCPTRUNION uPtr, PCPUMCTX pCtx)
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
VBOXSTRICTRC rcStrict = iemMemMap(pIemCpu, (void **)&uPtr.pv, enmEffOpSize == IEMMODE_16BIT ? 14 : 28,
return rcStrict;
return rcStrict;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
uint32_t u32Eflags = pfnAImpl(&pCtx->fpu, &u16Fsw, &pCtx->fpu.aRegs[0].r80, &pCtx->fpu.aRegs[iStReg].r80);
fPop = false;
if (fPop)
return VINF_SUCCESS;