3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/* $Id$ */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/** @file
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * CPU Instruction Decoding & Execution Tests - Simple Instructions.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Copyright (C) 2014 Oracle Corporation
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 *
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 *
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
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/*******************************************************************************
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync* Defined Constants And Macros *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync*******************************************************************************/
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync#define CIDET_INSTR_TEST_OP_FLAG(a_pInstr, a_fFlag) \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ( ((a_pInstr)->afOperands[0] & (a_fFlag)) \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || ((a_pInstr)->afOperands[1] & (a_fFlag)) \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || ( (a_pInstr)->cOperands > 2 \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && ( ((a_pInstr)->afOperands[2] & (a_fFlag)) \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || ((a_pInstr)->afOperands[3] & (a_fFlag)) ) ) )
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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)->cOperands > 2 \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && ( ((a_pInstr)->afOperands[2] & (a_fMask)) == (a_fValue) \
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || ((a_pInstr)->afOperands[3] & (a_fMask)) == (a_fValue) ) ) )
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/** @def CIDET_DPRINTF
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Debug printf. */
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#if 1 //def DEBUG_bird
694eb5fb2b25736d37902333e059a149f78c563cvboxsync# define CIDET_DPRINTF(a) do { RTPrintf a; } while (0)
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync# define CIDET_DPRINTF_ENABLED
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync#else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync# define CIDET_DPRINTF(a) do { } while (0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync#endif
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
694eb5fb2b25736d37902333e059a149f78c563cvboxsync/** @def CIDET_DEBUG_DISAS
694eb5fb2b25736d37902333e059a149f78c563cvboxsync * Enables instruction disassembly. */
694eb5fb2b25736d37902333e059a149f78c563cvboxsync#if defined(DOXYGEN_RUNNING)
694eb5fb2b25736d37902333e059a149f78c563cvboxsync# define CIDET_DEBUG_DISAS 1
694eb5fb2b25736d37902333e059a149f78c563cvboxsync#endif
694eb5fb2b25736d37902333e059a149f78c563cvboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync/*******************************************************************************
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync* Header Files *
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync*******************************************************************************/
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#include "cidet.h"
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#include <iprt/assert.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#include <iprt/rand.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#include <iprt/param.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#include <iprt/string.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#include <VBox/err.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#if defined(CIDET_DPRINTF_ENABLED) || defined(CIDET_DEBUG_DISAS)
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync# include <VBox/dis.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync# include <iprt/stream.h>
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#endif
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/*******************************************************************************
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync* Global Variables *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync*******************************************************************************/
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/** For translating CIDET_OF_Z_XXX values (after shifting). */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncuint16_t const g_acbCidetOfSizes[] =
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_NONE] = */ 0,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_BYTE] = */ 1,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_WORD] = */ 2,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_DWORD] = */ 4,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_QWORD] = */ 8,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_TBYTE] = */ 10,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_OWORD] = */ 16,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_YWORD] = */ 32,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_ZWORD] = */ 64,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_VAR_WDQ] = */ UINT16_MAX,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [0xa] = */ 0,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [0xb] = */ 0,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [0xc] = */ 0,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [0xd] = */ 0,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [0xe] = */ 0,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [CIDET_OF_Z_SPECIAL] = */ UINT16_MAX - 1,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync};
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/** Converts operand sizes in bytes to 64-bit masks. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic const uint64_t g_au64ByteSizeToMask[] =
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x0000000000000000),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x00000000000000ff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x000000000000ffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x0000000000ffffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x00000000ffffffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x000000ffffffffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x0000ffffffffffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0x00ffffffffffffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync UINT64_C(0xffffffffffffffff),
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync};
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
694eb5fb2b25736d37902333e059a149f78c563cvboxsync/** Converts operand sizes in bytes to 64-bit signed max values. */
694eb5fb2b25736d37902333e059a149f78c563cvboxsyncstatic const int64_t g_ai64ByteSizeToMax[] =
694eb5fb2b25736d37902333e059a149f78c563cvboxsync{
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x0000000000000000),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x000000000000007f),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x0000000000007fff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x00000000007fffff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x000000007fffffff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x0000007fffffffff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x00007fffffffffff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x007fffffffffffff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync INT64_C(0x7fffffffffffffff),
694eb5fb2b25736d37902333e059a149f78c563cvboxsync};
694eb5fb2b25736d37902333e059a149f78c563cvboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetInstrHasMrmMemOperand(PCCIDETINSTR pInstr)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return CIDET_INSTR_TEST_OP_FLAG(pInstr, CIDET_OF_M_RM_ONLY_M);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetInstrHasMrmRegOperand(PCCIDETINSTR pInstr)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return CIDET_INSTR_TEST_OP_FLAG(pInstr, CIDET_OF_M_RM_ONLY_R);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetInstrRespondsToOperandSizePrefixes(PCCIDETINSTR pInstr)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return CIDET_INSTR_TEST_OP_MASK_VALUE(pInstr, CIDET_OF_Z_MASK, CIDET_OF_Z_VAR_WDQ);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncint CidetCoreInit(PCIDETCORE pThis, RTRAND hRand)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertPtr(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertPtr(hRand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync RT_ZERO(*pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->u32Magic = CIDETCORE_MAGIC;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->hRand = hRand;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return VINF_SUCCESS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncvoid CidetCoreDelete(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertPtr(pThis); Assert(pThis->u32Magic == CIDETCORE_MAGIC);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync RTRandAdvDestroy(pThis->hRand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync RT_ZERO(*pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Report a test failure via CIDET::pfnFailure
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncint CidetCoreSetErrorV(PCIDETCORE pThis, const char *pszFormat, va_list va)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->pfnFailure(pThis, pszFormat, va);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Report a test failure via CIDET::pfnFailure
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetError(PCIDETCORE pThis, const char *pszFormat, ...)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync va_list va;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync va_start(va, pszFormat);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync CidetCoreSetErrorV(pThis, pszFormat, va);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync va_end(va);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Get a signed random number, with a given number of significant bytes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns Random number.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis Pointer to the core structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param cbSignificant The number of significant bytes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncint64_t CidetCoreGetRandS64(PCIDETCORE pThis, uint8_t cbSignificant)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync int64_t iVal = RTRandAdvS64(pThis->hRand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (cbSignificant)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1: return (int8_t)iVal;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2: return (int16_t)iVal;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 4: return (int32_t)iVal;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 8: return iVal;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailed();
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return iVal;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Get an unsigned random number, with a given number of significant bytes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns Random number.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis Pointer to the core structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param cbSignificant The number of significant bytes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncuint64_t CidetCoreGetRandU64(PCIDETCORE pThis, uint8_t cbSignificant)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(cbSignificant == 1 || cbSignificant == 2 || cbSignificant == 4 || cbSignificant == 8);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint64_t uVal = RTRandAdvU64(pThis->hRand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uVal &= g_au64ByteSizeToMask[cbSignificant];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return uVal;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncvoid CidetCoreInitializeCtxTemplate(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.rip = UINT64_MAX;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->InTemplateCtx.rfl = X86_EFL_1 | X86_EFL_ID | X86_EFL_IF;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync unsigned i = RT_ELEMENTS(pThis->InTemplateCtx.aGRegs);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CIDETMODE_IS_LM(pThis->bMode))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (i-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.aGRegs[i] = UINT64_C(0x3fefcc00daba005d)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync | ((uint64_t)i << 32)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync | ((uint32_t)i << 8);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (i-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.aGRegs[i] = UINT64_C(0xfada009b)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync | ((uint32_t)i << 12)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync | ((uint32_t)i << 8);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync i = RT_ELEMENTS(pThis->InTemplateCtx.aSRegs);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (i-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.aSRegs[i] = 0; /* Front end sets these afterwards. */
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync pThis->InTemplateCtx.cr2 = 0;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync#ifndef CIDET_REDUCED_CTX
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.tr = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.ldtr = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.cr0 = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.cr3 = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.cr4 = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.cr8 = 0;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync#endif
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.fIgnoredRFlags = 0;
305cd720ec3a20d3d646c145cb301cb6c1a385e8vboxsync pThis->InTemplateCtx.uXcpt = UINT32_MAX;
305cd720ec3a20d3d646c145cb301cb6c1a385e8vboxsync pThis->InTemplateCtx.uErr = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InTemplateCtx.fTrickyStack = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Sets the target mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Caller must set up default selector values after calling this function.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns VBox status code.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis Pointer to the core structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param bMode The new mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncint CidetCoreSetTargetMode(PCIDETCORE pThis, uint8_t bMode)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == CIDETCORE_MAGIC, VERR_INVALID_HANDLE);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (bMode)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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_32:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync //case CIDETMODE_PP_V86:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync //case CIDETMODE_PAE_16:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDETMODE_PAE_32:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync //case CIDETMODE_PAE_V86:
694eb5fb2b25736d37902333e059a149f78c563cvboxsync //case CIDETMODE_LM_S16:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync //case CIDETMODE_LM_32:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDETMODE_LM_64:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return VERR_NOT_IMPLEMENTED;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bMode = bMode;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync CidetCoreInitializeCtxTemplate(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return VINF_SUCCESS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreIsEncodingCompatibleWithInstruction(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next address size mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_AddressSize(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fAddrSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Reset to default.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbAddrMode = CIDETMODE_GET_BYTE_COUNT(pThis->bMode);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fAddrSizePrf = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * The other addressing size.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CIDETMODE_IS_64BIT(pThis->bMode))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbAddrMode = 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (CIDETMODE_IS_32BIT(pThis->bMode))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbAddrMode = 2;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(CIDETMODE_IS_16BIT(pThis->bMode));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbAddrMode = 2;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fAddrSizePrf = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return pThis->fAddrSizePrf;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync/**
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync * Selects the first REG encoding.
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync *
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync * @param pThis The core state structure.
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync */
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsyncstatic void cidetCoreSetupFirstBaseEncoding_MrmReg(PCIDETCORE pThis)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync{
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->aOperands[pThis->idxMrmRegOp].iReg = 0;
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;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->bModRm &= ~X86_MODRM_REG_MASK;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->fRexR = false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync}
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next REG (ModR/M) encoding.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmReg(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->idxMrmRegOp < RT_ELEMENTS(pThis->aOperands) && !pThis->aOperands[pThis->idxMrmRegOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(iReg < 16);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Clear the collision flags here because of the byte register kludge.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Clear the REX prefix and high byte register tracking too. ASSUMES MrmReg is after MrmRmMod.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fNoRexPrefixMrmRm);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasHighByteRegInMrmRm);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefixMrmReg = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefix = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasHighByteRegInMrmReg = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsHighByteRegister = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
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 */
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 if ( pThis->aOperands[pThis->idxMrmRegOp].cb == 1
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && iReg >= 3
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && ( iReg <= 6
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || (CIDETMODE_IS_64BIT(pThis->bMode) && iReg == 7 && !pThis->fRex)) )
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->fRex && iReg >= 4 && CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* The AMD64 low variants: spl, bpl, sil and dil. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRex = true;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync pThis->fHasStackRegInMrmReg = iReg == X86_GREG_xSP;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Check for collisions. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasHighByteRegInMrmRm);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->aOperands[pThis->idxMrmRmOp].fIsMem)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRmOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && iReg == pThis->aOperands[pThis->idxMrmRmOp].iReg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fUsesVexIndexRegs || pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg == UINT8_MAX);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Next register: ah, ch, dh and bh. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iReg++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRegOp].iReg = iReg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_REG_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= (iReg & X86_MODRM_REG_SMASK) << X86_MODRM_REG_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRex = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexR = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefixMrmReg = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefix = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasHighByteRegInMrmReg = true;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync pThis->fHasStackRegInMrmReg = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRegOp].fIsHighByteRegister = true;
305cd720ec3a20d3d646c145cb301cb6c1a385e8vboxsync Assert(!pThis->fRexW); Assert(!pThis->fRexX); Assert(!pThis->fRexB);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Check for collisions. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->aOperands[pThis->idxMrmRmOp].fIsMem)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRmOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && ( ( pThis->aOperands[pThis->idxMrmRmOp].cb == 1
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && iReg == pThis->aOperands[pThis->idxMrmRmOp].iReg
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && pThis->fHasHighByteRegInMrmRm)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || ( pThis->aOperands[pThis->idxMrmRmOp].cb > 1
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && iReg - 4 == pThis->aOperands[pThis->idxMrmRmOp].iReg));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fUsesVexIndexRegs || pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg == UINT8_MAX);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fRex || (iReg == 7 && CIDETMODE_IS_64BIT(pThis->bMode)));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRex = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Next register.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iReg = (iReg + 1) & (CIDETMODE_IS_64BIT(pThis->bMode) ? 15 : 7);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRegOp].iReg = iReg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_REG_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= (iReg & X86_MODRM_REG_SMASK) << X86_MODRM_REG_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexR = iReg >= 8;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync pThis->fHasStackRegInMrmReg = iReg == X86_GREG_xSP && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Register collision detection.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->aOperands[pThis->idxMrmRmOp].fIsMem)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = iReg == pThis->aOperands[pThis->idxMrmRmOp].iReg
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (CIDET_OF_K_IS_GPR(pThis->fMrmRegOp))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fSib);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return iReg != 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next MOD & R/M encoding, 16-bit addressing variant.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param iReg The value of MODRM.REG /w REX.R applied.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic void cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CidetInstrHasMrmRegOperand(pThis->pCurInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= 3 << X86_MODRM_MOD_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = iReg == 0
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(CidetInstrHasMrmMemOperand(pThis->pCurInstr));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync iReg -= pThis->fHasHighByteRegInMrmReg * 4;
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;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next MOD & R/M encoding, 16-bit addressing variant.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmRmMod_16bit(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(!pThis->fRexB);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(!pThis->fRexX);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t iRm = pThis->bModRm & X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t iMod = (pThis->bModRm >> X86_MODRM_MOD_SHIFT) & X86_MODRM_MOD_SMASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMod == 3)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Register access mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && !pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasMemoryOperand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasRegCollisionMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasRegCollisionMemBase);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasRegCollisionMemIndex);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iRm < 7)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iRm++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = iRm;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iRm;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = iRm == iReg
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* If no memory modes, we're done. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!CidetInstrHasMrmMemOperand(pThis->pCurInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(pThis, iReg);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Next mode: 16-bit memory addressing without displacement. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iMod = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Memory access mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->fHasMemoryOperand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iRm < 7)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iRm++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (iRm)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xDI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBP;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBP;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xDI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 4:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 5:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xDI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 6:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMod == 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 2;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBP;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 7:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMod == 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailed();
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iRm;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync if (CIDET_OF_K_IS_GPR(pThis->fMrmRegOp))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync iReg -= pThis->fHasHighByteRegInMrmReg * 4;
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Last mode? */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMod >= 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(pThis, iReg);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Next memory addressing mode (if any). */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iMod++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = X86_GREG_xBX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = X86_GREG_xSI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iMod << X86_MODRM_MOD_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CIDET_OF_K_IS_GPR(pThis->fMrmRmOp))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync iReg -= pThis->fHasHighByteRegInMrmReg * 4;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->fHasRegCollisionMemBase = iReg == X86_GREG_xBX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = iReg == X86_GREG_xSI;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the first MOD & R/M encoding, 32-bit and 64-bit addressing variant.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic void cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(PCIDETCORE pThis, uint8_t iReg, bool f64Bit)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CidetInstrHasMrmRegOperand(pThis->pCurInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= 3 << X86_MODRM_MOD_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = iReg == 0
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CIDET_OF_K_IS_SAME(pThis->fMrmRmOp, pThis->fMrmRegOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(CidetInstrHasMrmMemOperand(pThis->pCurInstr));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[pThis->idxMrmRmOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->fHasHighByteRegInMrmReg * 4 && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next MOD & R/M encoding, 32-bit and 64-bit addressing variant.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmRmMod_32bit64bit(PCIDETCORE pThis, uint8_t iReg, bool f64Bit)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
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 if (iMod == 3)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Register access mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && !pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasMemoryOperand);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasRegCollisionMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasRegCollisionMemBase);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->fHasRegCollisionMemIndex);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fRexX && !pThis->fNoRexPrefix) /* should be ignored. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Reset the byte register kludges variables. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasHighByteRegInMrmRm = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefixMrmRm = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefix = pThis->fNoRexPrefixMrmReg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iRm < (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix ? 15 : 7))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Byte register kludge.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ( pThis->aOperands[pThis->idxMrmRmOp].cb == 1
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && iRm >= 3
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && ( iRm <= 6
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || (iRm == 7 && CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fRexX) ) )
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->fRexX && iRm >= 4 && CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* The AMD64 low variants: spl, bpl, sil and dil. (Using fRexX here as REG covers fRex.) */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = true;
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Next register: ah, ch, dh and bh. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iRm++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = iRm;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iRm & X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
305cd720ec3a20d3d646c145cb301cb6c1a385e8vboxsync if (!pThis->fRexR && !pThis->fRexW && !pThis->fRex)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefixMrmRm = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fNoRexPrefix = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasHighByteRegInMrmRm = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsHighByteRegister = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = CIDET_OF_K_IS_GPR(pThis->fMrmRegOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && iRm - 4 == iReg - pThis->fHasHighByteRegInMrmReg * 4;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Normal register.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iRm++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iReg = iRm;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iRm & X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = iRm >= 8;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* If no memory modes, we're done. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!CidetInstrHasMrmMemOperand(pThis->pCurInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, f64Bit);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Next mode: 32-bit/64-bit memory addressing without displacement. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsMem = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iMod = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Memory access mode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->fHasMemoryOperand);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync Assert(!pThis->fHasStackRegInMrmRmBase);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iRm < (CIDETMODE_IS_64BIT(pThis->bMode) && !pThis->fNoRexPrefix ? 15 : 7))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iRm++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iRm == 12)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iRm++; /* Leave REX.B=1 to the next-sib-base function. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iRm == 4)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* SIB */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fSib = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if ((iRm & 7) == 5 && iMod == 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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].cbMemDisp = 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ((iRm & 7) == 6 && iMod == 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].fIsRipRelative = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = iRm;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iRm & X86_MODRM_RM_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = iRm >= 8;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync if (CIDET_OF_K_IS_GPR(pThis->fMrmRegOp))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync iReg -= pThis->fHasHighByteRegInMrmReg * 4;
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Last mode? */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMod >= 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, f64Bit);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Next memory addressing mode (if any). */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync iMod++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = iMod == 1 ? 1 : 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm &= ~(X86_MODRM_RM_MASK | X86_MODRM_MOD_MASK);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm |= iMod << X86_MODRM_MOD_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionDirect = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->fHasRegCollisionMemBase = iReg == pThis->fHasHighByteRegInMrmReg * 4
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync && CIDET_OF_K_IS_GPR(pThis->fMrmRmOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next MOD & R/M encoding.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_MrmRmMod(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->cbAddrMode == 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return cidetCoreSetupNextBaseEncoding_MrmRmMod_16bit(pThis, iReg);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->cbAddrMode == 4)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return cidetCoreSetupNextBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->cbAddrMode == 8)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return cidetCoreSetupNextBaseEncoding_MrmRmMod_32bit64bit(pThis, iReg, true);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next SIB base register (/ encoding).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SibBase(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(!pThis->fRexB || CIDETMODE_IS_64BIT(pThis->bMode));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ((iBase & 7) == 5 && (pThis->bModRm & X86_MODRM_MOD_MASK) == 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ((iBase & 7) == 6 && (pThis->bModRm & X86_MODRM_MOD_MASK) == 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg = iBase;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib &= ~X86_SIB_BASE_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib |= iBase & X86_SIB_BASE_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = iBase >= 8;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->fHasRegCollisionMemBase = pThis->aOperands[pThis->idxMrmRmOp].iMemBaseReg
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync == iReg - pThis->fHasHighByteRegInMrmReg * 4
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CIDET_OF_K_IS_GPR(pThis->fMrmRegOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = iBase == X86_GREG_xSP;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return iBase != 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next SIB index register (/ encoding).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SibIndex(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(!pThis->fRexX || CIDETMODE_IS_64BIT(pThis->bMode));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands) && pThis->aOperands[pThis->idxMrmRmOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iIndex == 4 && !pThis->fUsesVexIndexRegs)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg = iIndex;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib &= ~X86_SIB_INDEX_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib |= (iIndex & X86_SIB_INDEX_SMASK) << X86_SIB_INDEX_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = iIndex >= 8;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->fHasRegCollisionMemIndex = pThis->aOperands[pThis->idxMrmRmOp].iMemIndexReg
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync == iReg - pThis->fHasHighByteRegInMrmReg * 4
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && ( !pThis->fUsesVexIndexRegs
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ? CIDET_OF_K_IS_GPR(pThis->fMrmRegOp) : CIDET_OF_K_IS_VRX(pThis->fMrmRegOp) );
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = pThis->fHasRegCollisionMemBase || pThis->fHasRegCollisionMemIndex;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return iIndex != 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next SIB scale.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SibScale(PCIDETCORE pThis, uint8_t iReg)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch ((pThis->bSib >> X86_SIB_SCALE_SHIFT) & X86_SIB_SCALE_SMASK)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 0:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib |= 1 << X86_SIB_SCALE_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 2;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib &= ~X86_SIB_SCALE_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib |= 2 << X86_SIB_SCALE_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib |= 3 << X86_SIB_SCALE_SHIFT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 8;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib &= ~X86_SIB_SCALE_MASK;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[pThis->idxMrmRmOp].uMemScale = 1;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next segment prefix.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_SegmentPrefix(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ( pThis->fHasMemoryOperand
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_MASK))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->uSegPrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_COUNT:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_ES;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_ES)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* fall thru */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_ES:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_CS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_CS)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* fall thru */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_CS:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_SS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_SS)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* fall thru */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_SS:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_DS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_DS)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* fall thru */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_DS:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_FS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_FS)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* fall thru */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_FS:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_GS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fTestCfg & CIDET_TESTCFG_SEG_PRF_GS)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* fall thru */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case X86_SREG_GS:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailedBreak();
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_COUNT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Updates the variable sized operands.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic void cidetCoreUpdateOperandSizes(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t iOp = pThis->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (iOp-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].cb = (uint8_t)CidetCoreGetOperandSize(pThis, iOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Selects the next operand size.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns @c true if done, @c false if the next wheel needs to be moved.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic bool cidetCoreSetupNextBaseEncoding_OperandSize(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CidetInstrRespondsToOperandSizePrefixes(pThis->pCurInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CIDETMODE_IS_64BIT(pThis->bMode))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->fOpSizePrf + pThis->fRexW * 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 0:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fOpSizePrf = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreUpdateOperandSizes(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fOpSizePrf = false;
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync if (pThis->fNoRexPrefix)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexW = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreUpdateOperandSizes(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fOpSizePrf = true; /* check that it's ignored. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreUpdateOperandSizes(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailed();
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->fOpSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fOpSizePrf = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreUpdateOperandSizes(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexW = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fOpSizePrf = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreUpdateOperandSizes(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupNextBaseEncoding(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fUsesModRm)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (cidetCoreSetupNextBaseEncoding_OperandSize(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (cidetCoreSetupNextBaseEncoding_SegmentPrefix(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fSib)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(pThis->fHasMemoryOperand);
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 Assert(pThis->bSib == 0);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fSib = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupFirstBaseEncoding(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Reset all the knobs and wheels.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fSib = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->uSegPrf = X86_SREG_COUNT;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fAddrSizePrf = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fOpSizePrf = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexW = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexR = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexX = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRexB = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fRex = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bModRm = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->bSib = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Indicators. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbAddrMode = CIDETMODE_GET_BYTE_COUNT(pThis->bMode);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasMemoryOperand = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fHasRegCollisionMemIndex = false;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->fHasStackRegInMrmRmBase = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Now, drill down on the instruction encoding.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->pCurInstr->fFlags & CIDET_IF_MODRM)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->fUsesModRm == true);
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync cidetCoreSetupFirstBaseEncoding_MrmReg(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->cbAddrMode == 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_16bit(pThis, 0);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (pThis->cbAddrMode == 4)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, 0, false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (pThis->cbAddrMode == 8)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreSetupFirstBaseEncoding_MrmRmMod_32bit64bit(pThis, 0, true);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * The next memory operand configuration.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns true if new one to test, false if we've reached end already.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupNextMemoryOperandConfig(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Sets up the first memory operand configuration and counts memory operands.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns true on success, false if no data buffers configured or failure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupFirstMemoryOperandConfig(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cMemoryOperands = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync PCIDETBUF pDataBuf = &pThis->DataBuf;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t idxOp = pThis->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (idxOp-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->aOperands[idxOp].fIsMem)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].pDataBuf = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (RT_UNLIKELY(!pThis->cDataBufConfigs))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->idxCfg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->pCfg = &pThis->paDataBufConfigs[0];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->off = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->cb = pThis->aOperands[idxOp].cb;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->cbSegLimit = UINT16_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->offSegBase = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->fActive = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->idxOp = idxOp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->fXcptAfterInstruction = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->enmExpectXcpt = kCidetExpectXcpt_None;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].pDataBuf = pDataBuf;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cMemoryOperands++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo implement more than one memory operand. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseReturn(pThis->cMemoryOperands <= 1, false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * The next code buffer configuration.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns true if new one to test, false if we've reached end already.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupNextCodeBufferConfig(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Sets up the first code buffer configuration.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns true on success, false if no data buffers configured or failure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupFirstCodeBufferConfig(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->cCodeBufConfigs > 0);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(CIDETBUF_IS_CODE(pThis->paCodeBufConfigs[0].fFlags));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.idxCfg = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.pCfg = &pThis->paCodeBufConfigs[0];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.off = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.cb = 0x1000;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.cbSegLimit = UINT16_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.offSegBase = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.fActive = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.idxOp = 7;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.fXcptAfterInstruction = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.enmExpectXcpt = kCidetExpectXcpt_None;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Gets the (encoded) size of the given operand in the current context.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns Size in bytes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure (for context).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param iOp The operand index.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncuint32_t CidetCoreGetOperandSize(PCIDETCORE pThis, uint8_t iOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(iOp < RT_ELEMENTS(pThis->aOperands));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint32_t cbOp = g_acbCidetOfSizes[(pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) >> CIDET_OF_Z_SHIFT];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (cbOp == UINT16_MAX)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_VAR_WDQ);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CIDETMODE_IS_64BIT(pThis->bMode))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fRexW)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cbOp = 8;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (!pThis->fOpSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cbOp = 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cbOp = 2;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (CIDETMODE_IS_32BIT(pThis->bMode))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cbOp = !pThis->fOpSizePrf ? 4 : 2;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(CIDETMODE_IS_16BIT(pThis->bMode));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cbOp = !pThis->fOpSizePrf ? 2 : 4;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return cbOp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (cbOp == UINT16_MAX - 1)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert((pThis->aOperands[iOp].fFlags & CIDET_OF_Z_MASK) == CIDET_OF_Z_SPECIAL);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(0);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (cbOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync#ifdef VBOX_STRICT
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (cbOp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertFailed();
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync#endif
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return cbOp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(0);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CideCoreSetInstruction(PCIDETCORE pThis, PCCIDETINSTR pInstr)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseMsgReturn(RT_VALID_PTR(pInstr), ("%p\n", pInstr), false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->pCurInstr = pInstr;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Extract info from the instruction descriptor.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fUsesModRm = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fUsesVexIndexRegs = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->idxMrmRegOp = 7;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->idxMrmRmOp = 7;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fMrmRegOp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fMrmRmOp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fInstrFlags = pInstr->fFlags;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cOperands = pInstr->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pInstr->fFlags & CIDET_IF_MODRM)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fUsesModRm = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync for (uint8_t iOp = 0; iOp < pInstr->cOperands; iOp++)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pInstr->afOperands[iOp] & CIDET_OF_M_REG)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->idxMrmRegOp = iOp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fMrmRegOp = pInstr->afOperands[iOp];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (pInstr->afOperands[iOp] & CIDET_OF_M_RM)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->idxMrmRmOp = iOp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->fMrmRmOp = pInstr->afOperands[iOp];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t iOp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync for (iOp = 0; iOp < pInstr->cOperands; iOp++)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].fFlags = pInstr->afOperands[iOp];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iReg = UINT8_MAX;
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].fIsRipRelative = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uMemScale = 1;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].offSeg = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uEffAddr = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uImmDispValue = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uMemBaseRegValue = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uMemIndexRegValue = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].In.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].Expected.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].pDataBuf = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync for (; iOp < RT_ELEMENTS(pThis->aOperands); iOp++)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].fFlags = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].cb = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].fIsImmediate = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].fIsMem = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].fIsRipRelative = false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].cbMemDisp = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iMemBaseReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iMemIndexReg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uMemScale = 1;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].offSeg = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uEffAddr = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uImmDispValue = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uMemBaseRegValue = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].uMemIndexRegValue = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].In.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].Expected.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[iOp].pDataBuf = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Reset various things.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
ff454903834d245c742b066ebca74bdeac46d0f4vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aiInOut); i++)
ff454903834d245c742b066ebca74bdeac46d0f4vboxsync pThis->aiInOut[i] = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupInOut(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Enumerate the operands.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t *pbBuf = &pThis->abBuf[0];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pbBuf = RT_ALIGN_PT(pbBuf, 16, uint8_t *);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t idxOp = pThis->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (idxOp-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->aOperands[idxOp].fIsMem)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Memory operand.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->aOperands[idxOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Set the In & Expected members to point to temporary buffer space. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].Expected.pu8 = pbBuf;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pbBuf += pThis->aOperands[idxOp].cb;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pbBuf = RT_ALIGN_PT(pbBuf, 16, uint8_t *);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].In.pu8 = pbBuf;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pbBuf += pThis->aOperands[idxOp].cb;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pbBuf = RT_ALIGN_PT(pbBuf, 16, uint8_t *);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* Initialize the buffer we're gonna use. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].iEffSeg = pThis->uSegPrf != X86_SREG_COUNT
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ? pThis->uSegPrf
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : !(pThis->aOperands[idxOp].fFlags & CIDET_OF_ALWAYS_SEG_ES) ? X86_SREG_DS
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : X86_SREG_ES;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync PCIDETBUF pDataBuf = pThis->aOperands[idxOp].pDataBuf;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseReturn(pDataBuf, false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pDataBuf->cb == pThis->aOperands[idxOp].cb);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pDataBuf->idxOp == idxOp);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->pfnReInitDataBuf(pThis, pDataBuf))
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedReInitDataBuf++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDataBuf->fActive = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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 pThis->aOperands[idxOp].offSeg = offSeg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease(offSeg <= g_au64ByteSizeToMask[pThis->cbAddrMode]);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Select register and displacement values for the buffer addressing (works on offSeg).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t const iMemIndexReg = pThis->aOperands[idxOp].iMemIndexReg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t const iMemBaseReg = pThis->aOperands[idxOp].iMemBaseReg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->aOperands[idxOp].fIsRipRelative)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* rip relative. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uImmDispValue = offSeg - (pThis->InCtx.rip + pThis->cbInstr);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->aOperands[idxOp].cbMemDisp == 4);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ( (int64_t)pThis->aOperands[idxOp].uImmDispValue > INT32_MAX
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || (int64_t)pThis->aOperands[idxOp].uImmDispValue < INT32_MIN)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedDataBufWrtRip++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (iMemBaseReg != UINT8_MAX)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if ( iMemBaseReg != iMemIndexReg
694eb5fb2b25736d37902333e059a149f78c563cvboxsync || pThis->fUsesVexIndexRegs)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync /* [base] or [base + disp] or [base + index * scale] or [base + index * scale + disp] */
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if (pThis->aOperands[idxOp].cbMemDisp > 0)
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[idxOp].uImmDispValue = CidetCoreGetRandS64(pThis, pThis->aOperands[idxOp].cbMemDisp);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg -= (int64_t)pThis->aOperands[idxOp].uImmDispValue;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if (iMemIndexReg != UINT8_MAX)
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[idxOp].uMemIndexRegValue = CidetCoreGetRandU64(pThis, pThis->cbAddrMode);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg -= pThis->aOperands[idxOp].uMemIndexRegValue * pThis->aOperands[idxOp].uMemScale;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[idxOp].uMemBaseRegValue = offSeg & g_au64ByteSizeToMask[pThis->cbAddrMode];
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync /* base == index; [base + index * scale] or [base * (scale + 1)]. */
694eb5fb2b25736d37902333e059a149f78c563cvboxsync uint8_t const uEffScale = pThis->aOperands[idxOp].uMemScale + 1;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if (pThis->aOperands[idxOp].cbMemDisp > 0)
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[idxOp].uImmDispValue = CidetCoreGetRandS64(pThis, pThis->aOperands[idxOp].cbMemDisp);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg -= (int64_t)pThis->aOperands[idxOp].uImmDispValue;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg &= g_au64ByteSizeToMask[pThis->cbAddrMode];
694eb5fb2b25736d37902333e059a149f78c563cvboxsync uint8_t uRemainder = offSeg % uEffScale;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if (uRemainder != 0)
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync Assert(pThis->aOperands[idxOp].cbMemDisp < 8);
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 + uRemainder;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg -= uRemainder;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if ( (int64_t)pThis->aOperands[idxOp].uImmDispValue
694eb5fb2b25736d37902333e059a149f78c563cvboxsync > g_ai64ByteSizeToMax[pThis->aOperands[idxOp].cbMemDisp])
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[idxOp].uImmDispValue -= uEffScale;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg += uEffScale;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync Assert(offSeg % uEffScale == 0);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync else
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg &= g_au64ByteSizeToMask[pThis->cbAddrMode];
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if (offSeg % uEffScale != 0)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSameBaseIndexRemainder++;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync offSeg /= uEffScale;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->aOperands[idxOp].uMemBaseRegValue = pThis->aOperands[idxOp].uMemIndexRegValue = offSeg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (iMemIndexReg != UINT8_MAX)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [index * scale] or [index * scale + disp] */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->aOperands[idxOp].cbMemDisp > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (offSeg & (RT_BIT_64(pThis->aOperands[idxOp].uMemScale) - 1))
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedOnlyIndexRemainder++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /* [disp] */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert( pThis->aOperands[idxOp].cbMemDisp == 8
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || pThis->aOperands[idxOp].cbMemDisp == 4
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || pThis->aOperands[idxOp].cbMemDisp == 2
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync || pThis->aOperands[idxOp].cbMemDisp == 1);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ( pThis->aOperands[idxOp].cbMemDisp == 4
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ? (int64_t)offSeg != (int32_t)offSeg
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : pThis->aOperands[idxOp].cbMemDisp == 2
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ? (int64_t)offSeg != (int16_t)offSeg
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : pThis->aOperands[idxOp].cbMemDisp == 1
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ? (int64_t)offSeg != (int8_t)offSeg
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : false /* 8 */)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedDirectAddressingOverflow++;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uImmDispValue = offSeg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
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 */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMemBaseReg != UINT8_MAX)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
9f4f6a59c4f15adc4398bdfbf271ffd2ef521085vboxsync if (pThis->cbAddrMode == 4)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemBaseRegValue &= UINT32_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemBaseRegValue |= pThis->InCtx.aGRegs[iMemBaseReg] & UINT64_C(0xffffffff00000000);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
9f4f6a59c4f15adc4398bdfbf271ffd2ef521085vboxsync else if (pThis->cbAddrMode == 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemBaseRegValue &= UINT16_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemBaseRegValue |= pThis->InCtx.aGRegs[iMemBaseReg] & UINT64_C(0xffffffffffff0000);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InCtx.aGRegs[iMemBaseReg] = pThis->aOperands[idxOp].uMemBaseRegValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->ExpectedCtx.aGRegs[iMemBaseReg] = pThis->aOperands[idxOp].uMemBaseRegValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (iMemIndexReg != UINT8_MAX)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
9f4f6a59c4f15adc4398bdfbf271ffd2ef521085vboxsync if (pThis->cbAddrMode == 4)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemIndexRegValue &= UINT32_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemIndexRegValue |= pThis->InCtx.aGRegs[iMemIndexReg] & UINT64_C(0xffffffff00000000);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
9f4f6a59c4f15adc4398bdfbf271ffd2ef521085vboxsync else if (pThis->cbAddrMode == 2)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemIndexRegValue &= UINT16_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uMemIndexRegValue |= pThis->InCtx.aGRegs[iMemIndexReg] & UINT64_C(0xffffffffffff0000);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InCtx.aGRegs[iMemIndexReg] = pThis->aOperands[idxOp].uMemIndexRegValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->ExpectedCtx.aGRegs[iMemIndexReg] = pThis->aOperands[idxOp].uMemIndexRegValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Non-memory, so clear the memory related members.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(!pThis->aOperands[idxOp].fIsMem);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].iEffSeg = UINT8_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].offSeg = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].uEffAddr = UINT64_MAX;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].pDataBuf = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->aOperands[idxOp].fFlags & CIDET_OF_K_MASK)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_GPR:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->aOperands[idxOp].fIsHighByteRegister)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 }
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync else
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->aOperands[idxOp].In.pv = &pThis->InCtx.aGRegs[pThis->aOperands[idxOp].iReg - 4];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].In.pu8++;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->aOperands[idxOp].Expected.pv = &pThis->ExpectedCtx.aGRegs[pThis->aOperands[idxOp].iReg - 4];
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].Expected.pu8++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_IMM:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].In.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].Expected.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_SREG:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->aOperands[idxOp].iReg < RT_ELEMENTS(pThis->InCtx.aSRegs))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].In.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->aOperands[idxOp].Expected.pv = NULL;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_CR:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_SSE:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_AVX:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_AVX512:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_FPU:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_MMX:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_AVXFUTURE:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_SPECIAL:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_TEST:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo Implement testing these registers. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case CIDET_OF_K_NONE:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertRelease((uintptr_t)pbBuf - (uintptr_t)&pThis->abBuf[0] <= sizeof(pThis->abBuf));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Call instruction specific setup function (for operand values and flags).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync int rc = pThis->pCurInstr->pfnSetupInOut(pThis, false /*fInvalid*/);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (RT_FAILURE(rc))
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSetupInOut++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Do the 2nd set of the memory operand preparations.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fHasMemoryOperand)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync idxOp = pThis->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (idxOp-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->aOperands[idxOp].fIsMem)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(pThis->aOperands[idxOp].pDataBuf);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!pThis->pfnSetupDataBuf(pThis, pThis->aOperands[idxOp].pDataBuf, pThis->aOperands[idxOp].In.pv))
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync {
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSetupDataBuf++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync }
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
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->fUsesVexIndexRegs
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync ? pThis->InCtx.aGRegs[pThis->aOperands[idxOp].iMemIndexReg]
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync == pThis->aOperands[idxOp].uMemIndexRegValue
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : false /** @todo VEX indexing */));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Figures the instruction length.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * This is a duplicate of CidetCoreAssemble() with the buffer updates removed.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns true and pThis->cbInstr on success, false on failure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure (for context).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreAssembleLength(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t off = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Prefixes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (1)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fAddrSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fOpSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo prefix list. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Prefixes that must come right before the opcode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo VEX and EVEX. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fVex)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo VEX and EVEX. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (pThis->fEvex)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo VEX and EVEX. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fRexB || pThis->fRexX || pThis->fRexR || pThis->fRexW || pThis->fRex)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * The opcode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t const *pbOpcode = pThis->pCurInstr->abOpcode;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->pCurInstr->cbOpcode)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3: off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2: off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1: off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Mod R/M
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fUsesModRm)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fSib)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint64_t uDispValue = pThis->aOperands[pThis->idxMrmRmOp].uImmDispValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 0: break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 8:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 7:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 6:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 5:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 4:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off += pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Immediates.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t iOp = pThis->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (iOp-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ((pThis->aOperands[iOp].fFlags & CIDET_OF_K_MASK) == CIDET_OF_K_IMM)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint64_t uImmValue = pThis->aOperands[iOp].uImmDispValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->aOperands[iOp].cb)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 8:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 7:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 6:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 5:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 4:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off += pThis->aOperands[iOp].cb;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbInstr = off;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Assembles the instruction.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * This is a duplicate of CidetCoreAssembleLength() with buffer writes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync *
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @returns true and pThis->cbInstr and pThis->abInstr on success, false on
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * failure.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @param pThis The core state structure (for context).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreAssemble(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t off = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Prefixes.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (1)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fAddrSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->abInstr[off++] = 0x67;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fOpSizePrf)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->abInstr[off++] = 0x66;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo prefix list. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Prefixes that must come right before the opcode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo VEX and EVEX. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fVex)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo VEX and EVEX. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else if (pThis->fEvex)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /** @todo VEX and EVEX. */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * The opcode.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t const *pbOpcode = pThis->pCurInstr->abOpcode;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->pCurInstr->cbOpcode)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 3: pThis->abInstr[off++] = *pbOpcode++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 2: pThis->abInstr[off++] = *pbOpcode++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync case 1: pThis->abInstr[off++] = *pbOpcode++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default:
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Mod R/M
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fUsesModRm)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->abInstr[off++] = pThis->bModRm;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->fSib)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->abInstr[off++] = pThis->bSib;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->idxMrmRmOp < RT_ELEMENTS(pThis->aOperands))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint64_t uDispValue = pThis->aOperands[pThis->idxMrmRmOp].uImmDispValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off += pThis->aOperands[pThis->idxMrmRmOp].cbMemDisp;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Immediates.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint8_t iOp = pThis->cOperands;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync while (iOp-- > 0)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ((pThis->aOperands[iOp].fFlags & CIDET_OF_K_MASK) == CIDET_OF_K_IMM)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint64_t uImmValue = pThis->aOperands[iOp].uImmDispValue;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync switch (pThis->aOperands[iOp].cb)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
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 break;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync default: AssertReleaseFailedReturn(false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync off += pThis->aOperands[iOp].cb;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->cbInstr = off;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreReInitCodeBuf(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Re-initialize the buffer. Requires instruction length and positioning.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CidetCoreAssembleLength(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.cb = pThis->cbInstr;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.off = CIDET_CODE_BUF_SIZE - PAGE_SIZE - pThis->cbInstr;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->pfnReInitCodeBuf(pThis, &pThis->CodeBuf))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->CodeBuf.fActive = true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Update the RIP and CS values in the input and expected contexts.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
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 if (pThis->CodeBuf.uSeg != UINT32_MAX)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InCtx.aSRegs[X86_SREG_CS] = pThis->CodeBuf.uSeg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->ExpectedCtx.aSRegs[X86_SREG_CS] = pThis->CodeBuf.uSeg;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync else
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedReInitCodeBuf++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync else
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedAssemble++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#ifdef CIDET_DEBUG_DISAS
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync/**
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * @callback_method_impl{FNDISREADBYTES}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncstatic DECLCALLBACK(int) cidetCoreDisReadBytes(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync PCIDETCORE pThis = (PCIDETCORE)pDis->pvUser;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync memcpy(&pDis->abInstr[offInstr], &pThis->abInstr[offInstr], cbMaxRead);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pDis->cbCachedInstr = offInstr + cbMaxRead;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return VINF_SUCCESS;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
4871617acc3a7a0e0e51ac2eeaa6c8e96720b012vboxsync#endif
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreSetupCodeBuf(PCIDETCORE pThis, unsigned iSubTest)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CidetCoreAssemble(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync //CIDET_DPRINTF(("%04u: %.*Rhxs\n", i, pThis->cbInstr, pThis->abInstr));
694eb5fb2b25736d37902333e059a149f78c563cvboxsync#ifdef CIDET_DEBUG_DISAS
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync DISCPUSTATE Dis;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync char szInstr[80] = {0};
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync uint32_t cbInstr;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync int rcDis = DISInstrToStrEx(pThis->InCtx.rip,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync CIDETMODE_IS_64BIT(pThis->bMode) ? DISCPUMODE_64BIT
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync : CIDETMODE_IS_32BIT(pThis->bMode) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cidetCoreDisReadBytes,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync DISOPTYPE_ALL,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync &Dis,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync &cbInstr,
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync szInstr, sizeof(szInstr));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync CIDET_DPRINTF(("%04u: %s", iSubTest, szInstr));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync Assert(cbInstr == pThis->cbInstr);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync#endif
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (pThis->pfnSetupCodeBuf(pThis, &pThis->CodeBuf, pThis->abInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSetupCodeBuf++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync else
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedAssemble++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return false;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync/**
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync * Compares the output with the output expectations.
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync *
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync * @returns true if ok, false if not (calls pfnFailure too).
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync * @param pThis The core state structure.
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync */
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsyncbool CidetCoreCheckResults(PCIDETCORE pThis)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync{
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync if (memcmp(&pThis->ActualCtx, &pThis->ExpectedCtx, CIDETCPUCTX_COMPARE_SIZE) == 0)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync return true;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
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 { \
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync CidetCoreSetError(pThis, #a_Field " differs: got %#llx expected %#llx", \
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->ActualCtx.a_Field, pThis->ExpectedCtx.a_Field); \
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync cDiffs++; \
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync } else do { } while (0)
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(rip, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(rfl, "%#010llx");
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");
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync IF_FIELD_DIFFERS_SET_ERROR(uXcpt, "%#04x");
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync IF_FIELD_DIFFERS_SET_ERROR(uErr, "%#04llx");
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync IF_FIELD_DIFFERS_SET_ERROR(cr2, "%#010llx");
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync#ifndef CIDET_REDUCED_CTX
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(tr, "%#06x");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(ldtr, "%#06x");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(cr0, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(cr3, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(cr4, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(cr8, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(dr0, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(dr1, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(dr2, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(dr3, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(dr6, "%#010llx");
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync IF_FIELD_DIFFERS_SET_ERROR(dr7, "%#010llx");
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsync#endif
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
fdf66bdf7b03d58ec33dbc065f2d28e1f7d4986avboxsyncAssertMsgFailed(("cDiffs=%d\n", cDiffs));
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync Assert(cDiffs > 0);
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync return cDiffs == 0;
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync}
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreTest_Basic(PCIDETCORE pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Iterate all encodings.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!CidetCoreSetupFirstBaseEncoding(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return CidetCoreSetError(pThis, "CidetCoreSetupFirstBaseEncoding failed");
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync unsigned cExecuted = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync unsigned cSkipped = 0;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync do
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Iterate data buffer configurations (one iteration if none).
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (CidetCoreSetupFirstMemoryOperandConfig(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync do
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Iterate code buffer configurations.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!CidetCoreSetupFirstCodeBufferConfig(pThis))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return CidetCoreSetError(pThis, "CidetCoreSetupFirstMemoryOperandConfig failed");
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync do
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync /*
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync * Set up inputs and expected outputs, then emit the test code.
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync */
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync pThis->InCtx = pThis->InTemplateCtx;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->InCtx.fTrickyStack = pThis->fHasStackRegInMrmRmBase || pThis->fHasStackRegInMrmReg;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync pThis->ExpectedCtx = pThis->InCtx;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if ( CidetCoreReInitCodeBuf(pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CidetCoreSetupInOut(pThis)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync && CidetCoreSetupCodeBuf(pThis, cSkipped + cExecuted)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync )
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync if (pThis->pfnExecute(pThis))
694eb5fb2b25736d37902333e059a149f78c563cvboxsync {
694eb5fb2b25736d37902333e059a149f78c563cvboxsync cExecuted++;
694eb5fb2b25736d37902333e059a149f78c563cvboxsync
694eb5fb2b25736d37902333e059a149f78c563cvboxsync /*
694eb5fb2b25736d37902333e059a149f78c563cvboxsync * Check the result against our expectations.
694eb5fb2b25736d37902333e059a149f78c563cvboxsync */
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync CidetCoreCheckResults(pThis);
694eb5fb2b25736d37902333e059a149f78c563cvboxsync /** @todo check result. */
694eb5fb2b25736d37902333e059a149f78c563cvboxsync
694eb5fb2b25736d37902333e059a149f78c563cvboxsync }
694eb5fb2b25736d37902333e059a149f78c563cvboxsync else
694eb5fb2b25736d37902333e059a149f78c563cvboxsync cSkipped++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cSkipped++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync } while (CidetCoreSetupNextCodeBufferConfig(pThis));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync } while (CidetCoreSetupNextMemoryOperandConfig(pThis));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync }
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync else
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync cSkipped++;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync } while (CidetCoreSetupNextBaseEncoding(pThis));
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync
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"
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync ,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync cExecuted, cSkipped,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSetupInOut,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedReInitDataBuf,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSetupDataBuf,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedDataBufWrtRip,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedAssemble,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedReInitCodeBuf,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSetupCodeBuf,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedSameBaseIndexRemainder,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedOnlyIndexRemainder,
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync pThis->cSkippedDirectAddressingOverflow
c7522a3707ee4cc598fcb8d20bf679649dba09b3vboxsync ));
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return true;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsyncbool CidetCoreTestInstruction(PCIDETCORE pThis, PCCIDETINSTR pInstr)
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync{
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseMsgReturn(RT_VALID_PTR(pThis), ("%p\n", pThis), false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseReturn(pThis->u32Magic == CIDETCORE_MAGIC, false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync AssertReleaseReturn(pThis->cCodeBufConfigs > 0, false);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync if (!CideCoreSetInstruction(pThis, pInstr))
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return CidetCoreSetError(pThis, "CideCoreSetInstruction failed");
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync bool fResult = CidetCoreTest_Basic(pThis);
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync return fResult;
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync}
3bc264992af3416ecba168e6ffae1a334fe79088vboxsync