DisasmCore.cpp revision c5d43ad1264c4b88b4316c42d2abcd16e039d972
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/** @file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * VBox disassembler:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Core components
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright (C) 2006-2007 Sun Microsystems, Inc.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This file is part of VirtualBox Open Source Edition (OSE), as
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China * available from http://www.virtualbox.org. This file is free software;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * you can redistribute it and/or modify it under the terms of the GNU
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * General Public License (GPL) as published by the Free Software
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Foundation, in version 2 as it comes in the "COPYING" file of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Clara, CA 95054 USA or visit http://www.sun.com if you need
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China * additional information or have any questions.
a79493184c9332129c9c91500069322f6f3fafddReed */
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte* Header Files *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#define LOG_GROUP LOG_GROUP_DIS
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifdef USING_VISUAL_STUDIO
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# include <stdafx.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/dis.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/disopcode.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/cpum.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/err.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <VBox/log.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <iprt/assert.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <iprt/string.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <iprt/stdarg.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "DisasmInternal.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "DisasmTables.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# include <stdlib.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# include <stdio.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte* Internal Functions *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void disasmAddString(char *psz, const char *pszString);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void disasmAddStringF(char *psz, uint32_t cbString, const char *pszFormat, ...);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void disasmAddChar(char *psz, char ch);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# define disasmAddString(psz, pszString) do {} while (0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# ifdef _MSC_VER
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# define disasmAddStringF __noop
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# define disasmAddStringF(psz, cbString, pszFormat...) do {} while (0) /* Arg wanna get rid of that warning */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte# define disasmAddChar(psz, ch) do {} while (0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic unsigned QueryModRM(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic unsigned QueryModRM_SizeOnly(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void UseSIB(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic unsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte* Global Variables *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn FortePFNDISPARSE pfnFullDisasm[IDX_ParseMax] =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseIllegal,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseModRM,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte UseModRM,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmByte,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmBRel,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmUshort,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmV,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmVRel,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmAddr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseFixedReg,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmUlong,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmQword,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseTwoByteEsc,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmGrpl,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseShiftGrp2,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp3,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp4,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp5,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Parse3DNow,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp6,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp7,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp8,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp9,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp10,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp12,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp13,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp14,
a79493184c9332129c9c91500069322f6f3fafddReed ParseGrp15,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp16,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseModFence,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseYv,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseYb,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseXv,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseXb,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseEscFP,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseNopPause,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmByteSX,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmZ
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn FortePFNDISPARSE pfnCalcSize[IDX_ParseMax] =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseIllegal,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseModRM_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte UseModRM,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmByte_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmBRel_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmUshort_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmV_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmVRel_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmAddr_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseFixedReg,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmUlong_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmQword_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseTwoByteEsc,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmGrpl,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseShiftGrp2,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp3,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp4,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp5,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Parse3DNow,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp6,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp7,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp8,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp9,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp10,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp12,
a79493184c9332129c9c91500069322f6f3fafddReed ParseGrp13,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp14,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp15,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseGrp16,
a79493184c9332129c9c91500069322f6f3fafddReed ParseModFence,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseYv,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseYb,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseXv,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseXb,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseEscFP,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseNopPause,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmByteSX_SizeOnly,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ParseImmZ_SizeOnly
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Parses one instruction.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The result is found in pCpu.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns Success indicator.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pCpu Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param InstructionAddr Pointer to the instruction to parse.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pcbInstruction Where to store the size of the instruction.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * NULL is allowed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
a79493184c9332129c9c91500069322f6f3fafddReedDISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Reset instruction settings
a79493184c9332129c9c91500069322f6f3fafddReed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix = PREFIX_NONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix_seg = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->lastprefix = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->ModRM.u = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.u = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.parval = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.parval = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.parval = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.szParam[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.szParam[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.szParam[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnReadBytes = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->uFilter = OPTYPE_ALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnDisasmFnTable = pfnFullDisasm;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VBOX_SUCCESS(disCoreOne(pCpu, InstructionAddr, pcbInstruction));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Parses one guest instruction.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The result is found in pCpu and pcbInstruction.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns VBox status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param InstructionAddr Address of the instruction to decode. What this means
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is left to the pfnReadBytes function.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param enmCpuMode The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pfnReadBytes Callback for reading instruction bytes.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pvUser User argument for the instruction reader. (Ends up in apvUserData[0].)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pCpu Pointer to cpu structure. Will be initialized.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pcbInstruction Where to store the size of the instruction.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * NULL is allowed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteDISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte PDISCPUSTATE pCpu, unsigned *pcbInstruction)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Reset instruction settings
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix = PREFIX_NONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix_seg = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->lastprefix = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->mode = enmCpuMode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->ModRM.u = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.u = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.parval = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.parval = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.parval = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.szParam[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.szParam[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.szParam[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.size = 0;
a79493184c9332129c9c91500069322f6f3fafddReed pCpu->param2.size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnReadBytes = pfnReadBytes;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->apvUserData[0] = pvUser;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->uFilter = OPTYPE_ALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnDisasmFnTable = pfnFullDisasm;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return disCoreOne(pCpu, InstructionAddr, pcbInstruction);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/**
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Internal worker for DISCoreOne and DISCoreOneEx.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @returns VBox status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pCpu Initialized cpu state.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param InstructionAddr Instruction address.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pcbInstruction Where to store the instruction size. Can be NULL.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const OPCODE *paOneByteMap;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Parse byte by byte.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned iByte = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned cbInc;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_64BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte paOneByteMap = g_aOneByteMapX64;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->addrmode = CPUMODE_64BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opmode = CPUMODE_32BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte paOneByteMap = g_aOneByteMapX86;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->addrmode = pCpu->mode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opmode = pCpu->mode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while(1)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t codebyte = DISReadByte(pCpu, InstructionAddr+iByte);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t opcode = paOneByteMap[codebyte].opcode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Hardcoded assumption about OP_* values!! */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (opcode <= OP_LAST_PREFIX)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (opcode != OP_REX)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->lastprefix = opcode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix &= ~PREFIX_REX;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (opcode)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_INVALID:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte AssertMsgFailed(("Invalid opcode!!\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VERR_GENERAL_FAILURE; /** @todo better error code. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // segment override prefix byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_SEG:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix_seg = paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( pCpu->mode != CPUMODE_64BIT
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte || pCpu->prefix_seg >= OP_PARM_REG_FS)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_SEG;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // lock prefix byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_LOCK:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_LOCK;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // address size override prefix byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_ADDRSIZE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_ADDRSIZE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_16BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->addrmode = CPUMODE_32BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_32BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->addrmode = CPUMODE_16BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t);
a79493184c9332129c9c91500069322f6f3fafddReed continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // operand size override prefix byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_OPSIZE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_OPSIZE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_16BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opmode = CPUMODE_32BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
a79493184c9332129c9c91500069322f6f3fafddReed iByte += sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
a79493184c9332129c9c91500069322f6f3fafddReed // rep and repne are not really prefixes, but we'll treat them as such
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_REPE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_REP;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_REPNE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_REPNE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_REX:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Assert(pCpu->mode == CPUMODE_64BIT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* REX prefix byte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix |= PREFIX_REX;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte continue; //fetch the next byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned uIdx = iByte;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += sizeof(uint8_t); //first opcode byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opaddr = InstructionAddr + uIdx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opcode = codebyte;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cbInc = ParseInstruction(InstructionAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iByte += cbInc;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opsize = iByte;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pcbInstruction)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *pcbInstruction = iByte;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->prefix & PREFIX_LOCK)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disValidateLockSequence(pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return VINF_SUCCESS;
a79493184c9332129c9c91500069322f6f3fafddReed}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunsigned ParseInstruction(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, PDISCPUSTATE pCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bool fFiltered = false;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // Store the opcode format string for disasmPrintf
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifndef DIS_CORE_ONLY
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pszOpcode = pOp->pszOpcode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pCurInstr = pOp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Apply filter to instruction type to determine if a full disassembly is required.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @note Multibyte opcodes are always marked harmless until the final byte.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((pOp->optype & pCpu->uFilter) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fFiltered = true;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnDisasmFnTable = pfnCalcSize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Not filtered out -> full disassembly */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnDisasmFnTable = pfnFullDisasm;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // Should contain the parameter type on input
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.param = pOp->param1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.param = pOp->param2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param3.param = pOp->param3;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Correct the operand size if the instruction is marked as forced or default 64 bits */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_64BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pOp->optype & OPTYPE_FORCED_64_OP_SIZE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opsize = CPUMODE_64BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( (pOp->optype & OPTYPE_DEFAULT_64_OP_SIZE)
a79493184c9332129c9c91500069322f6f3fafddReed && !(pCpu->prefix & PREFIX_OPSIZE))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opsize = CPUMODE_64BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pOp->idxParse1 != IDX_ParseNop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += pCpu->pfnDisasmFnTable[pOp->idxParse1](lpszCodeBlock, pOp, &pCpu->param1, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fFiltered == false) pCpu->param1.size = DISGetParamSize(pCpu, &pCpu->param1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pOp->idxParse2 != IDX_ParseNop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += pCpu->pfnDisasmFnTable[pOp->idxParse2](lpszCodeBlock+size, pOp, &pCpu->param2, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fFiltered == false) pCpu->param2.size = DISGetParamSize(pCpu, &pCpu->param2);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pOp->idxParse3 != IDX_ParseNop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += pCpu->pfnDisasmFnTable[pOp->idxParse3](lpszCodeBlock+size, pOp, &pCpu->param3, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fFiltered == false) pCpu->param3.size = DISGetParamSize(pCpu, &pCpu->param3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // else simple one byte instruction
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Floating point opcode parsing */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunsigned ParseEscFP(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int index;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const OPCODE *fpop;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned size = 0, ModRM;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ModRM = DISReadByte(pCpu, lpszCodeBlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte index = pCpu->opcode - 0xD8;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ModRM <= 0xBF)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fpop = &(g_paMapX86_FP_Low[index])[MODRM_REG(ModRM)];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pCurInstr = (PCOPCODE)fpop;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // Should contain the parameter type on input
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param1.parval = fpop->param1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->param2.parval = fpop->param2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fpop = &(g_paMapX86_FP_High[index])[ModRM - 0xC0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pCurInstr = (PCOPCODE)fpop;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Apply filter to instruction type to determine if a full disassembly is required.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @note Multibyte opcodes are always marked harmless until the final byte.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((fpop->optype & pCpu->uFilter) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnDisasmFnTable = pfnCalcSize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Not filtered out -> full disassembly */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pfnDisasmFnTable = pfnFullDisasm;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Correct the operand size if the instruction is marked as forced or default 64 bits */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_64BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Note: redundant, but just in case this ever changes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fpop->optype & OPTYPE_FORCED_64_OP_SIZE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opsize = CPUMODE_64BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( (fpop->optype & OPTYPE_DEFAULT_64_OP_SIZE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte && !(pCpu->prefix & PREFIX_OPSIZE))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->opsize = CPUMODE_64BIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // Little hack to make sure the ModRM byte is included in the returned size
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size = sizeof(uint8_t); //ModRM byte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fpop->idxParse1 != IDX_ParseNop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += pCpu->pfnDisasmFnTable[fpop->idxParse1](lpszCodeBlock+size, (PCOPCODE)fpop, pParam, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fpop->idxParse2 != IDX_ParseNop)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += pCpu->pfnDisasmFnTable[fpop->idxParse2](lpszCodeBlock+size, (PCOPCODE)fpop, pParam, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // Store the opcode format string for disasmPrintf
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#ifndef DIS_CORE_ONLY
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->pszOpcode = fpop->pszOpcode;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
a79493184c9332129c9c91500069322f6f3fafddReed// SIB byte: (32 bits mode only)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte// 7 - 6 5 - 3 2-0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte// Scale Index Base
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic const char *szSIBBaseReg[8] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic const char *szSIBIndexReg[8] = {"EAX", "ECX", "EDX", "EBX", NULL, "EBP", "ESI", "EDI"};
a79493184c9332129c9c91500069322f6f3fafddReedstatic const char *szSIBBaseReg64[16] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic const char *szSIBIndexReg64[16]= {"RAX", "RCX", "RDX", "RBX", NULL, "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic const char *szSIBScale[4] = {"", "*2", "*4", "*8"};
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid UseSIB(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned scale, base, index, regtype;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char **ppszSIBIndexReg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const char **ppszSIBBaseReg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char szTemp[32];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte szTemp[0] = '\0';
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scale = pCpu->SIB.Bits.Scale;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte base = pCpu->SIB.Bits.Base;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte index = pCpu->SIB.Bits.Index;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->addrmode == CPUMODE_32BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ppszSIBIndexReg = szSIBIndexReg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ppszSIBBaseReg = szSIBBaseReg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte regtype = USE_REG_GEN32;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ppszSIBIndexReg = szSIBIndexReg64;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ppszSIBBaseReg = szSIBBaseReg64;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte regtype = USE_REG_GEN64;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ppszSIBIndexReg[index])
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_INDEX;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->index.reg_gen = index;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scale != 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_SCALE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->scale = (1<<scale);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (base == 5 && pCpu->ModRM.Bits.Mod == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(szTemp, sizeof(szTemp), "%s%s", ppszSIBIndexReg[index], szSIBScale[scale]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(szTemp, sizeof(szTemp), "%s+%s%s", ppszSIBBaseReg[base], ppszSIBIndexReg[index], szSIBScale[scale]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (base != 5 || pCpu->ModRM.Bits.Mod != 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(szTemp, sizeof(szTemp), "%s", ppszSIBBaseReg[base]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (base == 5 && pCpu->ModRM.Bits.Mod == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte // [scaled index] + disp32
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddString(pParam->szParam, &szTemp[0]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_DISPLACEMENT32;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->disp32 = pCpu->disp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '+');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmPrintDisp32(pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddString(pParam->szParam, szTemp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_BASE | regtype;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->base.reg_gen = base;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* Already fetched everything in ParseSIB; no size returned */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunsigned ParseSIB(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned size = sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned SIB;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SIB = DISReadByte(pCpu, lpszCodeBlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lpszCodeBlock += size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Base = SIB_BASE(SIB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Index = SIB_INDEX(SIB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Scale = SIB_SCALE(SIB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->prefix & PREFIX_REX)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* REX.B extends the Base field if not scaled index + disp32 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(pCpu->SIB.Bits.Base == 5 && pCpu->ModRM.Bits.Mod == 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Base |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_B)) << 3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Index |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_X)) << 3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( pCpu->SIB.Bits.Base == 5
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte && pCpu->ModRM.Bits.Mod == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Additional 32 bits displacement. No change in long mode. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += sizeof(int32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned size = sizeof(uint8_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned SIB;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SIB = DISReadByte(pCpu, lpszCodeBlock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lpszCodeBlock += size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Base = SIB_BASE(SIB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Index = SIB_INDEX(SIB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Scale = SIB_SCALE(SIB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->prefix & PREFIX_REX)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* REX.B extends the Base field. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Base |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_B)) << 3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* REX.X extends the Index field. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pCpu->SIB.Bits.Index |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_X)) << 3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( pCpu->SIB.Bits.Base == 5
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte && pCpu->ModRM.Bits.Mod == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Additional 32 bits displacement. No change in long mode. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size += sizeof(int32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte// ModR/M byte:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte// 7 - 6 5 - 3 2-0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte// Mod Reg/Opcode R/M
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte//*****************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteunsigned UseModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int vtype = OP_PARM_VTYPE(pParam->param);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned reg = pCpu->ModRM.Bits.Reg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned mod = pCpu->ModRM.Bits.Mod;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned rm = pCpu->ModRM.Bits.Rm;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (vtype)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_G: //general purpose register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg(pCpu, pOp, reg, pParam, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (IS_OP_PARM_RARE(vtype))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (vtype)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_C: //control register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "CR%d", reg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_REG_CR;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->base.reg_ctrl = reg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_D: //debug register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "DR%d", reg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_REG_DBG;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->base.reg_dbg = reg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_P: //MMX register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte reg &= 7; /* REX.R has no effect here */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "MM%d", reg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_REG_MMX;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->base.reg_mmx = reg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_S: //segment register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte reg &= 7; /* REX.R has no effect here */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMSReg(pCpu, pOp, reg, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_REG_SEG;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_T: //test register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte reg &= 7; /* REX.R has no effect here */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "TR%d", reg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_REG_TEST;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->base.reg_test = reg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_W: //XMM register or memory operand
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (mod != 3)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break; /* memory operand */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte reg = rm; /* the RM field specifies the xmm register */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* else no break */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case OP_PARM_V: //XMM register
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "XMM%d", reg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_REG_XMM;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->base.reg_xmm = reg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* @todo bound */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->addrmode != CPUMODE_16BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte Assert(pCpu->addrmode == CPUMODE_32BIT || pCpu->addrmode == CPUMODE_64BIT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (mod)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0: //effective address
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmGetPtrString(pCpu, pOp, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '[');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rm == 4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { /* SIB byte follows ModRM */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rm == 5)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 32 bits displacement */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCpu->mode == CPUMODE_32BIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_DISPLACEMENT32;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->disp32 = pCpu->disp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmPrintDisp32(pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_RIPDISPLACEMENT32;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->disp32 = pCpu->disp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "RIP+");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmPrintDisp32(pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else {//register address
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_BASE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg(pCpu, pOp, rm, pParam, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, ']');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 1: //effective address + 8 bits displacement
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmGetPtrString(pCpu, pOp, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '[');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rm == 4) {//SIB byte follows ModRM
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_BASE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg(pCpu, pOp, rm, pParam, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->disp8 = pCpu->disp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_DISPLACEMENT8;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pParam->disp8 != 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pParam->disp8 > 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '+');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmPrintDisp8(pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, ']');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 2: //effective address + 32 bits displacement
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmGetPtrString(pCpu, pOp, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '[');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rm == 4) {//SIB byte follows ModRM
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_BASE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg(pCpu, pOp, rm, pParam, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->disp32 = pCpu->disp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_DISPLACEMENT32;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pParam->disp32 != 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '+');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmPrintDisp32(pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, ']');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 3: //registers
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg(pCpu, pOp, rm, pParam, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {//16 bits addressing mode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (mod)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0: //effective address
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmGetPtrString(pCpu, pOp, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '[');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rm == 6)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {//16 bits displacement
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->disp16 = pCpu->disp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_DISPLACEMENT16;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmPrintDisp16(pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pParam->flags |= USE_BASE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg16(pCpu, pOp, rm, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, ']');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 1: //effective address + 8 bits displacement
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmGetPtrString(pCpu, pOp, pParam);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmAddChar(pParam->szParam, '[');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte disasmModRMReg16(pCpu, pOp, rm, pParam);
a79493184c9332129c9c91500069322f6f3fafddReed pParam->disp8 = pCpu->disp;
a79493184c9332129c9c91500069322f6f3fafddReed pParam->flags |= USE_BASE | USE_DISPLACEMENT8;
a79493184c9332129c9c91500069322f6f3fafddReed
a79493184c9332129c9c91500069322f6f3fafddReed if (pParam->disp8 != 0)
a79493184c9332129c9c91500069322f6f3fafddReed {
a79493184c9332129c9c91500069322f6f3fafddReed if (pParam->disp8 > 0)
a79493184c9332129c9c91500069322f6f3fafddReed disasmAddChar(pParam->szParam, '+');
a79493184c9332129c9c91500069322f6f3fafddReed disasmPrintDisp8(pParam);
a79493184c9332129c9c91500069322f6f3fafddReed }
a79493184c9332129c9c91500069322f6f3fafddReed disasmAddChar(pParam->szParam, ']');
a79493184c9332129c9c91500069322f6f3fafddReed break;
a79493184c9332129c9c91500069322f6f3fafddReed
a79493184c9332129c9c91500069322f6f3fafddReed case 2: //effective address + 16 bits displacement
a79493184c9332129c9c91500069322f6f3fafddReed disasmGetPtrString(pCpu, pOp, pParam);
a79493184c9332129c9c91500069322f6f3fafddReed disasmAddChar(pParam->szParam, '[');
a79493184c9332129c9c91500069322f6f3fafddReed disasmModRMReg16(pCpu, pOp, rm, pParam);
a79493184c9332129c9c91500069322f6f3fafddReed pParam->disp16 = pCpu->disp;
a79493184c9332129c9c91500069322f6f3fafddReed pParam->flags |= USE_BASE | USE_DISPLACEMENT16;
a79493184c9332129c9c91500069322f6f3fafddReed
a79493184c9332129c9c91500069322f6f3fafddReed if (pParam->disp16 != 0)
a79493184c9332129c9c91500069322f6f3fafddReed {
a79493184c9332129c9c91500069322f6f3fafddReed disasmAddChar(pParam->szParam, '+');
disasmPrintDisp16(pParam);
}
disasmAddChar(pParam->szParam, ']');
break;
case 3: //registers
disasmModRMReg(pCpu, pOp, rm, pParam, 0);
break;
}
}
return 0; //everything was already fetched in ParseModRM
}
//*****************************************************************************
// Query the size of the ModRM parameters and fetch the immediate data (if any)
//*****************************************************************************
unsigned QueryModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
{
unsigned sibinc;
unsigned size = 0;
// unsigned reg = pCpu->ModRM.Bits.Reg;
unsigned mod = pCpu->ModRM.Bits.Mod;
unsigned rm = pCpu->ModRM.Bits.Rm;
if (!pSibInc)
pSibInc = &sibinc;
*pSibInc = 0;
if (pCpu->addrmode != CPUMODE_16BIT)
{
Assert(pCpu->addrmode == CPUMODE_32BIT || pCpu->addrmode == CPUMODE_64BIT);
/*
* Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
*/
if (mod != 3 && rm == 4)
{ /* SIB byte follows ModRM */
*pSibInc = ParseSIB(lpszCodeBlock, pOp, pParam, pCpu);
lpszCodeBlock += *pSibInc;
size += *pSibInc;
}
switch (mod)
{
case 0: /* Effective address */
if (rm == 5) { /* 32 bits displacement */
pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
size += sizeof(int32_t);
}
/* else register address */
break;
case 1: /* Effective address + 8 bits displacement */
pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
size += sizeof(char);
break;
case 2: /* Effective address + 32 bits displacement */
pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
size += sizeof(int32_t);
break;
case 3: /* registers */
break;
}
}
else
{
/* 16 bits mode */
switch (mod)
{
case 0: /* Effective address */
if (rm == 6) {
pCpu->disp = DISReadWord(pCpu, lpszCodeBlock);
size += sizeof(uint16_t);
}
/* else register address */
break;
case 1: /* Effective address + 8 bits displacement */
pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
size += sizeof(char);
break;
case 2: /* Effective address + 32 bits displacement */
pCpu->disp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);
size += sizeof(uint16_t);
break;
case 3: /* registers */
break;
}
}
return size;
}
//*****************************************************************************
// Query the size of the ModRM parameters and fetch the immediate data (if any)
//*****************************************************************************
unsigned QueryModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
{
unsigned sibinc;
unsigned size = 0;
// unsigned reg = pCpu->ModRM.Bits.Reg;
unsigned mod = pCpu->ModRM.Bits.Mod;
unsigned rm = pCpu->ModRM.Bits.Rm;
if (!pSibInc)
pSibInc = &sibinc;
*pSibInc = 0;
if (pCpu->addrmode != CPUMODE_16BIT)
{
Assert(pCpu->addrmode == CPUMODE_32BIT || pCpu->addrmode == CPUMODE_64BIT);
/*
* Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
*/
if (mod != 3 && rm == 4)
{ /* SIB byte follows ModRM */
*pSibInc = ParseSIB_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu);
lpszCodeBlock += *pSibInc;
size += *pSibInc;
}
switch (mod)
{
case 0: //effective address
if (rm == 5) { /* 32 bits displacement */
size += sizeof(int32_t);
}
/* else register address */
break;
case 1: /* Effective address + 8 bits displacement */
size += sizeof(char);
break;
case 2: /* Effective address + 32 bits displacement */
size += sizeof(int32_t);
break;
case 3: /* registers */
break;
}
}
else
{
/* 16 bits mode */
switch (mod)
{
case 0: //effective address
if (rm == 6) {
size += sizeof(uint16_t);
}
/* else register address */
break;
case 1: /* Effective address + 8 bits displacement */
size += sizeof(char);
break;
case 2: /* Effective address + 32 bits displacement */
size += sizeof(uint16_t);
break;
case 3: /* registers */
break;
}
}
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseIllegal(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
AssertFailed();
return 0;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = sizeof(uint8_t); //ModRM byte
unsigned sibinc, ModRM;
ModRM = DISReadByte(pCpu, lpszCodeBlock);
lpszCodeBlock += sizeof(uint8_t);
pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
if (pCpu->prefix & PREFIX_REX)
{
Assert(pCpu->mode == CPUMODE_64BIT);
/* REX.R extends the Reg field. */
pCpu->ModRM.Bits.Reg |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_R)) << 3);
/* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
if (!( pCpu->ModRM.Bits.Mod != 3
&& pCpu->ModRM.Bits.Rm == 4)
&&
!( pCpu->ModRM.Bits.Mod == 0
&& pCpu->ModRM.Bits.Rm == 5))
{
pCpu->ModRM.Bits.Rm |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_B)) << 3);
}
}
size += QueryModRM(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
lpszCodeBlock += sibinc;
UseModRM(lpszCodeBlock, pOp, pParam, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = sizeof(uint8_t); //ModRM byte
unsigned sibinc, ModRM;
ModRM = DISReadByte(pCpu, lpszCodeBlock);
lpszCodeBlock += sizeof(uint8_t);
pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
if (pCpu->prefix & PREFIX_REX)
{
Assert(pCpu->mode == CPUMODE_64BIT);
/* REX.R extends the Reg field. */
pCpu->ModRM.Bits.Reg |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_R)) << 3);
/* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
if (!( pCpu->ModRM.Bits.Mod != 3
&& pCpu->ModRM.Bits.Rm == 4)
&&
!( pCpu->ModRM.Bits.Mod == 0
&& pCpu->ModRM.Bits.Rm == 5))
{
pCpu->ModRM.Bits.Rm |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_B)) << 3);
}
}
size += QueryModRM_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
lpszCodeBlock += sibinc;
/* UseModRM is not necessary here; we're only interested in the opcode size */
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseModFence(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
////AssertMsgFailed(("??\n"));
//nothing to do apparently
return 0;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmByte(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE8;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%02Xh", (uint32_t)pParam->parval);
return sizeof(uint8_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmByte_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
return sizeof(uint8_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmByteSX(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
if (pCpu->opmode == CPUMODE_32BIT)
{
pParam->parval = (uint32_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE32_SX8;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
}
else
{
pParam->parval = (uint16_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE16_SX8;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
}
return sizeof(uint8_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmByteSX_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
return sizeof(uint8_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmUshort(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE16;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
return sizeof(uint16_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmUshort_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
return sizeof(uint16_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmUlong(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE32;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
return sizeof(uint32_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmUlong_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
return sizeof(uint32_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmQword(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE64;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08X", (uint32_t)pParam->parval);
disasmAddStringF(&pParam->szParam[9], sizeof(pParam->szParam)-9, "%08Xh", (uint32_t)(pParam->parval >> 32));
return sizeof(uint64_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmQword_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
return sizeof(uint64_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmV(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
if (pCpu->opmode == CPUMODE_32BIT)
{
pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE32;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
return sizeof(uint32_t);
}
else
if (pCpu->opmode == CPUMODE_64BIT)
{
pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE64;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%VX64h", pParam->parval);
return sizeof(uint64_t);
}
else
{
pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE16;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint32_t)pParam->parval);
return sizeof(uint16_t);
}
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmV_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
if (pCpu->opmode == CPUMODE_32BIT)
return sizeof(uint32_t);
else
if (pCpu->opmode == CPUMODE_64BIT)
return sizeof(uint64_t);
return sizeof(uint16_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmZ(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
/* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
if (pCpu->opmode == CPUMODE_16BIT)
{
pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE16;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint32_t)pParam->parval);
return sizeof(uint16_t);
}
else
{
pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE32;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
return sizeof(uint32_t);
}
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmZ_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
/* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
if (pCpu->opmode == CPUMODE_16BIT)
return sizeof(uint16_t);
return sizeof(uint32_t);
}
//*****************************************************************************
// Relative displacement for branches (rel. to next instruction)
//*****************************************************************************
unsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE8_REL;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%02Xh)", (uint32_t)pParam->parval);
return sizeof(char);
}
//*****************************************************************************
// Relative displacement for branches (rel. to next instruction)
//*****************************************************************************
unsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
return sizeof(char);
}
//*****************************************************************************
// Relative displacement for branches (rel. to next instruction)
//*****************************************************************************
unsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
if (pCpu->opmode == CPUMODE_32BIT)
{
pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE32_REL;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%08Xh)", (uint32_t)pParam->parval);
return sizeof(int32_t);
}
else
if (pCpu->opmode == CPUMODE_64BIT)
{
pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE64_REL;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%VX64h)", pParam->parval);
return sizeof(int64_t);
}
else
{
pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE16_REL;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%04Xh)", (uint32_t)pParam->parval);
return sizeof(uint16_t);
}
}
//*****************************************************************************
// Relative displacement for branches (rel. to next instruction)
//*****************************************************************************
unsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
if (pCpu->opmode == CPUMODE_32BIT)
return sizeof(int32_t);
else
if (pCpu->opmode == CPUMODE_64BIT)
return sizeof(int64_t);
return sizeof(uint16_t);
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmGetPtrString(pCpu, pOp, pParam);
if (pCpu->addrmode == CPUMODE_32BIT)
{
if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
{// far 16:32 pointer
pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
*((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
return sizeof(uint32_t) + sizeof(uint16_t);
}
else
{// near 32 bits pointer
/*
* Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
* so we treat it like displacement.
*/
pParam->disp32 = DISReadDWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_DISPLACEMENT32;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08Xh]", pParam->disp32);
return sizeof(uint32_t);
}
}
else
if (pCpu->addrmode == CPUMODE_64BIT)
{
Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
/* near 64 bits pointer */
/*
* Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
* so we treat it like displacement.
*/
pParam->disp64 = DISReadQWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_DISPLACEMENT64;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64);
return sizeof(uint64_t);
}
else
{
if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
{// far 16:16 pointer
pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
return sizeof(uint32_t);
}
else
{// near 16 bits pointer
/*
* Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
* so we treat it like displacement.
*/
pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
pParam->flags |= USE_DISPLACEMENT16;
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
return sizeof(uint16_t);
}
}
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
if (pCpu->addrmode == CPUMODE_32BIT)
{
if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
{// far 16:32 pointer
return sizeof(uint32_t) + sizeof(uint16_t);
}
else
{// near 32 bits pointer
return sizeof(uint32_t);
}
}
if (pCpu->addrmode == CPUMODE_64BIT)
{
Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
return sizeof(uint64_t);
}
else
{
if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
{// far 16:16 pointer
return sizeof(uint32_t);
}
else
{// near 16 bits pointer
return sizeof(uint16_t);
}
}
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
/*
* Sets up flags for stored in OPC fixed registers.
*/
if (pParam->param == OP_PARM_NONE)
{
/* No parameter at all. */
return 0;
}
AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
if (pParam->param <= OP_PARM_REG_GEN32_END)
{
/* 32-bit EAX..EDI registers. */
if (pCpu->opmode == CPUMODE_32BIT)
{
/* Use 32-bit registers. */
pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
pParam->flags |= USE_REG_GEN32;
pParam->size = 4;
}
else
if (pCpu->opmode == CPUMODE_64BIT)
{
/* Use 64-bit registers. */
pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
&& pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
&& (pCpu->prefix & PREFIX_REX)
&& (pCpu->prefix_rex & PREFIX_REX_FLAGS))
pParam->base.reg_gen += 8;
pParam->flags |= USE_REG_GEN64;
pParam->size = 8;
}
else
{
/* Use 16-bit registers. */
pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
pParam->flags |= USE_REG_GEN16;
pParam->size = 2;
pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
}
}
else
if (pParam->param <= OP_PARM_REG_SEG_END)
{
/* Segment ES..GS registers. */
pParam->base.reg_seg = pParam->param - OP_PARM_REG_SEG_START;
pParam->flags |= USE_REG_SEG;
pParam->size = 2;
}
else
if (pParam->param <= OP_PARM_REG_GEN16_END)
{
/* 16-bit AX..DI registers. */
pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN16_START;
pParam->flags |= USE_REG_GEN16;
pParam->size = 2;
}
else
if (pParam->param <= OP_PARM_REG_GEN8_END)
{
/* 8-bit AL..DL, AH..DH registers. */
pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN8_START;
pParam->flags |= USE_REG_GEN8;
pParam->size = 1;
if (pCpu->opmode == CPUMODE_64BIT)
{
if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
&& pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
&& (pCpu->prefix & PREFIX_REX)
&& (pCpu->prefix_rex & PREFIX_REX_FLAGS))
pParam->base.reg_gen += 8; /* least significant byte of R8-R15 */
}
}
else
if (pParam->param <= OP_PARM_REG_FP_END)
{
/* FPU registers. */
pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
pParam->flags |= USE_REG_FP;
pParam->size = 10;
}
Assert(!(pParam->param >= OP_PARM_REG_GEN64_START && pParam->param <= OP_PARM_REG_GEN64_END));
/* else - not supported for now registers. */
return 0;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmGetPtrString(pCpu, pOp, pParam);
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
pParam->flags |= USE_POINTER_DS_BASED;
if (pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen = USE_REG_ESI;
pParam->flags |= USE_REG_GEN32;
}
else
if (pCpu->addrmode == CPUMODE_64BIT)
{
pParam->base.reg_gen = USE_REG_RSI;
pParam->flags |= USE_REG_GEN64;
}
else
{
pParam->base.reg_gen = USE_REG_SI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
pParam->flags |= USE_POINTER_DS_BASED;
if (pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen = USE_REG_ESI;
pParam->flags |= USE_REG_GEN32;
}
else
if (pCpu->addrmode == CPUMODE_64BIT)
{
pParam->base.reg_gen = USE_REG_RSI;
pParam->flags |= USE_REG_GEN64;
}
else
{
pParam->base.reg_gen = USE_REG_SI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmGetPtrString(pCpu, pOp, pParam);
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
pParam->flags |= USE_POINTER_ES_BASED;
if (pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen = USE_REG_EDI;
pParam->flags |= USE_REG_GEN32;
}
else
if (pCpu->addrmode == CPUMODE_64BIT)
{
pParam->base.reg_gen = USE_REG_RDI;
pParam->flags |= USE_REG_GEN64;
}
else
{
pParam->base.reg_gen = USE_REG_DI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
pParam->flags |= USE_POINTER_ES_BASED;
if (pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen = USE_REG_EDI;
pParam->flags |= USE_REG_GEN32;
}
else
if (pCpu->addrmode == CPUMODE_64BIT)
{
pParam->base.reg_gen = USE_REG_RDI;
pParam->flags |= USE_REG_GEN64;
}
else
{
pParam->base.reg_gen = USE_REG_DI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
const OPCODE *pOpcode;
int size = sizeof(uint8_t);
//2nd byte
pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
/* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
/** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
if (pCpu->lastprefix)
{
switch (pCpu->lastprefix)
{
case OP_OPSIZE: /* 0x66 */
if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
{
/* Table entry is valid, so use the extension table. */
pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
/* Cancel prefix changes. */
pCpu->prefix &= ~PREFIX_OPSIZE;
pCpu->opmode = pCpu->mode;
}
break;
case OP_REPNE: /* 0xF2 */
if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
{
/* Table entry is valid, so use the extension table. */
pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
/* Cancel prefix changes. */
pCpu->prefix &= ~PREFIX_REPNE;
}
break;
case OP_REPE: /* 0xF3 */
if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
{
/* Table entry is valid, so use the extension table. */
pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
/* Cancel prefix changes. */
pCpu->prefix &= ~PREFIX_REP;
}
break;
}
}
size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0;
if (pCpu->prefix & PREFIX_REP)
{
pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
pCpu->prefix &= ~PREFIX_REP;
}
else
pOp = &g_aMapX86_NopPause[0]; /* NOP */
size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
int idx = (pCpu->opcode - 0x80) * 8;
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
int idx;
unsigned size = 0, modrm, reg;
switch (pCpu->opcode)
{
case 0xC0:
case 0xC1:
idx = (pCpu->opcode - 0xC0)*8;
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
idx = (pCpu->opcode - 0xD0 + 2)*8;
break;
default:
AssertMsgFailed(("Oops\n"));
return sizeof(uint8_t);
}
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
int idx = (pCpu->opcode - 0xF6) * 8;
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
// It would appear the ModRM byte must always be present. How else can you
// determine the offset of the imm8_opcode byte otherwise?
//
//*****************************************************************************
unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrmsize;
#ifdef DEBUG_Sander
//needs testing
AssertMsgFailed(("Test me\n"));
#endif
unsigned ModRM = DISReadByte(pCpu, lpszCodeBlock);
pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
AssertMsgFailed(("Oops!\n")); //shouldn't happen!
#endif
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
size += sizeof(uint8_t); //imm8_opcode uint8_t
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg, rm, mod;
modrm = DISReadByte(pCpu, lpszCodeBlock);
mod = MODRM_MOD(modrm);
reg = MODRM_REG(modrm);
rm = MODRM_RM(modrm);
if (mod == 3 && rm == 0)
pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
else
if (mod == 3 && rm == 1)
pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
else
pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
if (pCpu->prefix & PREFIX_OPSIZE)
reg += 8; //2nd table
pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
if (pCpu->prefix & PREFIX_OPSIZE)
reg += 8; //2nd table
pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
if (pCpu->prefix & PREFIX_OPSIZE)
reg += 8; //2nd table
pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg, mod, rm;
modrm = DISReadByte(pCpu, lpszCodeBlock);
mod = MODRM_MOD(modrm);
reg = MODRM_REG(modrm);
rm = MODRM_RM(modrm);
if (mod == 3 && rm == 0)
pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
else
pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
//little hack to make sure the ModRM byte is included in the returned size
if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
size = sizeof(uint8_t); //ModRM byte
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
static const char *szModRMReg8_64[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8L", "R9L", "R10L", "R11L", "R12L", "R13L", "R14L", "R15L"};
static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
#endif
static const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
static const int BaseModRMReg16[8] = { USE_REG_BX, USE_REG_BX, USE_REG_BP, USE_REG_BP, USE_REG_SI, USE_REG_DI, USE_REG_BP, USE_REG_BX};
static const int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
//*****************************************************************************
void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam, int fRegAddr)
{
int subtype, type, mod;
mod = pCpu->ModRM.Bits.Mod;
type = OP_PARM_VTYPE(pParam->param);
subtype = OP_PARM_VSUBTYPE(pParam->param);
if (fRegAddr)
subtype = (pCpu->addrmode == CPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
else
if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
{
switch(pCpu->opmode)
{
case CPUMODE_32BIT:
subtype = OP_PARM_d;
break;
case CPUMODE_64BIT:
subtype = OP_PARM_q;
break;
case CPUMODE_16BIT:
subtype = OP_PARM_w;
break;
default:
/* make gcc happy */
break;
}
}
switch (subtype)
{
case OP_PARM_b:
#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
if (idx > (int)RT_ELEMENTS(szModRMReg8))
disasmAddString(pParam->szParam, szModRMReg8_64[idx]);
else
disasmAddString(pParam->szParam, szModRMReg8[idx]);
#endif
pParam->flags |= USE_REG_GEN8;
pParam->base.reg_gen = idx;
break;
case OP_PARM_w:
disasmAddString(pParam->szParam, szModRMReg16[idx]);
pParam->flags |= USE_REG_GEN16;
pParam->base.reg_gen = idx;
break;
case OP_PARM_d:
disasmAddString(pParam->szParam, szModRMReg32[idx]);
pParam->flags |= USE_REG_GEN32;
pParam->base.reg_gen = idx;
break;
case OP_PARM_q:
disasmAddString(pParam->szParam, szModRMReg64[idx]);
pParam->flags |= USE_REG_GEN64;
pParam->base.reg_gen = idx;
break;
default:
#ifdef IN_RING3
Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
DIS_THROW(ExceptionInvalidModRM);
#else
AssertMsgFailed(("Oops!\n"));
#endif
break;
}
}
//*****************************************************************************
//*****************************************************************************
void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
{
disasmAddString(pParam->szParam, szModRMReg1616[idx]);
pParam->flags |= USE_REG_GEN16;
pParam->base.reg_gen = BaseModRMReg16[idx];
if (idx < 4)
{
pParam->flags |= USE_INDEX;
pParam->index.reg_gen = IndexModRMReg16[idx];
}
}
//*****************************************************************************
//*****************************************************************************
void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
{
#if 0 //def DEBUG_Sander
AssertMsg(idx < (int)ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
#endif
#ifdef IN_RING3
if (idx >= (int)ELEMENTS(szModRMSegReg))
{
Log(("disasmModRMSReg %d failed!!\n", idx));
DIS_THROW(ExceptionInvalidParameter);
}
#endif
idx = RT_MIN(idx, (int)ELEMENTS(szModRMSegReg)-1);
disasmAddString(pParam->szParam, szModRMSegReg[idx]);
pParam->flags |= USE_REG_SEG;
pParam->base.reg_seg = idx;
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintAbs32(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintDisp32(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintDisp8(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintDisp16(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
}
//*****************************************************************************
//*****************************************************************************
void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
{
int subtype = OP_PARM_VSUBTYPE(pParam->param);
if (subtype == OP_PARM_v)
{
switch(pCpu->opmode)
{
case CPUMODE_32BIT:
subtype = OP_PARM_d;
break;
case CPUMODE_64BIT:
subtype = OP_PARM_q;
break;
case CPUMODE_16BIT:
subtype = OP_PARM_w;
break;
default:
/* make gcc happy */
break;
}
}
switch (subtype)
{
case OP_PARM_a: //two words or dwords depending on operand size (bound only)
break;
case OP_PARM_b:
disasmAddString(pParam->szParam, "byte ptr ");
break;
case OP_PARM_w:
disasmAddString(pParam->szParam, "word ptr ");
break;
case OP_PARM_d:
disasmAddString(pParam->szParam, "dword ptr ");
break;
case OP_PARM_q:
case OP_PARM_dq:
disasmAddString(pParam->szParam, "qword ptr ");
break;
case OP_PARM_p:
disasmAddString(pParam->szParam, "far ptr ");
break;
case OP_PARM_s:
break; //??
case OP_PARM_z:
break;
default:
break; //no pointer type specified/necessary
}
if (pCpu->prefix & PREFIX_SEG)
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->prefix_seg]);
}
#ifndef IN_GC
//*****************************************************************************
/* Read functions for getting the opcode bytes */
//*****************************************************************************
uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if (pCpu->pfnReadBytes)
{
uint8_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
if (VBOX_FAILURE(rc))
{
Log(("DISReadByte failed!!\n"));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint8_t *)pAddress;
#endif
}
//*****************************************************************************
//*****************************************************************************
uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if (pCpu->pfnReadBytes)
{
uint16_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
if (VBOX_FAILURE(rc))
{
Log(("DISReadWord failed!!\n"));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint16_t *)pAddress;
#endif
}
//*****************************************************************************
//*****************************************************************************
uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if (pCpu->pfnReadBytes)
{
uint32_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
if (VBOX_FAILURE(rc))
{
Log(("DISReadDWord failed!!\n"));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint32_t *)pAddress;
#endif
}
//*****************************************************************************
//*****************************************************************************
uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if (pCpu->pfnReadBytes)
{
uint64_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
if (VBOX_FAILURE(rc))
{
Log(("DISReadQWord %x failed!!\n", pAddress));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint64_t *)pAddress;
#endif
}
#endif /* IN_GC */
#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
//*****************************************************************************
//*****************************************************************************
void disasmAddString(char *psz, const char *pszAdd)
{
strcat(psz, pszAdd);
}
//*****************************************************************************
//*****************************************************************************
void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
{
va_list args;
va_start(args, pszFormat);
RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
va_end(args);
}
//*****************************************************************************
//*****************************************************************************
void disasmAddChar(char *psz, char ch)
{
char sz[2];
sz[0] = ch;
sz[1] = '\0';
strcat(psz, sz);
}
#endif /* !DIS_CORE_ONLY */
/**
* Validates the lock sequence.
*
* The AMD manual lists the following instructions:
* ADC
* ADD
* AND
* BTC
* BTR
* BTS
* CMPXCHG
* CMPXCHG8B
* CMPXCHG16B
* DEC
* INC
* NEG
* NOT
* OR
* SBB
* SUB
* XADD
* XCHG
* XOR
*
* @param pCpu Fully dissassembled instruction.
*/
void disValidateLockSequence(PDISCPUSTATE pCpu)
{
Assert(pCpu->prefix & PREFIX_LOCK);
/*
* Filter out the valid lock sequences.
*/
switch (pCpu->pCurInstr->opcode)
{
/* simple: no variations */
case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
return;
/* simple: /r - reject register destination. */
case OP_BTC:
case OP_BTR:
case OP_BTS:
case OP_CMPXCHG:
case OP_XADD:
if (pCpu->ModRM.Bits.Mod == 3)
break;
return;
/*
* Lots of variants but its sufficient to check that param 1
* is a memory operand.
*/
case OP_ADC:
case OP_ADD:
case OP_AND:
case OP_DEC:
case OP_INC:
case OP_NEG:
case OP_NOT:
case OP_OR:
case OP_SBB:
case OP_SUB:
case OP_XCHG:
case OP_XOR:
if (pCpu->param1.flags & (USE_BASE | USE_INDEX | USE_DISPLACEMENT32 | USE_DISPLACEMENT16 | USE_DISPLACEMENT8 | USE_RIPDISPLACEMENT32))
return;
break;
default:
break;
}
/*
* Invalid lock sequence, make it a OP_ILLUD2.
*/
pCpu->pCurInstr = &g_aTwoByteMapX86[11];
Assert(pCpu->pCurInstr->opcode == OP_ILLUD2);
}