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