cidet-core.cpp revision fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986a
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * CPU Instruction Decoding & Execution Tests - Simple Instructions.
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2014 Oracle Corporation
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * available from http://www.virtualbox.org. This file is free software;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * General Public License (GPL) as published by the Free Software
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The contents of this file may alternatively be used under the terms
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * of the Common Development and Distribution License Version 1.0
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * CDDL are applicable instead of those of the GPL.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * You may elect to license modified versions of this file under the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * terms and conditions of either the GPL or the CDDL or both.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/*******************************************************************************
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync* Defined Constants And Macros *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync*******************************************************************************/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define CIDET_INSTR_TEST_OP_FLAG(a_pInstr, a_fFlag) \
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync#define CIDET_INSTR_TEST_OP_MASK_VALUE(a_pInstr, a_fMask, a_fValue) \
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync ( ((a_pInstr)->afOperands[0] & (a_fMask)) == (a_fValue) \
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync || ((a_pInstr)->afOperands[1] & (a_fMask)) == (a_fValue) \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ( ((a_pInstr)->afOperands[2] & (a_fMask)) == (a_fValue) \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || ((a_pInstr)->afOperands[3] & (a_fMask)) == (a_fValue) ) ) )
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/** @def CIDET_DPRINTF
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Debug printf. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync# define CIDET_DPRINTF(a) do { RTPrintf a; } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync# define CIDET_DPRINTF(a) do { } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/** @def CIDET_DEBUG_DISAS
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Enables instruction disassembly. */
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync/*******************************************************************************
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync* Header Files *
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync*******************************************************************************/
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync#if defined(CIDET_DPRINTF_ENABLED) || defined(CIDET_DEBUG_DISAS)
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync/*******************************************************************************
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync* Global Variables *
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync*******************************************************************************/
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync/** For translating CIDET_OF_Z_XXX values (after shifting). */
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync /* [CIDET_OF_Z_NONE] = */ 0,
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync /* [0xa] = */ 0,
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync /* [0xb] = */ 0,
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync /* [0xc] = */ 0,
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync /* [0xd] = */ 0,
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync /* [0xe] = */ 0,
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync/** Converts operand sizes in bytes to 64-bit masks. */
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync/** Converts operand sizes in bytes to 64-bit signed max values. */
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsyncbool CidetInstrHasMrmMemOperand(PCCIDETINSTR pInstr)
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync return CIDET_INSTR_TEST_OP_FLAG(pInstr, CIDET_OF_M_RM_ONLY_M);
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsyncbool CidetInstrHasMrmRegOperand(PCCIDETINSTR pInstr)
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync return CIDET_INSTR_TEST_OP_FLAG(pInstr, CIDET_OF_M_RM_ONLY_R);
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsyncbool CidetInstrRespondsToOperandSizePrefixes(PCCIDETINSTR pInstr)
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync return CIDET_INSTR_TEST_OP_MASK_VALUE(pInstr, CIDET_OF_Z_MASK, CIDET_OF_Z_VAR_WDQ);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertPtr(pThis); Assert(pThis->u32Magic == CIDETCORE_MAGIC);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Report a test failure via CIDET::pfnFailure
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync * @returns false
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis Pointer to the core structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pszFormat Format string containing failure details.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param va Arguments referenced in @a pszFormat.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncint CidetCoreSetErrorV(PCIDETCORE pThis, const char *pszFormat, va_list va)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync * Report a test failure via CIDET::pfnFailure
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns false
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis Pointer to the core structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pszFormat Format string containing failure details.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param ... Arguments referenced in @a pszFormat.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetError(PCIDETCORE pThis, const char *pszFormat, ...)
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Get a signed random number, with a given number of significant bytes.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns Random number.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis Pointer to the core structure.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * @param cbSignificant The number of significant bytes.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsyncint64_t CidetCoreGetRandS64(PCIDETCORE pThis, uint8_t cbSignificant)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * Get an unsigned random number, with a given number of significant bytes.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * @returns Random number.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis Pointer to the core structure.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * @param cbSignificant The number of significant bytes.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsyncuint64_t CidetCoreGetRandU64(PCIDETCORE pThis, uint8_t cbSignificant)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(cbSignificant == 1 || cbSignificant == 2 || cbSignificant == 4 || cbSignificant == 8);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncvoid CidetCoreInitializeCtxTemplate(PCIDETCORE pThis)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync pThis->InTemplateCtx.rfl = X86_EFL_1 | X86_EFL_ID | X86_EFL_IF;
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync unsigned i = RT_ELEMENTS(pThis->InTemplateCtx.aGRegs);
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync while (i-- > 0)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync pThis->InTemplateCtx.aGRegs[i] = UINT64_C(0x3fefcc00daba005d)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync while (i-- > 0)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync pThis->InTemplateCtx.aGRegs[i] = UINT64_C(0xfada009b)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync while (i-- > 0)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync pThis->InTemplateCtx.aSRegs[i] = 0; /* Front end sets these afterwards. */
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * Sets the target mode.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * Caller must set up default selector values after calling this function.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * @returns VBox status code.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * @param pThis Pointer to the core structure.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync * @param bMode The new mode.
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsyncint CidetCoreSetTargetMode(PCIDETCORE pThis, uint8_t bMode)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == CIDETCORE_MAGIC, VERR_INVALID_HANDLE);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync //case CIDETMODE_RM:
359416647a711739d1b14addbf399178949a1a60vboxsync //case CIDETMODE_PE_16:
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync //case CIDETMODE_PE_32:
359416647a711739d1b14addbf399178949a1a60vboxsync //case CIDETMODE_PE_V86:
359416647a711739d1b14addbf399178949a1a60vboxsync //case CIDETMODE_PP_16:
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync //case CIDETMODE_PP_V86:
359416647a711739d1b14addbf399178949a1a60vboxsync //case CIDETMODE_PAE_16:
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync //case CIDETMODE_PAE_V86:
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync //case CIDETMODE_LM_S16:
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync //case CIDETMODE_LM_32:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreIsEncodingCompatibleWithInstruction(PCIDETCORE pThis)
1389294d44ac76b0a25f5655756c9d39855a73efvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the next address size mode.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_AddressSize(PCIDETCORE pThis)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Reset to default.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->cbAddrMode = CIDETMODE_GET_BYTE_COUNT(pThis->bMode);
359416647a711739d1b14addbf399178949a1a60vboxsync * The other addressing size.
359416647a711739d1b14addbf399178949a1a60vboxsync * Selects the first REG encoding.
359416647a711739d1b14addbf399178949a1a60vboxsync * @param pThis The core state structure.
359416647a711739d1b14addbf399178949a1a60vboxsyncstatic void cidetCoreSetupFirstBaseEncoding_MrmReg(PCIDETCORE pThis)
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsMem = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsRipRelative = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsHighByteRegister = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].cbMemDisp = 0;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].iMemBaseReg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].iMemIndexReg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].uMemScale = 1;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].iEffSeg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync * Selects the next REG (ModR/M) encoding.
359416647a711739d1b14addbf399178949a1a60vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
359416647a711739d1b14addbf399178949a1a60vboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmReg(PCIDETCORE pThis, uint8_t iReg)
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(pThis->idxMrmRegOp < RT_ELEMENTS(pThis->aOperands) && !pThis->aOperands[pThis->idxMrmRegOp].fIsMem);
359416647a711739d1b14addbf399178949a1a60vboxsync * Clear the collision flags here because of the byte register kludge.
359416647a711739d1b14addbf399178949a1a60vboxsync * Clear the REX prefix and high byte register tracking too. ASSUMES MrmReg is after MrmRmMod.
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsHighByteRegister = false;
41fcf8465b641c7083d3b440451f17c1210fce33vboxsync * Special kludge for ah, ch, dh, bh, spl, bpl, sil, and dil.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Needs extra care in 64-bit mode and special collision detection code.
41fcf8465b641c7083d3b440451f17c1210fce33vboxsync CIDET_DPRINTF(("aOperands[%u].cb=%u fGpr=%u iReg=%d fRex=%d fRexW=%u fRexX=%u fRexB=%u fRexR=%d\n",
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->idxMrmRegOp, pThis->aOperands[pThis->idxMrmRegOp].cb, CIDET_OF_K_IS_GPR(pThis->fMrmRegOp), iReg,
ad290511521ce8388a9926b165241ecf83c330a7vboxsync pThis->fRex, pThis->fRexW, pThis->fRexX, pThis->fRexB, pThis->fRexR));
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync || (CIDETMODE_IS_64BIT(pThis->bMode) && iReg == 7 && !pThis->fRex)) )
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync if (!pThis->fRex && iReg >= 4 && CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix)
bdbed0b8e7fb553d01417fdc976a76f3b287dbe2vboxsync /* The AMD64 low variants: spl, bpl, sil and dil. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasStackRegInMrmReg = iReg == X86_GREG_xSP;
359416647a711739d1b14addbf399178949a1a60vboxsync /* Check for collisions. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRmOp)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && iReg == pThis->aOperands[pThis->idxMrmRmOp].iReg;
329df9696e709dc71611f504a4774f323545be0avboxsync Assert(!pThis->fUsesVexIndexRegs || pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg == UINT8_MAX);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMemIndex = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
359416647a711739d1b14addbf399178949a1a60vboxsync /* Next register: ah, ch, dh and bh. */
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->bModRm |= (iReg & X86_MODRM_REG_SMASK) << X86_MODRM_REG_SHIFT;
4ecd4ad59281328476ad14f2baa51716b6f5f804vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsHighByteRegister = true;
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(!pThis->fRexW); Assert(!pThis->fRexX); Assert(!pThis->fRexB);
359416647a711739d1b14addbf399178949a1a60vboxsync /* Check for collisions. */
359416647a711739d1b14addbf399178949a1a60vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRmOp)
359416647a711739d1b14addbf399178949a1a60vboxsync && iReg == pThis->aOperands[pThis->idxMrmRmOp].iReg
359416647a711739d1b14addbf399178949a1a60vboxsync && iReg - 4 == pThis->aOperands[pThis->idxMrmRmOp].iReg));
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(!pThis->fUsesVexIndexRegs || pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg == UINT8_MAX);
46737b2c6b2da473108a7670c3682d88474bd8b9vboxsync pThis->fHasRegCollisionMemBase = iReg - 4 == pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMemIndex = iReg - 4 == pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
359416647a711739d1b14addbf399178949a1a60vboxsync return true;
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(!pThis->fRex || (iReg == 7 && CIDETMODE_IS_64BIT(pThis->bMode)));
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * Next register.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync iReg = (iReg + 1) & (CIDETMODE_IS_64BIT(pThis->bMode) ? 15 : 7);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pThis->bModRm |= (iReg & X86_MODRM_REG_SMASK) << X86_MODRM_REG_SHIFT;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasStackRegInMrmReg = iReg == X86_GREG_xSP && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
359416647a711739d1b14addbf399178949a1a60vboxsync * Register collision detection.
359416647a711739d1b14addbf399178949a1a60vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionDirect = iReg == pThis->aOperands[pThis->idxMrmRmOp].iReg
359416647a711739d1b14addbf399178949a1a60vboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(!pThis->fUsesVexIndexRegs || pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg == UINT8_MAX);
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMemIndex = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
359416647a711739d1b14addbf399178949a1a60vboxsync return iReg != 0;
09f4b412099acda62997fd82c8608075c453b3ebvboxsync * Selects the next MOD & R/M encoding, 16-bit addressing variant.
359416647a711739d1b14addbf399178949a1a60vboxsync * @param pThis The core state structure.
359416647a711739d1b14addbf399178949a1a60vboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
359416647a711739d1b14addbf399178949a1a60vboxsyncstatic void cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(PCIDETCORE pThis, uint8_t iReg)
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
09f4b412099acda62997fd82c8608075c453b3ebvboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(CidetInstrHasMrmMemOperand(pThis->pCurInstr));
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMemBase = iReg == X86_GREG_xBX && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMemIndex = iReg == X86_GREG_xSI && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
359416647a711739d1b14addbf399178949a1a60vboxsync * Selects the next MOD & R/M encoding, 16-bit addressing variant.
359416647a711739d1b14addbf399178949a1a60vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
359416647a711739d1b14addbf399178949a1a60vboxsync * @param pThis The core state structure.
09f4b412099acda62997fd82c8608075c453b3ebvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
359416647a711739d1b14addbf399178949a1a60vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmRmMod_16bit(PCIDETCORE pThis, uint8_t iReg)
359416647a711739d1b14addbf399178949a1a60vboxsync uint8_t iMod = (pThis->bModRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK;
359416647a711739d1b14addbf399178949a1a60vboxsync * Register access mode.
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && !pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
359416647a711739d1b14addbf399178949a1a60vboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->fHasStackRegInMrmRmBase = iRm == X86_GREG_xSP && CIDET_OF_K_IS_GPR(pThis->fMrmRmOp);
359416647a711739d1b14addbf399178949a1a60vboxsync return true;
09f4b412099acda62997fd82c8608075c453b3ebvboxsync /* If no memory modes, we're done. */
09f4b412099acda62997fd82c8608075c453b3ebvboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(pThis, iReg);
359416647a711739d1b14addbf399178949a1a60vboxsync return false;
359416647a711739d1b14addbf399178949a1a60vboxsync /* Next mode: 16-bit memory addressing without displacement. */
359416647a711739d1b14addbf399178949a1a60vboxsync * Memory access mode.
359416647a711739d1b14addbf399178949a1a60vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xDI;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBP;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBP;
359416647a711739d1b14addbf399178949a1a60vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xDI;
09f4b412099acda62997fd82c8608075c453b3ebvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xDI;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBP;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemIndex = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return true;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync /* Last mode? */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(pThis, iReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync /* Next memory addressing mode (if any). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemBase = iReg == X86_GREG_xBX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemIndex = iReg == X86_GREG_xSI;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the first MOD & R/M encoding, 32-bit and 64-bit addressing variant.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param f64Bit Set if 64-bit, clear if 32-bit.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic void cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(PCIDETCORE pThis, uint8_t iReg, bool f64Bit)
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = false;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(CidetInstrHasMrmMemOperand(pThis->pCurInstr));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->fHasHighByteRegInMrmReg * 4 && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the next MOD & R/M encoding, 32-bit and 64-bit addressing variant.
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param f64Bit Set if 64-bit, clear if 32-bit.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmRmMod_32bit64bit(PCIDETCORE pThis, uint8_t iReg, bool f64Bit)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertRelease(!pThis->fRexX || CIDETMODE_IS_64BIT(pThis->bMode));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertRelease(!pThis->fRexB || CIDETMODE_IS_64BIT(pThis->bMode));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t iRm = (pThis->bModRm & X86_MODRM_RM_MASK) + pThis->fRexB * 8;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t iMod = (pThis->bModRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Register access mode.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && !pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fRexX && !pThis->fNoRexPrefix) /* should be ignored. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Reset the byte register kludges variables. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (iRm < (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix ? 15 : 7))
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * Byte register kludge.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (iRm == 7 && CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fRexX) ) )
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (!pThis->fRexX && iRm >= 4 && CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* The AMD64 low variants: spl, bpl, sil and dil. (Using fRexX here as REG covers fRex.) */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRegOp)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && iRm == iReg - pThis->fHasHighByteRegInMrmReg * 4;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasStackRegInMrmRmBase = iRm == X86_GREG_xSP && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Next register: ah, ch, dh and bh. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (!pThis->fRexR && !pThis->fRexW && !pThis->fRex)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRegOp)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && iRm - 4 == iReg - pThis->fHasHighByteRegInMrmReg * 4;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Can't do the high stuff, so do the spl, bpl, sil and dil variation instead.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Note! We don't set the RexX yet since the base register or operand width holds it down. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRegOp)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && iRm == iReg - pThis->fHasHighByteRegInMrmReg * 4;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasStackRegInMrmRmBase = iRm == X86_GREG_xSP && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Normal register.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionDirect = iRm == iReg && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasStackRegInMrmRmBase = iRm == X86_GREG_xSP && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* If no memory modes, we're done. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, f64Bit);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Next mode: 32-bit/64-bit memory addressing without displacement. */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync * Memory access mode.
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync if (iRm < (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix ? 15 : 7))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync iRm++; /* Leave REX.B=1 to the next-sib-base function. */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = 0;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = 0;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync /* Absolute or wrt rip addressing. */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = CIDETMODE_IS_64BIT(pThis->bMode);
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = iRm;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->fHasRegCollisionMemIndex = iReg == pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync return true;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync /* Last mode? */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, f64Bit);
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync return false;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync /* Next memory addressing mode (if any). */
ad290511521ce8388a9926b165241ecf83c330a7vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = iMod == 1 ? 1 : 4;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = 0;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->fHasHighByteRegInMrmReg * 4
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the next MOD & R/M encoding.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmRmMod(PCIDETCORE pThis, uint8_t iReg)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return cidetCoreSetupNextBaseEncoding_MrmRmMod_16bit(pThis, iReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return cidetCoreSetupNextBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, false);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return cidetCoreSetupNextBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, true);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the next SIB base register (/ encoding).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
2721dfb0e330d57ba888311520f5a343c64e7cefvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SibBase(PCIDETCORE pThis, uint8_t iReg)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertRelease(!pThis->fRexB || CIDETMODE_IS_64BIT(pThis->bMode));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t iBase = (pThis->bSib & X86_SIB_BASE_MASK) + pThis->fRexB * 8;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync iBase = (iBase + 1) & (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix ? 15 : 7);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ((iBase & 7) == 5 && (pThis->bModRm & X86_MODRM_MOD_MASK) == 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ((iBase & 7) == 6 && (pThis->bModRm & X86_MODRM_MOD_MASK) == 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = iBase;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemBase = pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasStackRegInMrmRmBase = iBase == X86_GREG_xSP;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return iBase != 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the next SIB index register (/ encoding).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SibIndex(PCIDETCORE pThis, uint8_t iReg)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertRelease(!pThis->fRexX || CIDETMODE_IS_64BIT(pThis->bMode));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t iIndex = ((pThis->bSib >> X86_SIB_INDEX_SHIFT) & X86_SIB_INDEX_SMASK) + pThis->fRexX * 8;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync iIndex = (iIndex + 1) & (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix ? 15 : 7);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = iIndex;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->bSib |= (iIndex & X86_SIB_INDEX_SMASK) << X86_SIB_INDEX_SHIFT;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMemIndex = pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync ? CIDET_OF_K_IS_GPR(pThis->fMrmRegOp) : CIDET_OF_K_IS_VRX(pThis->fMrmRegOp) );
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return iIndex != 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Selects the next SIB scale.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SibScale(PCIDETCORE pThis, uint8_t iReg)
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync switch ((pThis->bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync return false;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync * Selects the next segment prefix.
ad290511521ce8388a9926b165241ecf83c330a7vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SegmentPrefix(PCIDETCORE pThis)
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* fall thru */
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return true;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync /* fall thru */
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return true;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync /* fall thru */
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
09f4b412099acda62997fd82c8608075c453b3ebvboxsync /* fall thru */
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return true;
c7d2f5508ab9703a7a6c5cce5c9d4bf335af660avboxsync /* fall thru */
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* fall thru */
67b8a5a52c43a79ea7e159dbbeec99687fb9cd3bvboxsync return false;
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * Updates the variable sized operands.
ad290511521ce8388a9926b165241ecf83c330a7vboxsync * @param pThis The core state structure.
ad290511521ce8388a9926b165241ecf83c330a7vboxsyncstatic void cidetCoreUpdateOperandSizes(PCIDETCORE pThis)
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync while (iOp-- > 0)
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pThis->aOperands[iOp].cb = (uint8_t)CidetCoreGetOperandSize(pThis, iOp);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * Selects the next operand size.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * @param pThis The core state structure.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_OperandSize(PCIDETCORE pThis)
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync if (CidetInstrRespondsToOperandSizePrefixes(pThis->pCurInstr))
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pThis->fOpSizePrf = true; /* check that it's ignored. */
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return false;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsyncbool CidetCoreSetupNextBaseEncoding(PCIDETCORE pThis)
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync * The wheels are lined up as follows:
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync * 1. Address size prefix.
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync * 2. MODRM.MOD
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 3. MODRM.REG + REX.R
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 4. MODRM.R/M + REX.B
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 5. SIB - MODRM.R/M == 4 && MODRM.MOD != 3:
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 5a) SIB.BASE + REX.B
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 5b) SIB.INDEX + REX.X
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 5c) SIB.SCALE
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 6. Segment prefix overrides if applicable and supported (memory).
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * 7. Operand size prefix and REX.W if applicable.
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync if (cidetCoreSetupNextBaseEncoding_OperandSize(pThis))
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync return true;
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync if (cidetCoreSetupNextBaseEncoding_SegmentPrefix(pThis))
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync return true;
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync /* The ModR/M register value for collision detection. */
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync uint8_t iReg = ((pThis->bModRm >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK) + pThis->fRexR * 8;
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync if (cidetCoreSetupNextBaseEncoding_SibScale(pThis, iReg))
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync return true;
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync if (cidetCoreSetupNextBaseEncoding_SibIndex(pThis, iReg))
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync return true;
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync if (cidetCoreSetupNextBaseEncoding_SibBase(pThis, iReg))
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync return true;
6b2a50fc09aa4f7ce2082284f082d97a2c738321vboxsync if (cidetCoreSetupNextBaseEncoding_MrmRmMod(pThis, iReg))
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync if (cidetCoreSetupNextBaseEncoding_MrmReg(pThis, iReg))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (cidetCoreSetupNextBaseEncoding_AddressSize(pThis))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetupFirstBaseEncoding(PCIDETCORE pThis)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Reset all the knobs and wheels.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Indicators. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->cbAddrMode = CIDETMODE_GET_BYTE_COUNT(pThis->bMode);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Now, drill down on the instruction encoding.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(pThis, 0);
ad290511521ce8388a9926b165241ecf83c330a7vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, 0, false);
ad290511521ce8388a9926b165241ecf83c330a7vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, 0, true);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The next memory operand configuration.
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync * @returns true if new one to test, false if we've reached end already.
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetupNextMemoryOperandConfig(PCIDETCORE pThis)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Sets up the first memory operand configuration and counts memory operands.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true on success, false if no data buffers configured or failure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetupFirstMemoryOperandConfig(PCIDETCORE pThis)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync while (idxOp-- > 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo implement more than one memory operand. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertReleaseReturn(pThis->cMemoryOperands <= 1, false);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The next code buffer configuration.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true if new one to test, false if we've reached end already.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetupNextCodeBufferConfig(PCIDETCORE pThis)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Sets up the first code buffer configuration.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true on success, false if no data buffers configured or failure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetupFirstCodeBufferConfig(PCIDETCORE pThis)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(CIDETBUF_IS_CODE(pThis->paCodeBufConfigs[0].fFlags));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->CodeBuf.enmExpectXcpt = kCidetExpectXcpt_None;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Gets the (encoded) size of the given operand in the current context.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns Size in bytes.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure (for context).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param iOp The operand index.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncuint32_t CidetCoreGetOperandSize(PCIDETCORE pThis, uint8_t iOp)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t cbOp = g_acbCidetOfSizes[(pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) >> CIDET_OF_Z_SHIFT];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_VAR_WDQ);
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_SPECIAL);
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync case 1: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_BYTE); break;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync case 2: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_WORD); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync case 4: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_DWORD); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync case 8: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_QWORD); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync case 10: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_TBYTE); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync case 16: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_OWORD); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync case 32: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_YWORD); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync case 64: Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_ZWORD); break;
fdb57e5580007400346665b64c0e14ca1d149019vboxsyncbool CideCoreSetInstruction(PCIDETCORE pThis, PCCIDETINSTR pInstr)
fdb57e5580007400346665b64c0e14ca1d149019vboxsync AssertReleaseMsgReturn(RT_VALID_PTR(pInstr), ("%p\n", pInstr), false);
fdb57e5580007400346665b64c0e14ca1d149019vboxsync * Extract info from the instruction descriptor.
fdb57e5580007400346665b64c0e14ca1d149019vboxsync for (uint8_t iOp = 0; iOp < pInstr->cOperands; iOp++)
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].fFlags = pInstr->afOperands[iOp];
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].cb = (uint8_t)CidetCoreGetOperandSize(pThis, iOp);
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].fIsImmediate = (pInstr->afOperands[iOp] & CIDET_OF_K_MASK) == CIDET_OF_K_IMM;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].fIsMem = (pInstr->afOperands[iOp] & CIDET_OF_K_MASK) == CIDET_OF_K_MEM;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].uMemBaseRegValue = UINT64_MAX;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].uMemIndexRegValue = UINT64_MAX;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].uMemBaseRegValue = UINT64_MAX;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync pThis->aOperands[iOp].uMemIndexRegValue = UINT64_MAX;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync * Reset various things.
fdb57e5580007400346665b64c0e14ca1d149019vboxsync return true;
fdb57e5580007400346665b64c0e14ca1d149019vboxsync * Enumerate the operands.
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync while (idxOp-- > 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Memory operand.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Set the In & Expected members to point to temporary buffer space. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Initialize the buffer we're gonna use. */
e6ad2e18e663b076aeabfec994947514566a7accvboxsync pThis->aOperands[idxOp].iEffSeg = pThis->uSegPrf != X86_SREG_COUNT
e6ad2e18e663b076aeabfec994947514566a7accvboxsync : !(pThis->aOperands[idxOp].fFlags & CIDET_OF_ALWAYS_SEG_ES) ? X86_SREG_DS
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PCIDETBUF pDataBuf = pThis->aOperands[idxOp].pDataBuf;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pDataBuf->cb == pThis->aOperands[idxOp].cb);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
3ea1dbf096240fc221aea99352a74c17a367a9b6vboxsync /* Calc buffer related operand members. */
3ea1dbf096240fc221aea99352a74c17a367a9b6vboxsync pThis->aOperands[idxOp].uEffAddr = pDataBuf->uEffBufAddr + pDataBuf->off;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint64_t offSeg = pThis->aOperands[idxOp].uEffAddr - pDataBuf->uSegBase;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertRelease(offSeg <= g_au64ByteSizeToMask[pThis->cbAddrMode]);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Select register and displacement values for the buffer addressing (works on offSeg).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t const iMemIndexReg = pThis->aOperands[idxOp].iMemIndexReg;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t const iMemBaseReg = pThis->aOperands[idxOp].iMemBaseReg;
dc959f60f6d3e0cba86f7da4d39aa475913a7e10vboxsync /* rip relative. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue = offSeg - (pThis->InCtx.rip + pThis->cbInstr);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( (int64_t)pThis->aOperands[idxOp].uImmDispValue > INT32_MAX
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (int64_t)pThis->aOperands[idxOp].uImmDispValue < INT32_MIN)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* [base] or [base + disp] or [base + index * scale] or [base + index * scale + disp] */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue = CidetCoreGetRandS64(pThis, pThis->aOperands[idxOp].cbMemDisp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offSeg -= (int64_t)pThis->aOperands[idxOp].uImmDispValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemIndexRegValue = CidetCoreGetRandU64(pThis, pThis->cbAddrMode);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offSeg -= pThis->aOperands[idxOp].uMemIndexRegValue * pThis->aOperands[idxOp].uMemScale;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemBaseRegValue = offSeg & g_au64ByteSizeToMask[pThis->cbAddrMode];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* base == index; [base + index * scale] or [base * (scale + 1)]. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t const uEffScale = pThis->aOperands[idxOp].uMemScale + 1;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue = CidetCoreGetRandS64(pThis, pThis->aOperands[idxOp].cbMemDisp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offSeg -= (int64_t)pThis->aOperands[idxOp].uImmDispValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert( (int64_t)pThis->aOperands[idxOp].uImmDispValue
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync <= g_ai64ByteSizeToMax[pThis->aOperands[idxOp].cbMemDisp]);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue = (int64_t)pThis->aOperands[idxOp].uImmDispValue
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( (int64_t)pThis->aOperands[idxOp].uImmDispValue
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync > g_ai64ByteSizeToMax[pThis->aOperands[idxOp].cbMemDisp])
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue -= uEffScale;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemBaseRegValue = pThis->aOperands[idxOp].uMemIndexRegValue = offSeg;
e6ad2e18e663b076aeabfec994947514566a7accvboxsync /* [index * scale] or [index * scale + disp] */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue = CidetCoreGetRandS64(pThis, pThis->aOperands[idxOp].cbMemDisp);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync offSeg -= (int64_t)pThis->aOperands[idxOp].uImmDispValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uImmDispValue += offSeg & (RT_BIT_64(pThis->aOperands[idxOp].uMemScale) - 1);
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync offSeg &= ~(RT_BIT_64(pThis->aOperands[idxOp].uMemScale) - 1);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else if (offSeg & (RT_BIT_64(pThis->aOperands[idxOp].uMemScale) - 1))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemIndexRegValue = offSeg / pThis->aOperands[idxOp].uMemScale;
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync Assert((offSeg % pThis->aOperands[idxOp].uMemScale) == 0);
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync AssertRelease(!pThis->fUsesVexIndexRegs); /** @todo implement VEX indexing */
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync /* [disp] */
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync : false /* 8 */)
1389294d44ac76b0a25f5655756c9d39855a73efvboxsync return false;
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * Modify the input and expected output contexts with the base and
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * index register values. To simplify verification and the work
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * here, we update the uMemBaseRegValue and uMemIndexRegValue
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * members to reflect the whole register.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemBaseRegValue &= UINT32_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemBaseRegValue |= pThis->InCtx.aGRegs[iMemBaseReg] & UINT64_C(0xffffffff00000000);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemBaseRegValue &= UINT16_MAX;
c58dc77ef4af214d7ae06910fa5ab18587d2ae08vboxsync pThis->aOperands[idxOp].uMemBaseRegValue |= pThis->InCtx.aGRegs[iMemBaseReg] & UINT64_C(0xffffffffffff0000);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->InCtx.aGRegs[iMemBaseReg] = pThis->aOperands[idxOp].uMemBaseRegValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->ExpectedCtx.aGRegs[iMemBaseReg] = pThis->aOperands[idxOp].uMemBaseRegValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemIndexRegValue &= UINT32_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemIndexRegValue |= pThis->InCtx.aGRegs[iMemIndexReg] & UINT64_C(0xffffffff00000000);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemIndexRegValue &= UINT16_MAX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].uMemIndexRegValue |= pThis->InCtx.aGRegs[iMemIndexReg] & UINT64_C(0xffffffffffff0000);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->InCtx.aGRegs[iMemIndexReg] = pThis->aOperands[idxOp].uMemIndexRegValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->ExpectedCtx.aGRegs[iMemIndexReg] = pThis->aOperands[idxOp].uMemIndexRegValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Non-memory, so clear the memory related members.
423b1ce7f19ff0687e825ddc42d8bc6c68a4c9cdvboxsync switch (pThis->aOperands[idxOp].fFlags & CIDET_OF_K_MASK)
423b1ce7f19ff0687e825ddc42d8bc6c68a4c9cdvboxsync pThis->aOperands[idxOp].In.pv = &pThis->InCtx.aGRegs[pThis->aOperands[idxOp].iReg];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->aOperands[idxOp].Expected.pv = &pThis->ExpectedCtx.aGRegs[pThis->aOperands[idxOp].iReg];
ad290511521ce8388a9926b165241ecf83c330a7vboxsync pThis->aOperands[idxOp].In.pv = &pThis->InCtx.aGRegs[pThis->aOperands[idxOp].iReg - 4];
ad290511521ce8388a9926b165241ecf83c330a7vboxsync pThis->aOperands[idxOp].Expected.pv = &pThis->ExpectedCtx.aGRegs[pThis->aOperands[idxOp].iReg - 4];
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync if (pThis->aOperands[idxOp].iReg < RT_ELEMENTS(pThis->InCtx.aSRegs))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[idxOp].In.pv = &pThis->InCtx.aSRegs[pThis->aOperands[idxOp].iReg];
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync pThis->aOperands[idxOp].Expected.pv = &pThis->ExpectedCtx.aSRegs[pThis->aOperands[idxOp].iReg];
fdb57e5580007400346665b64c0e14ca1d149019vboxsync /** @todo Implement testing these registers. */
fdb57e5580007400346665b64c0e14ca1d149019vboxsync AssertRelease((uintptr_t)pbBuf - (uintptr_t)&pThis->abBuf[0] <= sizeof(pThis->abBuf));
fdb57e5580007400346665b64c0e14ca1d149019vboxsync * Call instruction specific setup function (for operand values and flags).
fdb57e5580007400346665b64c0e14ca1d149019vboxsync int rc = pThis->pCurInstr->pfnSetupInOut(pThis, false /*fInvalid*/);
fdb57e5580007400346665b64c0e14ca1d149019vboxsync return false;
423b1ce7f19ff0687e825ddc42d8bc6c68a4c9cdvboxsync * Do the 2nd set of the memory operand preparations.
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync while (idxOp-- > 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (!pThis->pfnSetupDataBuf(pThis, pThis->aOperands[idxOp].pDataBuf, pThis->aOperands[idxOp].In.pv))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert( pThis->aOperands[idxOp].iMemBaseReg == UINT8_MAX
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || pThis->InCtx.aGRegs[pThis->aOperands[idxOp].iMemBaseReg] == pThis->aOperands[idxOp].uMemBaseRegValue);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert( pThis->aOperands[idxOp].iMemIndexReg == UINT8_MAX
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync ? pThis->InCtx.aGRegs[pThis->aOperands[idxOp].iMemIndexReg]
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync : false /** @todo VEX indexing */));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync * Figures the instruction length.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This is a duplicate of CidetCoreAssemble() with the buffer updates removed.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true and pThis->cbInstr on success, false on failure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure (for context).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Prefixes.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo prefix list. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Prefixes that must come right before the opcode.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo VEX and EVEX. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo VEX and EVEX. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo VEX and EVEX. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pThis->fRexB || pThis->fRexX || pThis->fRexR || pThis->fRexW || pThis->fRex)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The opcode.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t const *pbOpcode = pThis->pCurInstr->abOpcode;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint64_t uDispValue = pThis->aOperands[pThis->idxMrmRmOp].uImmDispValue;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync switch (pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 0: break;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync off += pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Immediates.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync while (iOp-- > 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ((pThis->aOperands[iOp].fFlags & CIDET_OF_K_MASK) == CIDET_OF_K_IMM)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint64_t uImmValue = pThis->aOperands[iOp].uImmDispValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Assembles the instruction.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This is a duplicate of CidetCoreAssembleLength() with buffer writes.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true and pThis->cbInstr and pThis->abInstr on success, false on
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure (for context).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Prefixes.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo prefix list. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Prefixes that must come right before the opcode.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo VEX and EVEX. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo VEX and EVEX. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo VEX and EVEX. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pThis->fRexB || pThis->fRexX || pThis->fRexR || pThis->fRexW || pThis->fRex)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->abInstr[off++] = 0x40 | (pThis->fRexB * 1) | (pThis->fRexX * 2) | (pThis->fRexR * 4) | (pThis->fRexW * 8);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The opcode.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t const *pbOpcode = pThis->pCurInstr->abOpcode;
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync uint64_t uDispValue = pThis->aOperands[pThis->idxMrmRmOp].uImmDispValue;
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync switch (pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp)
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync case 0: break;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 8: pThis->abInstr[off + 3] = (uDispValue >> 56) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 7: pThis->abInstr[off + 3] = (uDispValue >> 48) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 6: pThis->abInstr[off + 3] = (uDispValue >> 40) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 5: pThis->abInstr[off + 3] = (uDispValue >> 32) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 4: pThis->abInstr[off + 3] = (uDispValue >> 24) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 3: pThis->abInstr[off + 2] = (uDispValue >> 16) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 2: pThis->abInstr[off + 1] = (uDispValue >> 8) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 1: pThis->abInstr[off] = uDispValue & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync off += pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Immediates.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync while (iOp-- > 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ((pThis->aOperands[iOp].fFlags & CIDET_OF_K_MASK) == CIDET_OF_K_IMM)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint64_t uImmValue = pThis->aOperands[iOp].uImmDispValue;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 8: pThis->abInstr[off + 3] = (uImmValue >> 56) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 7: pThis->abInstr[off + 3] = (uImmValue >> 48) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 6: pThis->abInstr[off + 3] = (uImmValue >> 40) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 5: pThis->abInstr[off + 3] = (uImmValue >> 32) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 4: pThis->abInstr[off + 3] = (uImmValue >> 24) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 3: pThis->abInstr[off + 2] = (uImmValue >> 16) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 2: pThis->abInstr[off + 1] = (uImmValue >> 8) & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 1: pThis->abInstr[off] = uImmValue & UINT8_C(0xff);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Re-initialize the buffer. Requires instruction length and positioning.
6b2a50fc09aa4f7ce2082284f082d97a2c738321vboxsync pThis->CodeBuf.off = CIDET_CODE_BUF_SIZE - PAGE_SIZE - pThis->cbInstr;
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync if (pThis->pfnReInitCodeBuf(pThis, &pThis->CodeBuf))
c2e22ad3bb703daa53362d626dd2b4965e511142vboxsync * Update the RIP and CS values in the input and expected contexts.
c2e22ad3bb703daa53362d626dd2b4965e511142vboxsync pThis->InCtx.rip = pThis->CodeBuf.uEffBufAddr + pThis->CodeBuf.offActive - pThis->CodeBuf.uSegBase;
71c0735a959eefb3e0b7a3bd8c8640a5660584cavboxsync pThis->ExpectedCtx.rip = pThis->InCtx.rip + pThis->cbInstr; /** @todo account for expected traps. */
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync pThis->InCtx.aSRegs[X86_SREG_CS] = pThis->CodeBuf.uSeg;
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync pThis->ExpectedCtx.aSRegs[X86_SREG_CS] = pThis->CodeBuf.uSeg;
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync return true;
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @callback_method_impl{FNDISREADBYTES}
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic DECLCALLBACK(int) cidetCoreDisReadBytes(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync memcpy(&pDis->abInstr[offInstr], &pThis->abInstr[offInstr], cbMaxRead);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncbool CidetCoreSetupCodeBuf(PCIDETCORE pThis, unsigned iSubTest)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync //CIDET_DPRINTF(("%04u: %.*Rhxs\n", i, pThis->cbInstr, pThis->abInstr));
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync CIDETMODE_IS_64BIT(pThis->bMode) ? DISCPUMODE_64BIT
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync : CIDETMODE_IS_32BIT(pThis->bMode) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync if (pThis->pfnSetupCodeBuf(pThis, &pThis->CodeBuf, pThis->abInstr))
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return false;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Compares the output with the output expectations.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true if ok, false if not (calls pfnFailure too).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pThis The core state structure.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (memcmp(&pThis->ActualCtx, &pThis->ExpectedCtx, CIDETCPUCTX_COMPARE_SIZE) == 0)
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync unsigned cDiffs = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define IF_FIELD_DIFFERS_SET_ERROR(a_Field, a_Fmt) \
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync if (pThis->ActualCtx.a_Field != pThis->ExpectedCtx.a_Field) \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync CidetCoreSetError(pThis, #a_Field " differs: got %#llx expected %#llx", \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->ActualCtx.a_Field, pThis->ExpectedCtx.a_Field); \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } else do { } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xAX], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xBX], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xCX], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xDX], "%#010llx");
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xSP], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xBP], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xSI], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_xDI], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x8], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x9], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x9], "%#010llx");
be99a23d38fa03a9e93de71398f43ce4c4d7c685vboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x10], "%#010llx");
be99a23d38fa03a9e93de71398f43ce4c4d7c685vboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x11], "%#010llx");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x12], "%#010llx");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x13], "%#010llx");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x14], "%#010llx");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aGRegs[X86_GREG_x15], "%#010llx");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aSRegs[X86_SREG_CS], "%#06x");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aSRegs[X86_SREG_SS], "%#06x");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aSRegs[X86_SREG_DS], "%#06x");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aSRegs[X86_SREG_ES], "%#06x");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aSRegs[X86_SREG_FS], "%#06x");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync IF_FIELD_DIFFERS_SET_ERROR(aSRegs[X86_SREG_GS], "%#06x");
b6b29a7e040f2b46480aa596fe0861bb16ce3da5vboxsync return cDiffs == 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Iterate all encodings.
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync return CidetCoreSetError(pThis, "CidetCoreSetupFirstBaseEncoding failed");
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync unsigned cExecuted = 0;
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync unsigned cSkipped = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Iterate data buffer configurations (one iteration if none).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Iterate code buffer configurations.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return CidetCoreSetError(pThis, "CidetCoreSetupFirstMemoryOperandConfig failed");
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Set up inputs and expected outputs, then emit the test code.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pThis->InCtx.fTrickyStack = pThis->fHasStackRegInMrmRmBase || pThis->fHasStackRegInMrmReg;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && CidetCoreSetupCodeBuf(pThis, cSkipped + cExecuted)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Check the result against our expectations.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo check result. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } while (CidetCoreSetupNextCodeBufferConfig(pThis));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } while (CidetCoreSetupNextMemoryOperandConfig(pThis));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync CIDET_DPRINTF(("CidetCoreTest_Basic: cExecuted=%u cSkipped=%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedSetupInOut =%u\n"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync " cSkippedReInitDataBuf =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedSetupDataBuf =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedDataBufWrtRip =%u\n"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync " cSkippedAssemble =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedReInitCodeBuf =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedSetupCodeBuf =%u\n"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync " cSkippedSameBaseIndexRemainder =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedOnlyIndexRemainder =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync " cSkippedDirectAddressingOverflow =%u\n"
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync return true;
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsyncbool CidetCoreTestInstruction(PCIDETCORE pThis, PCCIDETINSTR pInstr)
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync AssertReleaseMsgReturn(RT_VALID_PTR(pThis), ("%p\n", pThis), false);
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync AssertReleaseReturn(pThis->u32Magic == CIDETCORE_MAGIC, false);
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync AssertReleaseReturn(pThis->cCodeBufConfigs > 0, false);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return CidetCoreSetError(pThis, "CideCoreSetInstruction failed");