DisasmCore.cpp revision c2e9d2e74a22023533b45a005c3e90a29d2eb216
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync/* $Id$ */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @file
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * VBox Disassembler - Core Components.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2012 Oracle Corporation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header Files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define LOG_GROUP LOG_GROUP_DIS
cd6f71bc352f550074f1ba2c830a2cf2f0b3dd46vboxsync#include <VBox/dis.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/disopcode.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/err.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/log.h>
16a9adc14900ca18e6909679a579f6833425e030vboxsync#include <iprt/assert.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/param.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/string.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/stdarg.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "DisasmInternal.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync* Defined Constants And Macros *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync*******************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** This must be less or equal to DISSTATE::abInstr. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync#define DIS_MAX_INSTR_LENGTH 16
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync/** Whether we can do unaligned access. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync# define DIS_HOST_UNALIGNED_ACCESS_OK
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync/*******************************************************************************
efff36b306e370346025647a158689021df2e1d1vboxsync* Internal Functions *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync/** @name Parsers
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @{ */
efff36b306e370346025647a158689021df2e1d1vboxsyncstatic FNDISPARSE ParseIllegal;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic FNDISPARSE ParseModRM;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic FNDISPARSE ParseModRM_SizeOnly;
efff36b306e370346025647a158689021df2e1d1vboxsyncstatic FNDISPARSE UseModRM;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic FNDISPARSE ParseImmByte;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByte_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByteSX;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByteSX_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmBRel;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmBRel_SizeOnly;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic FNDISPARSE ParseImmUshort;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmUshort_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmV;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmV_SizeOnly;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmVRel;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmVRel_SizeOnly;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmZ;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmZ_SizeOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmAddr;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmAddr_SizeOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmAddrF;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmAddrF_SizeOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseFixedReg;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmUlong;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmUlong_SizeOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmQword;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmQword_SizeOnly;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncstatic FNDISPARSE ParseInvOpModRm;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncstatic FNDISPARSE ParseTwoByteEsc;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncstatic FNDISPARSE ParseThreeByteEsc4;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncstatic FNDISPARSE ParseThreeByteEsc5;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncstatic FNDISPARSE ParseImmGrpl;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseShiftGrp2;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseGrp3;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp4;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp5;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE Parse3DNow;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp6;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp7;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp8;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp9;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp10;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp12;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp13;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp14;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp15;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseGrp16;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsyncstatic FNDISPARSE ParseModFence;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsyncstatic FNDISPARSE ParseNopPause;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseYv;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseYb;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseXv;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseXb;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/** Floating point parsing */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic FNDISPARSE ParseEscFP;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/** @} */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/*******************************************************************************
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync* Global Variables *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Parser opcode table for full disassembly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseIllegal,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseModRM,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync UseModRM,
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync ParseImmByte,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmBRel,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmUshort,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmV,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmVRel,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmAddr,
21029597fc4b76d0db0c9542daee201447281781vboxsync ParseFixedReg,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmUlong,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmQword,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseTwoByteEsc,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmGrpl,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseShiftGrp2,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseGrp3,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseGrp4,
c0a370e600bb60153a269fb32b5f709347c35768vboxsync ParseGrp5,
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync Parse3DNow,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseGrp6,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp7,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp8,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp9,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp10,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp12,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp13,
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync ParseGrp14,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseGrp15,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseGrp16,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseModFence,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseYv,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseYb,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseXv,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseXb,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseEscFP,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseNopPause,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseImmByteSX,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmZ,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseThreeByteEsc4,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseThreeByteEsc5,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmAddrF,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseInvOpModRm
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync};
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/** Parser opcode table for only calculating instruction size. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseIllegal,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseModRM_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync UseModRM,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmByte_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmBRel_SizeOnly,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmUshort_SizeOnly,
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync ParseImmV_SizeOnly,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseImmVRel_SizeOnly,
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync ParseImmAddr_SizeOnly,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseFixedReg,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync ParseImmUlong_SizeOnly,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync ParseImmQword_SizeOnly,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseTwoByteEsc,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync ParseImmGrpl,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseShiftGrp2,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ParseGrp3,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ParseGrp4,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ParseGrp5,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Parse3DNow,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp6,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync ParseGrp7,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp8,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync ParseGrp9,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp10,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp12,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp13,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp14,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp15,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp16,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseModFence,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseYv,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseYb,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseXv,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseXb,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseEscFP,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseNopPause,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmByteSX_SizeOnly,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmZ_SizeOnly,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseThreeByteEsc4,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseThreeByteEsc5,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmAddrF_SizeOnly,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseInvOpModRm
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync};
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/********************************************************************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Read functions for getting the opcode bytes
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ********************************************************************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync#ifdef IN_RING0
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_BZERO(&pDis->abInstr[offInstr], cbMaxRead);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->cbCachedInstr = offInstr + cbMaxRead;
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VERR_DIS_NO_READ_CALLBACK;
16a9adc14900ca18e6909679a579f6833425e030vboxsync#else
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr;
16a9adc14900ca18e6909679a579f6833425e030vboxsync size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t cbToRead = cbLeftOnPage >= cbMaxRead
16a9adc14900ca18e6909679a579f6833425e030vboxsync ? cbMaxRead
16a9adc14900ca18e6909679a579f6833425e030vboxsync : cbLeftOnPage <= cbMinRead
16a9adc14900ca18e6909679a579f6833425e030vboxsync ? cbMinRead
16a9adc14900ca18e6909679a579f6833425e030vboxsync : (uint8_t)cbLeftOnPage;
16a9adc14900ca18e6909679a579f6833425e030vboxsync memcpy(&pDis->abInstr[offInstr], pbSrc, cbToRead);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->cbCachedInstr = offInstr + cbToRead;
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VINF_SUCCESS;
16a9adc14900ca18e6909679a579f6833425e030vboxsync#endif
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Read more bytes into the DISSTATE::abInstr buffer, advance
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * DISSTATE::cbCachedInstr.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Will set DISSTATE::rc on failure, but still advance cbCachedInstr.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * The caller shall fend off reads beyond the DISSTATE::abInstr buffer.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param pDis The disassembler state.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param offInstr The offset of the read request.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param cbMin The size of the read request that needs to be
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * satisfied.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncDECL_NO_INLINE(static, void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(cbMin + offInstr <= sizeof(pDis->abInstr));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /*
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Adjust the incoming request to not overlap with bytes that has already
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * been read and to make sure we don't leave unread gaps.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (offInstr < pDis->cbCachedInstr)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(offInstr + cbMin > pDis->cbCachedInstr);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync cbMin -= pDis->cbCachedInstr - offInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync offInstr = pDis->cbCachedInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (offInstr > pDis->cbCachedInstr)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync cbMin += offInstr - pDis->cbCachedInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync offInstr = pDis->cbCachedInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /*
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Do the read.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * (No need to zero anything on failure as abInstr is already zeroed by the
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * DISInstrEx API.)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (RT_SUCCESS(rc))
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync {
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync Assert(pDis->cbCachedInstr >= offInstr + cbMin);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync Log(("disReadMore failed with rc=%Rrc!!\n", rc));
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDis->rc = VERR_DIS_MEM_READ;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync
22ec733a5e041fcdfe02fce2eafc9faf8b0077ddvboxsync/**
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Function for handling a 8-bit cache miss.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns The requested byte.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis The disassembler state.
aa834e89e076db44fa8fe82d177748f0a45d14c2vboxsync * @param offInstr The offset of the byte relative to the
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * instruction.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (RT_UNLIKELY(offInstr >= DIS_MAX_INSTR_LENGTH))
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync {
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync Log(("disReadByte: too long instruction...\n"));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync disReadMore(pDis, (uint8_t)offInstr, 1);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return pDis->abInstr[offInstr];
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync/**
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * Read a byte (8-bit) instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested byte.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis The disassembler state.
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * @param uAddress The address.
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync */
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsyncDECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_UNLIKELY(offInstr >= pDis->cbCachedInstr))
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disReadByteSlow(pDis, offInstr);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return pDis->abInstr[offInstr];
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/**
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync * Function for handling a 16-bit cache miss.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns The requested word.
ffbe6daf773e38167f3cabaf1f063d84ecd063e9vboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the word relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync */
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsyncDECL_NO_INLINE(static, uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr + 2 > DIS_MAX_INSTR_LENGTH))
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
adefd5e9babba486cba0cfae52f5a0f6c8c4ef24vboxsync Log(("disReadWord: too long instruction...\n"));
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync if (offInstr < DIS_MAX_INSTR_LENGTH)
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync return pDis->abInstr[offInstr];
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return 0;
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync }
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync disReadMore(pDis, (uint8_t)offInstr, 2);
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync return *(uint16_t const *)&pDis->abInstr[offInstr];
adefd5e9babba486cba0cfae52f5a0f6c8c4ef24vboxsync#else
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync#endif
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/**
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * Read a word (16-bit) instruction.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync *
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * @returns The requested word.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * @param pDis The disassembler state.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * @param offInstr The offset of the qword relative to the
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * instruction.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync */
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsyncDECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync{
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync if (RT_UNLIKELY(offInstr + 2 > pDis->cbCachedInstr))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return disReadWordSlow(pDis, offInstr);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint16_t const *)&pDis->abInstr[offInstr];
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#else
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#endif
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Function for handling a 32-bit cache miss.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested dword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param offInstr The offset of the dword relative to the
16a9adc14900ca18e6909679a579f6833425e030vboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncDECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr + 4 > DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Log(("disReadDWord: too long instruction...\n"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync switch ((RTUINTPTR)DIS_MAX_INSTR_LENGTH - offInstr)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync case 1:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync case 2:
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
16a9adc14900ca18e6909679a579f6833425e030vboxsync case 3:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync disReadMore(pDis, (uint8_t)offInstr, 4);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint32_t const *)&pDis->abInstr[offInstr];
9496f2d398b49813176939d7a339ae513d5175efvboxsync#else
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#endif
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync/**
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * Read a dword (32-bit) instruction.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync *
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * @returns The requested dword.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * @param pDis The disassembler state.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync if (RT_UNLIKELY(offInstr + 4 > pDis->cbCachedInstr))
9496f2d398b49813176939d7a339ae513d5175efvboxsync return disReadDWordSlow(pDis, offInstr);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return *(uint32_t const *)&pDis->abInstr[offInstr];
9496f2d398b49813176939d7a339ae513d5175efvboxsync#else
16a9adc14900ca18e6909679a579f6833425e030vboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync#endif
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync/**
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Function for handling a 64-bit cache miss.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested qword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncDECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (RT_UNLIKELY(offInstr + 8 > DIS_MAX_INSTR_LENGTH))
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync {
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync Log(("disReadQWord: too long instruction...\n"));
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync switch ((RTUINTPTR)DIS_MAX_INSTR_LENGTH - offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case 1:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case 2:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync case 3:
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDis->abInstr[offInstr + 2], 0, 0, 0, 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case 4:
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 4], 0, 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case 5:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5], 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case 6:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync return 0;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync }
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync disReadMore(pDis, (uint8_t)offInstr, 8);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync#else
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync#endif
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync/**
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Read a qword (64-bit) instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested qword.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param uAddress The address.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncDECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync{
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (RT_UNLIKELY(offInstr + 8 > pDis->cbCachedInstr))
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return disReadQWordSlow(pDis, offInstr);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
9496f2d398b49813176939d7a339ae513d5175efvboxsync#else
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#endif
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync//*****************************************************************************
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync//*****************************************************************************
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncstatic size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync{
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync Assert(pOp); Assert(pDis);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync // Store the opcode format string for disasmPrintf
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->pCurInstr = pOp;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /*
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Note! Multibyte opcodes are always marked harmless until the final byte.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync bool fFiltered;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if ((pOp->fOpType & pDis->fFilter) == 0)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync fFiltered = true;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->pfnDisasmFnTable = g_apfnCalcSize;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync /* Not filtered out -> full disassembly */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync fFiltered = false;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->pfnDisasmFnTable = g_apfnFullDisasm;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync }
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync // Should contain the parameter type on input
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->Param1.fParam = pOp->fParam1;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->Param2.fParam = pOp->fParam2;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->Param3.fParam = pOp->fParam3;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (pOp->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->uOpMode = DISCPUMODE_64BIT;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync else
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync if ( (pOp->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync && !(pDis->fPrefix & DISPREFIX_OPSIZE))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->uOpMode = DISCPUMODE_64BIT;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
16a9adc14900ca18e6909679a579f6833425e030vboxsync Assert(pDis->uCpuMode != DISCPUMODE_64BIT);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_32BIT;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->idxParse1 != IDX_ParseNop)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->idxParse2 != IDX_ParseNop)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->idxParse3 != IDX_ParseNop)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync // else simple one byte instruction
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync/* Floating point opcode parsing */
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync PCDISOPCODE fpop;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync NOREF(pOp);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync uint8_t index = pDis->bOpCode - 0xD8;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (ModRM <= 0xBF)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync {
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pDis->pCurInstr = fpop;
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync // Should contain the parameter type on input
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pDis->Param1.fParam = fpop->fParam1;
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync pDis->Param2.fParam = fpop->fParam2;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync else
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync {
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync fpop = &(g_apMapX86_FP_High[index])[ModRM - 0xC0];
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pDis->pCurInstr = fpop;
efff36b306e370346025647a158689021df2e1d1vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Apply filter to instruction type to determine if a full disassembly is required.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if ((fpop->fOpType & pDis->fFilter) == 0)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pDis->pfnDisasmFnTable = g_apfnCalcSize;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync else
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* Not filtered out -> full disassembly */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pDis->pfnDisasmFnTable = g_apfnFullDisasm;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Note: redundant, but just in case this ever changes */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fpop->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->uOpMode = DISCPUMODE_64BIT;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && !(pDis->fPrefix & DISPREFIX_OPSIZE))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->uOpMode = DISCPUMODE_64BIT;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // Little hack to make sure the ModRM byte is included in the returned size
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++; //ModRM byte
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fpop->idxParse1 != IDX_ParseNop)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fpop->idxParse2 != IDX_ParseNop)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/********************************************************************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * SIB byte: (not 16-bit mode)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * 7 - 6 5 - 3 2-0
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Scale Index Base
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync ********************************************************************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync unsigned scale = pDis->SIB.Bits.Scale;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned base = pDis->SIB.Bits.Base;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unsigned index = pDis->SIB.Bits.Index;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned regtype;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync regtype = DISUSE_REG_GEN32;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync regtype = DISUSE_REG_GEN64;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (index != 4)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_INDEX | regtype;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->Index.idxGenReg = index;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (scale != 0)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_SCALE;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->uScale = (1<<scale);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (base == 5 && pDis->ModRM.Bits.Mod == 0)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // [scaled index] + disp32
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_DISPLACEMENT32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->uDisp.i32 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { /* sign-extend to 64 bits */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_DISPLACEMENT64;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->uDisp.i64 = pDis->i32SibDisp;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_BASE | regtype;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->Base.idxGenReg = base;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return; /* Already fetched everything in ParseSIB; no size returned */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pOp); NOREF(pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t SIB = disReadByte(pDis, offInstr);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr++;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Base = SIB_BASE(SIB);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Index = SIB_INDEX(SIB);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->fPrefix & DISPREFIX_REX)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Base field if not scaled index + disp32 */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if ( pDis->SIB.Bits.Base == 5
251b3801f86afc901bee955a7e5a8d14b5836e74vboxsync && pDis->ModRM.Bits.Mod == 0)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Additional 32 bits displacement. No change in long mode. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->i32SibDisp = disReadDWord(pDis, offInstr);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr += 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return offInstr;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NOREF(pOp); NOREF(pParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t SIB = disReadByte(pDis, offInstr);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr++;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Base = SIB_BASE(SIB);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index = SIB_INDEX(SIB);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->fPrefix & DISPREFIX_REX)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Base field. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Base |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.X extends the Index field. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if ( pDis->SIB.Bits.Base == 5
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync && pDis->ModRM.Bits.Mod == 0)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Additional 32 bits displacement. No change in long mode. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr += 4;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return offInstr;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/********************************************************************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * ModR/M byte:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * 7 - 6 5 - 3 2-0
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Mod Reg/Opcode R/M
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
59a2c1c0a4a0762b46bc5ff056f5705ec9c0a660vboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ********************************************************************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void disasmModRMReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, int fRegAddr)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NOREF(pOp); NOREF(pDis);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned mod = pDis->ModRM.Bits.Mod;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned type = OP_PARM_VTYPE(pParam->fParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fRegAddr)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync switch (pDis->uOpMode)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case DISCPUMODE_32BIT:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync subtype = OP_PARM_d;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case DISCPUMODE_64BIT:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync subtype = OP_PARM_q;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case DISCPUMODE_16BIT:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync subtype = OP_PARM_w;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync default:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* make gcc happy */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (subtype)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case OP_PARM_b:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Intel� 64 and IA-32 Architectures Software Developer�s Manual: 3.4.1.1 */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if ( (pDis->fPrefix & DISPREFIX_REX)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync && idx >= DISGREG_AH
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync && idx <= DISGREG_BH)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync idx += (DISGREG_SPL - DISGREG_AH);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_GEN8;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pParam->Base.idxGenReg = idx;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync break;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync case OP_PARM_w:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pParam->fUse |= DISUSE_REG_GEN16;
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync pParam->Base.idxGenReg = idx;
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync break;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync case OP_PARM_d:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pParam->fUse |= DISUSE_REG_GEN32;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pParam->Base.idxGenReg = idx;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync break;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync case OP_PARM_q:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_REG_GEN64;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxGenReg = idx;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync default:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->rc = VERR_DIS_INVALID_MODRM;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsyncstatic void disasmModRMReg16(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync{
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync static const uint8_t s_auBaseModRMReg16[8] =
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX };
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pDis); NOREF(pOp);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_GEN16;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync pParam->Base.idxGenReg = s_auBaseModRMReg16[idx];
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (idx < 4)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync static const uint8_t s_auIndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI };
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_INDEX;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Index.idxGenReg = s_auIndexModRMReg16[idx];
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsyncstatic void disasmModRMSReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync{
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync NOREF(pOp);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (idx >= DISSELREG_END)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync Log(("disasmModRMSReg %d failed!!\n", idx));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pDis->rc = VERR_DIS_INVALID_PARAMETER;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync return;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_SEG;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Base.idxSegReg = (DISSELREG)idx;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic size_t UseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync{
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync unsigned vtype = OP_PARM_VTYPE(pParam->fParam);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync uint8_t reg = pDis->ModRM.Bits.Reg;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync uint8_t mod = pDis->ModRM.Bits.Mod;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync uint8_t rm = pDis->ModRM.Bits.Rm;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync switch (vtype)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_G: //general purpose register
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync disasmModRMReg(reg, pOp, pDis, pParam, 0);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync default:
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if (IS_OP_PARM_RARE(vtype))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync switch (vtype)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync case OP_PARM_C: //control register
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_CR;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if ( pDis->pCurInstr->uOpcode == OP_MOV_CR
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync && pDis->uOpMode == DISCPUMODE_32BIT
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync && (pDis->fPrefix & DISPREFIX_LOCK))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pDis->fPrefix &= ~DISPREFIX_LOCK;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Base.idxCtrlReg = DISCREG_CR8;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Base.idxCtrlReg = reg;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync return offInstr;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync case OP_PARM_D: //debug register
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_DBG;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxDbgReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_P: //MMX register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg &= 7; /* REX.R has no effect here */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_MMX;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxMmxReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_S: //segment register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg &= 7; /* REX.R has no effect here */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMSReg(reg, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_SEG;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync case OP_PARM_T: //test register
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync reg &= 7; /* REX.R has no effect here */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_REG_TEST;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxTestReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_W: //XMM register or memory operand
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (mod != 3)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break; /* memory operand */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg = rm; /* the RM field specifies the xmm register */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else no break */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_V: //XMM register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_XMM;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxXmmReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /** @todo bound */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uAddrMode != DISCPUMODE_16BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 4) /* SIB byte follows ModRM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync UseSIB(pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 5)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uCpuMode != DISCPUMODE_64BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_DISPLACEMENT32;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i32 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_RIPDISPLACEMENT32;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i32 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { //register address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg(rm, pOp, pDis, pParam, 1);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: //effective address + 8 bits displacement
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 4) /* SIB byte follows ModRM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync UseSIB(pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg(rm, pOp, pDis, pParam, 1);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i8 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_DISPLACEMENT8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: //effective address + 32 bits displacement
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 4) /* SIB byte follows ModRM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync UseSIB(pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg(rm, pOp, pDis, pParam, 1);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i32 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_DISPLACEMENT32;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case 3: //registers
b0b15690f00527424b2d5fb88456d747252322f7vboxsync disasmModRMReg(rm, pOp, pDis, pParam, 0);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync break;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {//16 bits addressing mode
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 6)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {//16 bits displacement
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i16 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_DISPLACEMENT16;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg16(rm, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case 1: //effective address + 8 bits displacement
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg16(rm, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i8 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: //effective address + 16 bits displacement
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg16(rm, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uDisp.i16 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT16;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 3: //registers
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync disasmModRMReg(rm, pOp, pDis, pParam, 0);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync// Query the size of the ModRM parameters and fetch the immediate data (if any)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t QueryModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t mod = pDis->ModRM.Bits.Mod;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t rm = pDis->ModRM.Bits.Rm;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uAddrMode != DISCPUMODE_16BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
51a01524909c95ee04b636218b6a89b29fb81825vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (mod != 3 && rm == 4) /* SIB byte follows ModRM */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr = ParseSIB(offInstr, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case 0: /* Effective address */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (rm == 5) /* 32 bits displacement */
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = disReadDWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = disReadDWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 3: /* registers */
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 16 bits mode */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: /* Effective address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 6)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = disReadWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = (int16_t)disReadWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 3: /* registers */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync// Parse the ModRM parameters and fetch the immediate data (if any)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t QueryModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t mod = pDis->ModRM.Bits.Mod;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t rm = pDis->ModRM.Bits.Rm;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uAddrMode != DISCPUMODE_16BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
51a01524909c95ee04b636218b6a89b29fb81825vboxsync */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (mod != 3 && rm == 4)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync { /* SIB byte follows ModRM */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr = ParseSIB_SizeOnly(offInstr, pOp, pDis, pParam);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync switch (mod)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 0: //effective address
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (rm == 5) /* 32 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr += 4;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* else register address */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 1: /* Effective address + 8 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr += 1;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 2: /* Effective address + 32 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr += 4;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 3: /* registers */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 16 bits mode */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 6)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 3: /* registers */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AssertFailed();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncstatic size_t ParseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
217fa436516d137a409bb493cb7d350898f64666vboxsync pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
217fa436516d137a409bb493cb7d350898f64666vboxsync pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* Disregard the mod bits for certain instructions (mov crx, mov drx).
51a01524909c95ee04b636218b6a89b29fb81825vboxsync *
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * From the AMD manual:
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * encoding of the MOD field in the MODR/M byte.
51a01524909c95ee04b636218b6a89b29fb81825vboxsync */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->ModRM.Bits.Mod = 3;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (pDis->fPrefix & DISPREFIX_REX)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* REX.R extends the Reg field. */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!( pDis->ModRM.Bits.Mod != 3
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && pDis->ModRM.Bits.Rm == 4)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync &&
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync !( pDis->ModRM.Bits.Mod == 0
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && pDis->ModRM.Bits.Rm == 5))
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = QueryModRM(offInstr, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return UseModRM(offInstr, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
51a01524909c95ee04b636218b6a89b29fb81825vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Disregard the mod bits for certain instructions (mov crx, mov drx).
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * From the AMD manual:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
217fa436516d137a409bb493cb7d350898f64666vboxsync * encoding of the MOD field in the MODR/M byte.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Mod = 3;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->fPrefix & DISPREFIX_REX)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.R extends the Reg field. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!( pDis->ModRM.Bits.Mod != 3
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && pDis->ModRM.Bits.Rm == 4)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync &&
b0b15690f00527424b2d5fb88456d747252322f7vboxsync !( pDis->ModRM.Bits.Mod == 0
b0b15690f00527424b2d5fb88456d747252322f7vboxsync && pDis->ModRM.Bits.Rm == 5))
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync offInstr += QueryModRM_SizeOnly(offInstr, pOp, pDis, pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* UseModRM is not necessary here; we're only interested in the opcode size */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseModFence(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* Note! Only used in group 15, so we must account for the mod/rm byte. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 1;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByte(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE8;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint8_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 1;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByte_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 1;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByteSX(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = (uint32_t)(int8_t)disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE32_SX8;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint32_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync else
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = (uint64_t)(int8_t)disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE64_SX8;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint64_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync else
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = (uint16_t)(int8_t)disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE16_SX8;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint16_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 1;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByteSX_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 1;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUshort(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = disReadWord(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE16;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint16_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 2;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUshort_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 2;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUlong(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE32;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint32_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 4;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUlong_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 4;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmQword(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = disReadQWord(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE64;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint64_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 8;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmQword_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 8;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmV(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pOp);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE32;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint32_t);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return offInstr + 4;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = disReadQWord(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE64;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->cb = sizeof(uint64_t);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uValue = disReadWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_IMMEDIATE16;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->cb = sizeof(uint16_t);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseImmV_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmZ(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pOp);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (pDis->uOpMode == DISCPUMODE_16BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = disReadWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_IMMEDIATE16;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint16_t);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return offInstr + 2;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* 64 bits op mode means *sign* extend to 64 bits. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_IMMEDIATE64;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->cb = sizeof(uint64_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync else
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_IMMEDIATE32;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->cb = sizeof(uint32_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 4;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmZ_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uOpMode == DISCPUMODE_16BIT)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return sizeof(uint16_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 4;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync// Relative displacement for branches (rel. to next instruction)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmBRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pOp);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = disReadByte(pDis, offInstr);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pParam->fUse |= DISUSE_IMMEDIATE8_REL;
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync pParam->cb = sizeof(uint8_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 1;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// Relative displacement for branches (rel. to next instruction)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmBRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync{
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return offInstr + 1;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync// Relative displacement for branches (rel. to next instruction)
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmVRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pOp);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_IMMEDIATE32_REL;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->cb = sizeof(int32_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 4;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 32 bits relative immediate sign extended to 64 bits. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->fUse |= DISUSE_IMMEDIATE64_REL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->cb = sizeof(int64_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->uValue = disReadWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_IMMEDIATE16_REL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->cb = sizeof(int16_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmVRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uOpMode == DISCPUMODE_16BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Both 32 & 64 bits mode use 32 bits relative immediates. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 4;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmAddr(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* far 16:32 pointer */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 4 + 2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /*
16a9adc14900ca18e6909679a579f6833425e030vboxsync * near 32 bits pointer
16a9adc14900ca18e6909679a579f6833425e030vboxsync *
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
16a9adc14900ca18e6909679a579f6833425e030vboxsync * so we treat it like displacement.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->uDisp.i32 = disReadDWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_DISPLACEMENT32;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->cb = sizeof(uint32_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 4;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * near 64 bits pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * so we treat it like displacement.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->uDisp.i64 = disReadQWord(pDis, offInstr);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->fUse |= DISUSE_DISPLACEMENT64;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint64_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 8;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* far 16:16 pointer */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->uValue = disReadDWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = 2*sizeof(uint16_t);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return offInstr + 4;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /*
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * near 16 bits pointer
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync *
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * so we treat it like displacement.
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->uDisp.i16 = disReadWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_DISPLACEMENT16;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint16_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 2;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(offInstr); NOREF(pOp);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 4 + 2; /* far 16:32 pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4; /* near 32 bits pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 8;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync return offInstr + 4; /* far 16:16 pointer */
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync return offInstr + 2; /* near 16 bits pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync{
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // far 16:32 pointer
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4 + 2;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // far 16:16 pointer
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->uValue = disReadDWord(pDis, offInstr);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->cb = 2*sizeof(uint16_t);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return offInstr + 2 + 2;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync}
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync NOREF(offInstr); NOREF(pOp);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // immediate far pointers - only 16:16 or 16:32
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4 + 2; /* far 16:32 pointer */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return offInstr + 2 + 2; /* far 16:16 pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync}
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync NOREF(offInstr);
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Sets up flags for stored in OPC fixed registers.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pParam->fParam == OP_PARM_NONE)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* No parameter at all. */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync if (pParam->fParam <= OP_PARM_REG_GEN32_END)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync {
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync /* 32-bit EAX..EDI registers. */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync /* Use 32-bit registers. */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync pParam->fUse |= DISUSE_REG_GEN32;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync pParam->cb = 4;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync /* Use 64-bit registers. */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
7a3f491705173bc08122f2c7d26d48a8b4c5ceecvboxsync if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync && (pDis->fPrefix & DISPREFIX_REX)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg += 8;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN64;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->cb = 8;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync /* Use 16-bit registers. */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pParam->fUse |= DISUSE_REG_GEN16;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->cb = 2;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (pParam->fParam <= OP_PARM_REG_SEG_END)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Segment ES..GS registers. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync pParam->fUse |= DISUSE_REG_SEG;
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync pParam->cb = 2;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (pParam->fParam <= OP_PARM_REG_GEN16_END)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* 16-bit AX..DI registers. */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN16_START;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN16;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->cb = 2;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (pParam->fParam <= OP_PARM_REG_GEN8_END)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* 8-bit AL..DL, AH..DH registers. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->fUse |= DISUSE_REG_GEN8;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->cb = 1;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync && (pDis->fPrefix & DISPREFIX_REX)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync else
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync if (pParam->fParam <= OP_PARM_REG_FP_END)
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* FPU registers. */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_FP;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pParam->cb = 10;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* else - not supported for now registers. */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return offInstr;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync NOREF(pOp);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync pParam->fUse |= DISUSE_POINTER_DS_BASED;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_ESI;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync pParam->fUse |= DISUSE_REG_GEN32;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_RSI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN64;
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync }
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync else
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync {
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync pParam->Base.idxGenReg = DISGREG_SI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN16;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync return offInstr;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync}
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncstatic size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync NOREF(pOp);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->fUse |= DISUSE_POINTER_DS_BASED;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->Base.idxGenReg = DISGREG_ESI;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->fUse |= DISUSE_REG_GEN32;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync else
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->Base.idxGenReg = DISGREG_RSI;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->fUse |= DISUSE_REG_GEN64;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync else
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->Base.idxGenReg = DISGREG_SI;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->fUse |= DISUSE_REG_GEN16;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync return offInstr;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync{
009d45aa55691312278d41edb20154dc208d9cd8vboxsync NOREF(pOp);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_POINTER_ES_BASED;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_EDI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN32;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_RDI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN64;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_DI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN16;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return offInstr;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync{
009d45aa55691312278d41edb20154dc208d9cd8vboxsync NOREF(pOp);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_POINTER_ES_BASED;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_EDI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN32;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = DISGREG_RDI;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->fUse |= DISUSE_REG_GEN64;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->Base.idxGenReg = DISGREG_DI;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pParam->fUse |= DISUSE_REG_GEN16;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync return offInstr;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync}
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncstatic size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync /* This is used to avoid a bunch of special hacks to get the ModRM byte
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync included when encountering invalid opcodes in groups. */
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync return offInstr + 1;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync}
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncstatic size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync NOREF(pOp); NOREF(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 2nd byte */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->bOpCode = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync offInstr++;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* default to the non-prefixed table. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
9daee41d5cb5a2e8390f015a486e67a6cd52b836vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync if (pDis->bLastPrefix)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync switch (pDis->bLastPrefix)
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync {
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync case OP_OPSIZE: /* 0x66 */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Table entry is valid, so use the extension table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpcode = &g_aTwoByteMapX86_PF66[pDis->bOpCode];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->uOpMode = pDis->uCpuMode;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_REPNE: /* 0xF2 */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = &g_aTwoByteMapX86_PFF2[pDis->bOpCode];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->fPrefix &= ~DISPREFIX_REPNE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_REPE: /* 0xF3 */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = &g_aTwoByteMapX86_PFF3[pDis->bOpCode];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->fPrefix &= ~DISPREFIX_REP;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pOp); NOREF(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 3rd byte */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->bOpCode = disReadByte(pDis, offInstr);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync offInstr++;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* default to the non-prefixed table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PCDISOPCODE pOpcode;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4])
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = &g_InvalidOpcode[0];
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync switch (pDis->bLastPrefix)
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync {
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync case OP_OPSIZE: /* 0x66 */
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync {
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pOpcode->uOpcode != OP_INVALID)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->uOpMode = pDis->uCpuMode;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_REPNE: /* 0xF2 */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pOpcode->uOpcode != OP_INVALID)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync /* Table entry is valid, so use the extension table. */
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync /* Cancel prefix changes. */
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync pDis->fPrefix &= ~DISPREFIX_REPNE;
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync }
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync }
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync break;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pOp); NOREF(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 3rd byte */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->bOpCode = disReadByte(pDis, offInstr);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync offInstr++;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(pDis->bLastPrefix == OP_OPSIZE);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* default to the non-prefixed table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync PCDISOPCODE pOpcode;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pOpcode->uOpcode != OP_INVALID)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Table entry is valid, so use the extension table. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync /* Cancel prefix changes. */
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync pDis->uOpMode = pDis->uCpuMode;
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync }
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync }
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync else
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pOpcode = &g_InvalidOpcode[0];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pDis->fPrefix & DISPREFIX_REP)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pDis->fPrefix &= ~DISPREFIX_REP;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOp = &g_aMapX86_NopPause[0]; /* NOP */
c7ff622115966b69b482bd2896662e40d823b22fvboxsync
c7ff622115966b69b482bd2896662e40d823b22fvboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t reg = MODRM_REG(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync unsigned idx = (pDis->bOpCode - 0x80) * 8;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group1[idx+reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return disParseInstruction(offInstr, pOp, pDis);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync unsigned idx;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync switch (pDis->bOpCode)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case 0xC0:
76364cddabfeb143dad91862d41a5638d8860b25vboxsync case 0xC1:
76364cddabfeb143dad91862d41a5638d8860b25vboxsync idx = (pDis->bOpCode - 0xC0)*8;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync break;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync
76364cddabfeb143dad91862d41a5638d8860b25vboxsync case 0xD0:
76364cddabfeb143dad91862d41a5638d8860b25vboxsync case 0xD1:
76364cddabfeb143dad91862d41a5638d8860b25vboxsync case 0xD2:
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync case 0xD3:
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync idx = (pDis->bOpCode - 0xD0 + 2)*8;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync break;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync default:
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync pDis->rc = VERR_DIS_INVALID_OPCODE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return offInstr;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t reg = MODRM_REG(modrm);
cba6719bd64ec749967bbe931230452664109857vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOp = &g_aMapX86_Group2[idx+reg];
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync return disParseInstruction(offInstr, pOp, pDis);
cba6719bd64ec749967bbe931230452664109857vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync unsigned idx = (pDis->bOpCode - 0xF6) * 8;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync NOREF(pParam);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync uint8_t reg = MODRM_REG(modrm);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync pOp = &g_aMapX86_Group3[idx+reg];
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disParseInstruction(offInstr, pOp, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync NOREF(pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
090d729e786b999dc285f8ea267f9effd1319544vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync uint8_t reg = MODRM_REG(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group4[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disParseInstruction(offInstr, pOp, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync uint8_t reg = MODRM_REG(modrm);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pOp = &g_aMapX86_Group5[reg];
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync return disParseInstruction(offInstr, pOp, pDis);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync// It would appear the ModRM byte must always be present. How else can you
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync// determine the offset of the imm8_opcode byte otherwise?
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync//
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** @todo This code needs testing! */
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync uint8_t opcode = disReadByte(pDis, offRet);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync offRet++;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync pOp = &g_aTwoByteMapX86_3DNow[opcode];
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync Assert(offStrict == offRet - 1); NOREF(offStrict); /* the imm8_opcode */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync return offRet;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync uint8_t reg = MODRM_REG(modrm);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync pOp = &g_aMapX86_Group6[reg];
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disParseInstruction(offInstr, pOp, pDis);
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync}
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync//*****************************************************************************
090d729e786b999dc285f8ea267f9effd1319544vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t mod = MODRM_MOD(modrm);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync uint8_t reg = MODRM_REG(modrm);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync uint8_t rm = MODRM_RM(modrm);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync if (mod == 3 && rm == 0)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pOp = &g_aMapX86_Group7_mod11_rm000[reg];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (mod == 3 && rm == 1)
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync pOp = &g_aMapX86_Group7_mod11_rm001[reg];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOp = &g_aMapX86_Group7_mem[reg];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync /* Cannot easily skip this hack because of monitor and vmcall! */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync //little hack to make sure the ModRM byte is included in the returned size
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr++;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disParseInstruction(offInstr, pOp, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pParam);
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync uint8_t modrm = disReadByte(pDis, offInstr);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync uint8_t reg = MODRM_REG(modrm);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOp = &g_aMapX86_Group8[reg];
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync return disParseInstruction(offInstr, pOp, pDis);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync}
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncstatic size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync{
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync NOREF(pParam);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync uint8_t modrm = disReadByte(pDis, offInstr);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync uint8_t reg = MODRM_REG(modrm);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pOp = &g_aMapX86_Group9[reg];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return disParseInstruction(offInstr, pOp, pDis);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync}
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync{
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync NOREF(pParam);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync uint8_t reg = MODRM_REG(modrm);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync pOp = &g_aMapX86_Group10[reg];
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync return disParseInstruction(offInstr, pOp, pDis);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync}
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync{
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync NOREF(pParam);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync uint8_t modrm = disReadByte(pDis, offInstr);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync uint8_t reg = MODRM_REG(modrm);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->fPrefix & DISPREFIX_OPSIZE)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync reg += 8; /* 2nd table */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOp = &g_aMapX86_Group12[reg];
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return disParseInstruction(offInstr, pOp, pDis);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync}
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync//*****************************************************************************
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync//*****************************************************************************
61d064a54f03596920c3918f58ecc7764074a5d8vboxsyncstatic size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync{
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync NOREF(pParam);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
44fc72ff17b23a9b970505fcf8d6da1019ddcec5vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync uint8_t reg = MODRM_REG(modrm);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync if (pDis->fPrefix & DISPREFIX_OPSIZE)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync reg += 8; /* 2nd table */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync pOp = &g_aMapX86_Group13[reg];
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t reg = MODRM_REG(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->fPrefix & DISPREFIX_OPSIZE)
16a9adc14900ca18e6909679a579f6833425e030vboxsync reg += 8; /* 2nd table */
16a9adc14900ca18e6909679a579f6833425e030vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pOp = &g_aMapX86_Group14[reg];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOp, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pParam);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync uint8_t mod = MODRM_MOD(modrm);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync uint8_t reg = MODRM_REG(modrm);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync uint8_t rm = MODRM_RM(modrm);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (mod == 3 && rm == 0)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pOp = &g_aMapX86_Group15_mod11_rm000[reg];
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pOp = &g_aMapX86_Group15_mem[reg];
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return disParseInstruction(offInstr, pOp, pDis);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync}
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync//*****************************************************************************
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync//*****************************************************************************
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsyncstatic size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync{
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync NOREF(pParam);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync return disParseInstruction(offInstr, pOp, pDis);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync}
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync/**
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * Validates the lock sequence.
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync *
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * The AMD manual lists the following instructions:
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * ADC
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * ADD
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * AND
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * BTC
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * BTR
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * BTS
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * CMPXCHG
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * CMPXCHG8B
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * CMPXCHG16B
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * DEC
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * INC
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * NEG
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * NOT
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * OR
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * SBB
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * SUB
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * XADD
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * XCHG
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * XOR
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync *
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * @param pDis Fully disassembled instruction.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync */
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsyncstatic void disValidateLockSequence(PDISSTATE pDis)
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync{
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync Assert(pDis->fPrefix & DISPREFIX_LOCK);
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync /*
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * Filter out the valid lock sequences.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync */
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync switch (pDis->pCurInstr->uOpcode)
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync {
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync /* simple: no variations */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync return;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /* simple: /r - reject register destination. */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_BTC:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_BTR:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_BTS:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_CMPXCHG:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_XADD:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync if (pDis->ModRM.Bits.Mod == 3)
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync break;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync return;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /*
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * Lots of variants but its sufficient to check that param 1
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * is a memory operand.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_ADC:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_ADD:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_AND:
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync case OP_DEC:
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync case OP_INC:
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync case OP_NEG:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_NOT:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_OR:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_SBB:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_SUB:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_XCHG:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_XOR:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
16a9adc14900ca18e6909679a579f6833425e030vboxsync return;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync default:
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync break;
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync }
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync /*
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync * Invalid lock sequence, make it a OP_ILLUD2.
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync */
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync pDis->pCurInstr = &g_aTwoByteMapX86[11];
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync}
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync/**
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync * Internal worker for DISInstEx.
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync *
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync * @returns VBox status code.
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync * @param pDis Initialized disassembler state.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param paOneByteMap The one byte opcode map to use.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pcbInstr Where to store the instruction size. Can be NULL.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync /*
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Parse byte by byte.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync size_t offInstr = 0;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync for (;;)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync uint8_t codebyte = disReadByte(pDis, offInstr++);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync uint8_t opcode = paOneByteMap[codebyte].uOpcode;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Hardcoded assumption about OP_* values!! */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (opcode <= OP_LAST_PREFIX)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (opcode != OP_REX)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pDis->bLastPrefix = opcode;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync pDis->fPrefix &= ~DISPREFIX_REX;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync }
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync switch (opcode)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_INVALID:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pcbInstr)
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync *pcbInstr = (uint32_t)offInstr;
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return pDis->rc = VERR_DIS_INVALID_OPCODE;
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync // segment override prefix byte
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync case OP_SEG:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if ( pDis->uCpuMode != DISCPUMODE_64BIT
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync || pDis->idxSegPrefix >= DISSELREG_FS)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync pDis->fPrefix |= DISPREFIX_SEG;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync continue; //fetch the next byte
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // lock prefix byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_LOCK:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->fPrefix |= DISPREFIX_LOCK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync continue; //fetch the next byte
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // address size override prefix byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_ADDRSIZE:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->fPrefix |= DISPREFIX_ADDRSIZE;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->uCpuMode == DISCPUMODE_16BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->uAddrMode = DISCPUMODE_32BIT;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync if (pDis->uCpuMode == DISCPUMODE_32BIT)
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pDis->uAddrMode = DISCPUMODE_16BIT;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync else
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pDis->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync continue; //fetch the next byte
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync // operand size override prefix byte
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync case OP_OPSIZE:
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fPrefix |= DISPREFIX_OPSIZE;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uCpuMode == DISCPUMODE_16BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_32BIT;
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync // rep and repne are not really prefixes, but we'll treat them as such
16a9adc14900ca18e6909679a579f6833425e030vboxsync case OP_REPE:
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fPrefix |= DISPREFIX_REP;
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync case OP_REPNE:
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fPrefix |= DISPREFIX_REPNE;
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync case OP_REX:
16a9adc14900ca18e6909679a579f6833425e030vboxsync Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* REX prefix byte */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fPrefix |= DISPREFIX_REX;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* first opcode byte. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->bOpCode = codebyte;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->cbPrefix = (uint8_t)offInstr - 1;
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->cbInstr = (uint8_t)offInstr;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pcbInstr)
16a9adc14900ca18e6909679a579f6833425e030vboxsync *pcbInstr = (uint32_t)offInstr;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->fPrefix & DISPREFIX_LOCK)
16a9adc14900ca18e6909679a579f6833425e030vboxsync disValidateLockSequence(pDis);
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return pDis->rc;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Inlined worker that initializes the disassembler state.
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync *
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @returns The primary opcode map to use.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pDis The disassembler state.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param uInstrAddr The instruction address.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param enmCpuMode The CPU mode.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param fFilter The instruction filter settings.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pfnReadBytes The byte reader, can be NULL.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pvUser The the user data for the reader.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncDECL_FORCE_INLINE(PCDISOPCODE)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncdisInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PFNDISREADBYTES pfnReadBytes, void *pvUser)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync RT_ZERO(*pDis);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync#ifdef VBOX_STRICT /* poison */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.Base.idxGenReg = 0xc1;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.Base.idxGenReg = 0xc2;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.Base.idxGenReg = 0xc3;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.Index.idxGenReg = 0xc4;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.Index.idxGenReg = 0xc5;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.Index.idxGenReg = 0xc6;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.uScale = 28;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.uScale = 29;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.uScale = 30;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync#endif
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->fPrefix = DISPREFIX_NONE;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->idxSegPrefix = DISSELREG_DS;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->rc = VINF_SUCCESS;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->pfnDisasmFnTable = g_apfnFullDisasm;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->uInstrAddr = uInstrAddr;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->fFilter = fFilter;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->pvUser = pvUser;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->uCpuMode = enmCpuMode;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PCDISOPCODE paOneByteMap;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (enmCpuMode == DISCPUMODE_64BIT)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->uAddrMode = DISCPUMODE_64BIT;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->uOpMode = DISCPUMODE_32BIT;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync paOneByteMap = g_aOneByteMapX64;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync else
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->uAddrMode = enmCpuMode;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->uOpMode = enmCpuMode;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync paOneByteMap = g_aOneByteMapX86;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return paOneByteMap;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Reads some bytes into the cache.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * While this will set DISSTATE::rc on failure, the caller should disregard
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * this since that is what would happen if we didn't prefetch bytes prior to the
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * instruction parsing.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pDis The disassembler state.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncDECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /*
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Read some bytes into the cache. (If this fail we continue as nothing
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * has gone wrong since this is what would happen if we didn't precharge
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * the cache here.)
c0a370e600bb60153a269fb32b5f709347c35768vboxsync */
c0a370e600bb60153a269fb32b5f709347c35768vboxsync int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
c0a370e600bb60153a269fb32b5f709347c35768vboxsync if (RT_SUCCESS(rc))
c0a370e600bb60153a269fb32b5f709347c35768vboxsync {
c0a370e600bb60153a269fb32b5f709347c35768vboxsync Assert(pDis->cbCachedInstr >= 1);
c0a370e600bb60153a269fb32b5f709347c35768vboxsync Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync else
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync Log(("Initial read failed with rc=%Rrc!!\n", rc));
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->rc = VERR_DIS_MEM_READ;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @returns VBox status code.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param uInstrAddr Address of the instruction to decode. What this means
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * is left to the pfnReadBytes function.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param fFilter Instruction type filter.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pDis Pointer to disassembler state (output).
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pcbInstr Where to store the size of the instruction. (This
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * is also stored in PDISSTATE::cbInstr.) Optional.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncDISDECL(int) DISInstEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PFNDISREADBYTES pfnReadBytes, void *pvUser,
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync PDISSTATE pDis, uint32_t *pcbInstr)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disPrefetchBytes(pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disInstrWorker(pDis, paOneByteMap, pcbInstr);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync/**
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * Disassembles on instruction partially or fully from prefetched bytes, details
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * in @a pDis and length in @a pcbInstr.
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync *
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * @returns VBox status code.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param uInstrAddr Address of the instruction to decode. What this means
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * is left to the pfnReadBytes function.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pvPrefetched Pointer to the prefetched bytes.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param cbPrefetched The number of valid bytes pointed to by @a
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * pbPrefetched.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pfnReadBytes Callback for reading instruction bytes.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param fFilter Instruction type filter.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis Pointer to disassembler state (output).
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * @param pcbInstr Where to store the size of the instruction. (This
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * is also stored in PDISSTATE::cbInstr.) Optional.
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsyncDISDECL(int) DISInstWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync void const *pvPrefetched, size_t cbPretched,
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync PFNDISREADBYTES pfnReadBytes, void *pvUser,
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync PDISSTATE pDis, uint32_t *pcbInstr)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (!cbPretched)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync disPrefetchBytes(pDis);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync else
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync {
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync if (cbPretched >= sizeof(pDis->abInstr))
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync }
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync else
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync memcpy(pDis->abInstr, pvPrefetched, cbPretched);
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync pDis->cbCachedInstr = (uint8_t)cbPretched;
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync }
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync }
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return disInstrWorker(pDis, paOneByteMap, pcbInstr);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync}
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsync * Parses one guest instruction.
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * The result is found in pDis and pcbInstr.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @returns VBox status code.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param uInstrAddr Address of the instruction to decode. What this means
9496f2d398b49813176939d7a339ae513d5175efvboxsync * is left to the pfnReadBytes function.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @param pDis Pointer to disassembler state (output).
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pcbInstr Where to store the size of the instruction.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * NULL is allowed. This is also stored in
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * PDISSTATE::cbInstr.
76364cddabfeb143dad91862d41a5638d8860b25vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncDISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDISSTATE pDis, uint32_t *pcbInstr)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync return DISInstEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync}
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync/**
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * Parses one guest instruction.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync *
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * The result is found in pDis and pcbInstr.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @returns VBox status code.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pvInstr Address of the instruction to decode. This is a
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * real address in the current context that can be
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * accessed without faulting. (Consider
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * DISInstrWithReader if this isn't the case.)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pDis Pointer to disassembler state (output).
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pcbInstr Where to store the size of the instruction.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * NULL is allowed. This is also stored in
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * PDISSTATE::cbInstr.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncDISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return DISInstEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync