DisasmCore.cpp revision 03e8e21575a0d6ace51c528e7a6fcc35ce69cae7
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
662d52947eeb3fc8fca3b23991a5eee47077f896vboxsync#include <VBox/dis.h>
da957c069c2a3c582fe265ff88170ce4c42b499dvboxsync#include <VBox/disopcode.h>
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#include <VBox/err.h>
16a9adc14900ca18e6909679a579f6833425e030vboxsync#include <VBox/log.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/assert.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/param.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/string.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/stdarg.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "DisasmInternal.h"
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync/*******************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync* Defined Constants And Macros *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync*******************************************************************************/
b0b15690f00527424b2d5fb88456d747252322f7vboxsync/** This must be less or equal to DISSTATE::abInstr.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */
efff36b306e370346025647a158689021df2e1d1vboxsync#define DIS_MAX_INSTR_LENGTH 15
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync/** Whether we can do unaligned access. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync# define DIS_HOST_UNALIGNED_ACCESS_OK
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Internal Functions *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
efff36b306e370346025647a158689021df2e1d1vboxsync/** @name Parsers
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @{ */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic FNDISPARSE ParseIllegal;
efff36b306e370346025647a158689021df2e1d1vboxsyncstatic FNDISPARSE ParseModRM;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic FNDISPARSE ParseModRM_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE UseModRM;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByte;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByte_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByteSX;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmByteSX_SizeOnly;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic FNDISPARSE ParseImmBRel;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmBRel_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmUshort;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmUshort_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmV;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmV_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmVRel;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmVRel_SizeOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmZ;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmZ_SizeOnly;
0abd77741a608f6c41c8dfcd4781b8b84adf1044vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic FNDISPARSE ParseImmAddr;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmAddr_SizeOnly;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmAddrF;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseImmAddrF_SizeOnly;
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic FNDISPARSE ParseFixedReg;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmUlong;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmUlong_SizeOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmQword;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmQword_SizeOnly;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseInvOpModRm;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseTwoByteEsc;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseThreeByteEsc4;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseThreeByteEsc5;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseImmGrpl;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseShiftGrp2;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseGrp3;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic FNDISPARSE ParseGrp4;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic 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;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseModFence;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseNopPause;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsyncstatic FNDISPARSE ParseVex2b;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsyncstatic FNDISPARSE ParseVex3b;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseVexDest;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsyncstatic FNDISPARSE ParseYv;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsyncstatic FNDISPARSE ParseYb;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsyncstatic FNDISPARSE ParseXv;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsyncstatic FNDISPARSE ParseXb;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/** Floating point parsing */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic FNDISPARSE ParseEscFP;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @} */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/*******************************************************************************
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync* Global Variables *
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync*******************************************************************************/
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/** Parser opcode table for full disassembly. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseIllegal,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseModRM,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync UseModRM,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmByte,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmBRel,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmUshort,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmV,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmVRel,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmAddr,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseFixedReg,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmUlong,
21029597fc4b76d0db0c9542daee201447281781vboxsync ParseImmQword,
21029597fc4b76d0db0c9542daee201447281781vboxsync ParseTwoByteEsc,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmGrpl,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseShiftGrp2,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp3,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp4,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp5,
9496f2d398b49813176939d7a339ae513d5175efvboxsync Parse3DNow,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseGrp6,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseGrp7,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseGrp8,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseGrp9,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp10,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp12,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp13,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp14,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseGrp15,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseGrp16,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseModFence,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseYv,
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync ParseYb,
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync ParseXv,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseXb,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseEscFP,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseNopPause,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmByteSX,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmZ,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseThreeByteEsc4,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseThreeByteEsc5,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmAddrF,
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync ParseInvOpModRm,
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync ParseVex2b,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseVex3b,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseVexDest
16a9adc14900ca18e6909679a579f6833425e030vboxsync};
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** Parser opcode table for only calculating instruction size. */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseIllegal,
16a9adc14900ca18e6909679a579f6833425e030vboxsync ParseModRM_SizeOnly,
16a9adc14900ca18e6909679a579f6833425e030vboxsync UseModRM,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmByte_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmBRel_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmUshort_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmV_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmVRel_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmAddr_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseFixedReg,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmUlong_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmQword_SizeOnly,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseTwoByteEsc,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseImmGrpl,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseShiftGrp2,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseGrp3,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync ParseGrp4,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync 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 ParseVex2b,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseVex3b,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseVexDest
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync};
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/********************************************************************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Read functions for getting the opcode bytes
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ********************************************************************************************************************************/
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync#ifdef IN_RING0
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(cbMinRead);
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
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/**
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
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync * DISInstrEx API.)
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync if (RT_SUCCESS(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(pDis->cbCachedInstr >= offInstr + cbMin);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync Log(("disReadMore failed with rc=%Rrc!!\n", rc));
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync pDis->rc = rc;
22ec733a5e041fcdfe02fce2eafc9faf8b0077ddvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Function for handling a 8-bit cache miss.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @returns The requested byte.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the byte relative to the
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * instruction.
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync */
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsyncDECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr >= DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Log(("disReadByte: too long instruction...\n"));
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (cbLeft > 0)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return pDis->abInstr[offInstr];
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync return 0;
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync }
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync disReadMore(pDis, (uint8_t)offInstr, 1);
9496f2d398b49813176939d7a339ae513d5175efvboxsync return pDis->abInstr[offInstr];
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync/**
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * Read a byte (8-bit) instruction.
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested byte.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param uAddress The address.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncDECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr >= pDis->cbCachedInstr))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return disReadByteSlow(pDis, offInstr);
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return pDis->abInstr[offInstr];
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync}
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync/**
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * Function for handling a 16-bit cache miss.
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync *
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 {
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync Log(("disReadWord: too long instruction...\n"));
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync switch (cbLeft)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync case 1:
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return pDis->abInstr[offInstr];
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync default:
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync if (cbLeft >= 2)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return 0;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync disReadMore(pDis, (uint8_t)offInstr, 2);
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
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/**
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Read a word (16-bit) instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns The requested word.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
9496f2d398b49813176939d7a339ae513d5175efvboxsync * instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (RT_UNLIKELY(offInstr + 2 > pDis->cbCachedInstr))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return disReadWordSlow(pDis, offInstr);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
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]);
9496f2d398b49813176939d7a339ae513d5175efvboxsync#endif
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/**
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Function for handling a 32-bit cache miss.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @returns The requested dword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync * @param offInstr The offset of the dword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr + 4 > DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync Log(("disReadDWord: too long instruction...\n"));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync switch (cbLeft)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case 1:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case 2:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case 3:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync default:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (cbLeft >= 4)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync disReadMore(pDis, (uint8_t)offInstr, 4);
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 * Read a dword (32-bit) instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested dword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncDECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (RT_UNLIKELY(offInstr + 4 > pDis->cbCachedInstr))
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return disReadDWordSlow(pDis, offInstr);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return *(uint32_t const *)&pDis->abInstr[offInstr];
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync#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}
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Function for handling a 64-bit cache miss.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @returns The requested qword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncDECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (RT_UNLIKELY(offInstr + 8 > DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Log(("disReadQWord: too long instruction...\n"));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->rc = VERR_DIS_TOO_LONG_INSTR;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
9496f2d398b49813176939d7a339ae513d5175efvboxsync switch (cbLeft)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync {
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case 1:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case 3:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pDis->abInstr[offInstr + 2], 0, 0, 0, 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case 4:
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
9496f2d398b49813176939d7a339ae513d5175efvboxsync 0, 0, 0, 0);
9496f2d398b49813176939d7a339ae513d5175efvboxsync case 5:
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], 0, 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case 6:
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], pDis->abInstr[offInstr + 5],
9496f2d398b49813176939d7a339ae513d5175efvboxsync 0, 0);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync case 7:
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 6], 0);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync default:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (cbLeft >= 8)
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync disReadMore(pDis, (uint8_t)offInstr, 8);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync#else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
9496f2d398b49813176939d7a339ae513d5175efvboxsync#endif
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Read a qword (64-bit) instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @returns The requested qword.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param pDis The disassembler state.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param uAddress The address.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncDECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_UNLIKELY(offInstr + 8 > pDis->cbCachedInstr))
9496f2d398b49813176939d7a339ae513d5175efvboxsync return disReadQWordSlow(pDis, offInstr);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync#else
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync#endif
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync}
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync//*****************************************************************************
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync//*****************************************************************************
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncstatic size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync{
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync Assert(pOp); Assert(pDis);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync // Store the opcode format string for disasmPrintf
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync pDis->pCurInstr = pOp;
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /*
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Note! Multibyte opcodes are always marked harmless until the final byte.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsync bool fFiltered;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if ((pOp->fOpType & pDis->fFilter) == 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync fFiltered = true;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->pfnDisasmFnTable = g_apfnCalcSize;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Not filtered out -> full disassembly */
16a9adc14900ca18e6909679a579f6833425e030vboxsync fFiltered = false;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->pfnDisasmFnTable = g_apfnFullDisasm;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync // Should contain the parameter type on input
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->Param1.fParam = pOp->fParam1;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->Param2.fParam = pOp->fParam2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->Param3.fParam = pOp->fParam3;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->Param4.fParam = pOp->fParam4;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_64BIT;
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync if ( (pOp->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
16a9adc14900ca18e6909679a579f6833425e030vboxsync && !(pDis->fPrefix & DISPREFIX_OPSIZE))
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_64BIT;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync {
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync Assert(pDis->uCpuMode != DISCPUMODE_64BIT);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync pDis->uOpMode = DISCPUMODE_32BIT;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (pOp->idxParse1 != IDX_ParseNop)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync {
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync }
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (pOp->idxParse2 != IDX_ParseNop)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync {
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (pOp->idxParse3 != IDX_ParseNop)
efff36b306e370346025647a158689021df2e1d1vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (pOp->idxParse4 != IDX_ParseNop)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse4](offInstr, pOp, pDis, &pDis->Param4);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (fFiltered == false) pDis->Param4.cb = DISGetParamSize(pDis, &pDis->Param4);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync }
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync // else simple one byte instruction
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/* Floating point opcode parsing */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync PCDISOPCODE fpop;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pOp);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t index = pDis->bOpCode - 0xD8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (ModRM <= 0xBF)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->pCurInstr = fpop;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // Should contain the parameter type on input
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->Param1.fParam = fpop->fParam1;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->Param2.fParam = fpop->fParam2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync fpop = &(g_apMapX86_FP_High[index])[ModRM - 0xC0];
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->pCurInstr = fpop;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ((fpop->fOpType & pDis->fFilter) == 0)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->pfnDisasmFnTable = g_apfnCalcSize;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Not filtered out -> full disassembly */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->pfnDisasmFnTable = g_apfnFullDisasm;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Note: redundant, but just in case this ever changes */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fpop->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->uOpMode = DISCPUMODE_64BIT;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync && !(pDis->fPrefix & DISPREFIX_OPSIZE))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->uOpMode = DISCPUMODE_64BIT;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // Little hack to make sure the ModRM byte is included in the returned size
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr++; //ModRM byte
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fpop->idxParse1 != IDX_ParseNop)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fpop->idxParse2 != IDX_ParseNop)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/********************************************************************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * SIB byte: (not 16-bit mode)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * 7 - 6 5 - 3 2-0
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Scale Index Base
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ********************************************************************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned scale = pDis->SIB.Bits.Scale;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned base = pDis->SIB.Bits.Base;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned index = pDis->SIB.Bits.Index;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned regtype;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync regtype = DISUSE_REG_GEN32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync regtype = DISUSE_REG_GEN64;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (index != 4)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_INDEX | regtype;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->Index.idxGenReg = index;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (scale != 0)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_SCALE;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uScale = (1<<scale);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (base == 5 && pDis->ModRM.Bits.Mod == 0)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // [scaled index] + disp32
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_DISPLACEMENT32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->uDisp.i32 = pDis->i32SibDisp;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync { /* sign-extend to 64 bits */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_DISPLACEMENT64;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->uDisp.i64 = pDis->i32SibDisp;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->fUse |= DISUSE_BASE | regtype;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->Base.idxGenReg = base;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return; /* Already fetched everything in ParseSIB; no size returned */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NOREF(pOp); NOREF(pParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t SIB = disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Base = SIB_BASE(SIB);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Index = SIB_INDEX(SIB);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDis->fPrefix & DISPREFIX_REX)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.B extends the Base field if not scaled index + disp32 */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
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 pDis->i32SibDisp = disReadDWord(pDis, offInstr);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr += 4;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
59a2c1c0a4a0762b46bc5ff056f5705ec9c0a660vboxsyncstatic size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
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
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pDis->fPrefix & DISPREFIX_REX)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.B extends the Base field. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync 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 {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Additional 32 bits displacement. No change in long mode. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr += 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/********************************************************************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * ModR/M byte:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * 7 - 6 5 - 3 2-0
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Mod Reg/Opcode R/M
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ********************************************************************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void disasmModRMReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, int fRegAddr)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NOREF(pOp); NOREF(pDis);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned type = OP_PARM_VTYPE(pParam->fParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (fRegAddr)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync else
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (subtype == OP_PARM_v || subtype == OP_PARM_NONE || subtype == OP_PARM_y)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync switch (pDis->uOpMode)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync case DISCPUMODE_32BIT:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync subtype = OP_PARM_d;
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync break;
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync case DISCPUMODE_64BIT:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync subtype = OP_PARM_q;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync break;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync case DISCPUMODE_16BIT:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (subtype != OP_PARM_y)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync subtype = OP_PARM_w;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync break;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync default:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* make gcc happy */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (subtype)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case OP_PARM_b:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync 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. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Intel� 64 and IA-32 Architectures Software Developer�s Manual: 3.4.1.1 */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if ( (pDis->fPrefix & DISPREFIX_REX)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync && idx >= DISGREG_AH
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync && idx <= DISGREG_BH)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync idx += (DISGREG_SPL - DISGREG_AH);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_GEN8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxGenReg = idx;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case OP_PARM_w:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_GEN16;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Base.idxGenReg = idx;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_d:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_GEN32;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxGenReg = idx;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync break;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync case OP_PARM_q:
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_GEN64;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Base.idxGenReg = idx;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync break;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync default:
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pDis->rc = VERR_DIS_INVALID_MODRM;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync break;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic void disasmModRMReg16(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync{
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync static const uint8_t s_auBaseModRMReg16[8] =
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX };
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pDis); NOREF(pOp);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->fUse |= DISUSE_REG_GEN16;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxGenReg = s_auBaseModRMReg16[idx];
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (idx < 4)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync static const uint8_t s_auIndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI };
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_INDEX;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Index.idxGenReg = s_auIndexModRMReg16[idx];
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic void disasmModRMSReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync{
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync NOREF(pOp);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync 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}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncstatic size_t UseModRM(size_t const offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unsigned vtype = OP_PARM_VTYPE(pParam->fParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t reg = pDis->ModRM.Bits.Reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t mod = pDis->ModRM.Bits.Mod;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync uint8_t rm = pDis->ModRM.Bits.Rm;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (vtype)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_G: //general purpose register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg(reg, pOp, pDis, pParam, 0);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync default:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (IS_OP_PARM_RARE(vtype))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (vtype)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_C: //control register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_CR;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( pDis->pCurInstr->uOpcode == OP_MOV_CR
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && pDis->uOpMode == DISCPUMODE_32BIT
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync && (pDis->fPrefix & DISPREFIX_LOCK))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->fPrefix &= ~DISPREFIX_LOCK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxCtrlReg = DISCREG_CR8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxCtrlReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_D: //debug register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_DBG;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxDbgReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case OP_PARM_Q: //MMX or memory operand
51a01524909c95ee04b636218b6a89b29fb81825vboxsync 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_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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_T: //test register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg &= 7; /* REX.R has no effect here */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync 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 case OP_PARM_U: // XMM/YMM register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg = rm; /* the RM field specifies the xmm register */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else no break */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case OP_PARM_V: //XMM register
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (VEXREG_IS256B(pDis->bVexDestReg))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // Use YMM register if VEX.L is set.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_YMM;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxYmmReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_REG_XMM;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->Base.idxXmmReg = reg;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /** @todo bound */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uAddrMode != DISCPUMODE_16BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /*
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
b0b15690f00527424b2d5fb88456d747252322f7vboxsync */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync switch (mod)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync 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
b0b15690f00527424b2d5fb88456d747252322f7vboxsync { //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;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 3: //registers
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync disasmModRMReg(rm, pOp, pDis, pParam, 0);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {//16 bits addressing mode
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case 0: //effective address
b0b15690f00527424b2d5fb88456d747252322f7vboxsync 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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync 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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync 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 /*
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (mod != 3 && rm == 4) /* SIB byte follows ModRM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = ParseSIB(offInstr, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: /* Effective address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (rm == 5) /* 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
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
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 2: /* Effective address + 32 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->i32SibDisp = disReadDWord(pDis, offInstr);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr += 4;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 3: /* registers */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync else
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* 16 bits mode */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync switch (mod)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 0: /* Effective address */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (rm == 6)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->i32SibDisp = disReadWord(pDis, offInstr);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr += 2;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* else register address */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync break;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync 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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (mod != 3 && rm == 4)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { /* SIB byte follows ModRM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = ParseSIB_SizeOnly(offInstr, pOp, pDis, pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (mod)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (rm == 5) /* 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
217fa436516d137a409bb493cb7d350898f64666vboxsync case 1: /* Effective address + 8 bits displacement */
217fa436516d137a409bb493cb7d350898f64666vboxsync 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;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync else
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* 16 bits mode */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync switch (mod)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 0: //effective address
51a01524909c95ee04b636218b6a89b29fb81825vboxsync 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;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr += 2;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 3: /* registers */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
51a01524909c95ee04b636218b6a89b29fb81825vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncstatic size_t ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
51a01524909c95ee04b636218b6a89b29fb81825vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertFailed();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
217fa436516d137a409bb493cb7d350898f64666vboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr++;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync 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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * 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;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->fPrefix & DISPREFIX_REX)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* REX.R extends the Reg field. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (!( pDis->ModRM.Bits.Mod != 3
b0b15690f00527424b2d5fb88456d747252322f7vboxsync && 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 offInstr = QueryModRM(offInstr, pOp, pDis, pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return UseModRM(offInstr, pOp, pDis, pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync offInstr++;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* Disregard the mod bits for certain instructions (mov crx, mov drx).
b0b15690f00527424b2d5fb88456d747252322f7vboxsync *
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * From the AMD manual:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * encoding of the MOD field in the MODR/M byte.
b0b15690f00527424b2d5fb88456d747252322f7vboxsync */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Mod = 3;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->fPrefix & DISPREFIX_REX)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* REX.R extends the Reg field. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (!( pDis->ModRM.Bits.Mod != 3
b0b15690f00527424b2d5fb88456d747252322f7vboxsync && 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}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseImmUlong(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pOp);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_IMMEDIATE32;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->cb = sizeof(uint32_t);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseImmUlong_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(pOp); NOREF(pParam); NOREF(pDis);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return offInstr + 4;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmQword(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pOp);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->uValue = disReadQWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_IMMEDIATE64;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->cb = sizeof(uint64_t);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return offInstr + 8;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseImmQword_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 8;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmV(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;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->cb = sizeof(uint32_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 4;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = disReadQWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_IMMEDIATE64;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->cb = sizeof(uint64_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 8;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = disReadWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_IMMEDIATE16;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->cb = sizeof(uint16_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return offInstr + 2;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmV_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync return offInstr + 4;
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 8;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 2;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmZ(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync{
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync NOREF(pOp);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->uOpMode == DISCPUMODE_16BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->uValue = disReadWord(pDis, offInstr);
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync pParam->fUse |= DISUSE_IMMEDIATE16;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->cb = sizeof(uint16_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync 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;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->cb = sizeof(uint64_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_IMMEDIATE32;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->cb = sizeof(uint32_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmZ_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uOpMode == DISCPUMODE_16BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 4;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmBRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pOp);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->uValue = disReadByte(pDis, offInstr);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->fUse |= DISUSE_IMMEDIATE8_REL;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->cb = sizeof(uint8_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 1;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmBRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 1;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmVRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pOp);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->fUse |= DISUSE_IMMEDIATE32_REL;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->cb = sizeof(int32_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return offInstr + 4;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (pDis->uOpMode == DISCPUMODE_64BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* 32 bits relative immediate sign extended to 64 bits. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->fUse |= DISUSE_IMMEDIATE64_REL;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(int64_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 4;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->uValue = disReadWord(pDis, offInstr);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->fUse |= DISUSE_IMMEDIATE16_REL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->cb = sizeof(int16_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 2;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync// Relative displacement for branches (rel. to next instruction)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmVRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (pDis->uOpMode == DISCPUMODE_16BIT)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return offInstr + 2;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Both 32 & 64 bits mode use 32 bits relative immediates. */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseImmAddr(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync NOREF(pOp);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* far 16:32 pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4 + 2;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * near 32 bits pointer
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync *
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so we treat it like displacement.
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->uDisp.i32 = disReadDWord(pDis, offInstr);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->fUse |= DISUSE_DISPLACEMENT32;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint32_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync {
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync /*
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * near 64 bits pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so we treat it like displacement.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->uDisp.i64 = disReadQWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_DISPLACEMENT64;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = sizeof(uint64_t);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return offInstr + 8;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* far 16:16 pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->uValue = disReadDWord(pDis, offInstr);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pParam->cb = 2*sizeof(uint16_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /*
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * near 16 bits pointer
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync *
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * so we treat it like displacement.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->uDisp.i16 = disReadWord(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_DISPLACEMENT16;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParam->cb = sizeof(uint16_t);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return offInstr + 2;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync NOREF(offInstr); NOREF(pOp);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 4 + 2; /* far 16:32 pointer */
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync return offInstr + 4; /* near 32 bits pointer */
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 8;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 4; /* far 16:16 pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 2; /* near 16 bits pointer */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pOp);
9496f2d398b49813176939d7a339ae513d5175efvboxsync // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync // far 16:32 pointer
7a3f491705173bc08122f2c7d26d48a8b4c5ceecvboxsync pParam->uValue = disReadDWord(pDis, offInstr);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return offInstr + 4 + 2;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync // far 16:16 pointer
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pParam->uValue = disReadDWord(pDis, offInstr);
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->cb = 2*sizeof(uint16_t);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return offInstr + 2 + 2;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync}
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync NOREF(offInstr); NOREF(pOp);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync // immediate far pointers - only 16:16 or 16:32
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
9496f2d398b49813176939d7a339ae513d5175efvboxsync return offInstr + 4 + 2; /* far 16:32 pointer */
9496f2d398b49813176939d7a339ae513d5175efvboxsync return offInstr + 2 + 2; /* far 16:16 pointer */
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync NOREF(offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /*
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync * Sets up flags for stored in OPC fixed registers.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pParam->fParam == OP_PARM_NONE)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* No parameter at all. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync return offInstr;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync }
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync if (pParam->fParam <= OP_PARM_REG_GEN32_END)
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 32-bit EAX..EDI registers. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->uOpMode == DISCPUMODE_32BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Use 32-bit registers. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync pParam->fUse |= DISUSE_REG_GEN32;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync pParam->cb = 4;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync }
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync else if (pDis->uOpMode == DISCPUMODE_64BIT)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* Use 64-bit registers. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync pParam->fUse |= DISUSE_REG_GEN64;
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync pParam->cb = 8;
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync }
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync else
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Use 16-bit registers. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_REG_GEN16;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->cb = 2;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && (pDis->fPrefix & DISPREFIX_REX)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg += 8;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (pParam->fParam <= OP_PARM_REG_SEG_END)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Segment ES..GS registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_SEG;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->cb = 2;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (pParam->fParam <= OP_PARM_REG_GEN16_END)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 16-bit AX..DI registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN16_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN16;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->cb = 2;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (pParam->fParam <= OP_PARM_REG_GEN8_END)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 8-bit AL..DL, AH..DH registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN8;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->cb = 1;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if ( pDis->uCpuMode == DISCPUMODE_64BIT
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync && (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && (pDis->fPrefix & DISPREFIX_REX))
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if ( pParam->Base.idxGenReg >= DISGREG_AH
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && pParam->Base.idxGenReg <= DISGREG_BH)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg += DISGREG_SPL - DISGREG_AH;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (pParam->fParam <= OP_PARM_REG_FP_END)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* FPU registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_FP;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->cb = 10;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* else - not supported for now registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return offInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pOp);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_POINTER_DS_BASED;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_ESI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN32;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_RSI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN64;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_SI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN16;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return offInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pOp);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_POINTER_DS_BASED;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_ESI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN32;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_RSI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN64;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_SI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN16;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return offInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pOp);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_POINTER_ES_BASED;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->Base.idxGenReg = DISGREG_EDI;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->fUse |= DISUSE_REG_GEN32;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync else
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->Base.idxGenReg = DISGREG_RDI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN64;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_DI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN16;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return offInstr;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
c7ff622115966b69b482bd2896662e40d823b22fvboxsync//*****************************************************************************
c7ff622115966b69b482bd2896662e40d823b22fvboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pOp);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->fUse |= DISUSE_POINTER_ES_BASED;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uAddrMode == DISCPUMODE_32BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->Base.idxGenReg = DISGREG_EDI;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->fUse |= DISUSE_REG_GEN32;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pDis->uAddrMode == DISCPUMODE_64BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_RDI;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fUse |= DISUSE_REG_GEN64;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = DISGREG_DI;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync pParam->fUse |= DISUSE_REG_GEN16;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync }
76364cddabfeb143dad91862d41a5638d8860b25vboxsync return offInstr;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync}
76364cddabfeb143dad91862d41a5638d8860b25vboxsync//*****************************************************************************
76364cddabfeb143dad91862d41a5638d8860b25vboxsync//*****************************************************************************
76364cddabfeb143dad91862d41a5638d8860b25vboxsyncstatic size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pOp); NOREF(pDis); NOREF(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* This is used to avoid a bunch of special hacks to get the ModRM byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync included when encountering invalid opcodes in groups. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offInstr + 1;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
cba6719bd64ec749967bbe931230452664109857vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseVexDest(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync{
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync NOREF(pOp);
cba6719bd64ec749967bbe931230452664109857vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned type = OP_PARM_VTYPE(pParam->fParam);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync switch (type)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync case OP_PARM_H: //XMM or YMM register
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync if (VEXREG_IS256B(pDis->bVexDestReg))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync pParam->fUse |= DISUSE_REG_YMM;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxYmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->fUse |= DISUSE_REG_XMM;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxXmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync case OP_PARM_B: // Always OP_PARM_By. Change if it is not so.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if ((pDis->fPrefix & DISPREFIX_REX) && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W))
090d729e786b999dc285f8ea267f9effd1319544vboxsync pParam->fUse |= DISUSE_REG_GEN64;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->fUse |= DISUSE_REG_GEN32;
16a9adc14900ca18e6909679a579f6833425e030vboxsync // TODO: Check if the register number is correct
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->Base.idxGenReg = (pDis->bVexDestReg >> 1) ^ 0xf;
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return offInstr;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync}
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync NOREF(pOp); NOREF(pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* 2nd byte */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pDis->bOpCode = disReadByte(pDis, offInstr);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync offInstr++;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* default to the non-prefixed table. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (pDis->bLastPrefix)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync switch (pDis->bLastPrefix)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync case OP_OPSIZE: /* 0x66 */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
caf54c14752060b187e3fca12a6f71f4b13126b8vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Table entry is valid, so use the extension table. */
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync pOpcode = &g_aTwoByteMapX86_PF66[pDis->bOpCode];
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Cancel prefix changes. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync else
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync pDis->uOpMode = pDis->uCpuMode;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync break;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync case OP_REPNE: /* 0xF2 */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Table entry is valid, so use the extension table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpcode = &g_aTwoByteMapX86_PFF2[pDis->bOpCode];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Cancel prefix changes. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->fPrefix &= ~DISPREFIX_REPNE;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync case OP_REPE: /* 0xF3 */
090d729e786b999dc285f8ea267f9effd1319544vboxsync if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Table entry is valid, so use the extension table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpcode = &g_aTwoByteMapX86_PFF3[pDis->bOpCode];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync /* Cancel prefix changes. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->fPrefix &= ~DISPREFIX_REP;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync }
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync }
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
76364cddabfeb143dad91862d41a5638d8860b25vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync{
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync NOREF(pOp); NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* 3rd byte */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->bOpCode = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync offInstr++;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* default to the non-prefixed table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCDISOPCODE pOpcode;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4])
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync }
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync else
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pOpcode = &g_InvalidOpcode[0];
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync /* Handle opcode table extensions that rely on the address, repne prefix byte. */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync switch (pDis->bLastPrefix)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync {
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync case OP_OPSIZE: /* 0x66 */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync {
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync if (pOpcode->uOpcode != OP_INVALID)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Table entry is valid, so use the extension table. */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Cancel prefix changes. */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync {
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync }
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync else
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync pDis->uOpMode = pDis->uCpuMode;
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync }
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync }
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync break;
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync case OP_REPNE: /* 0xF2 */
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync if ((pDis->fPrefix & DISPREFIX_OPSIZE) && g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4])
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* 0x66F2 */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOpcode = g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync if (pOpcode->uOpcode != OP_INVALID)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Table entry is valid, so use the extension table. */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Cancel prefix changes. */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pDis->fPrefix &= ~DISPREFIX_REPNE;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync {
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync }
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync else
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pDis->uOpMode = pDis->uCpuMode;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync }
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync }
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync else if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync {
44fc72ff17b23a9b970505fcf8d6da1019ddcec5vboxsync pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync if (pOpcode->uOpcode != OP_INVALID)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync {
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync /* Table entry is valid, so use the extension table. */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Cancel prefix changes. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fPrefix &= ~DISPREFIX_REPNE;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync case OP_REPE: /* 0xF3 */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4])
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOpcode = g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4];
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOpcode->uOpcode != OP_INVALID)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Table entry is valid, so use the extension table. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Cancel prefix changes. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pDis->fPrefix &= ~DISPREFIX_REP;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync{
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync NOREF(pOp); NOREF(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 3rd byte */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->bOpCode = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync offInstr++;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(pDis->bLastPrefix == OP_OPSIZE);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* default to the non-prefixed table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCDISOPCODE pOpcode;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pOpcode = &pOpcode[pDis->bOpCode & 0xf];
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pOpcode->uOpcode != OP_INVALID)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Table entry is valid, so use the extension table. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Cancel prefix changes. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->fPrefix &= ~DISPREFIX_OPSIZE;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pDis->uCpuMode == DISCPUMODE_64BIT)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->uOpMode = pDis->uCpuMode;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync }
51a01524909c95ee04b636218b6a89b29fb81825vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pOpcode = &g_InvalidOpcode[0];
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (pDis->fPrefix & DISPREFIX_REP)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->fPrefix &= ~DISPREFIX_REP;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync else
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pOp = &g_aMapX86_NopPause[0]; /* NOP */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return disParseInstruction(offInstr, pOp, pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t reg = MODRM_REG(modrm);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned idx = (pDis->bOpCode - 0x80) * 8;
efff36b306e370346025647a158689021df2e1d1vboxsync
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync pOp = &g_aMapX86_Group1[idx+reg];
efff36b306e370346025647a158689021df2e1d1vboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync return disParseInstruction(offInstr, pOp, pDis);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NOREF(pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned idx;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync switch (pDis->bOpCode)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync case 0xC0:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case 0xC1:
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync idx = (pDis->bOpCode - 0xC0)*8;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync break;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0xD0:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0xD1:
efff36b306e370346025647a158689021df2e1d1vboxsync case 0xD2:
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync case 0xD3:
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync idx = (pDis->bOpCode - 0xD0 + 2)*8;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync break;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync default:
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync pDis->rc = VERR_DIS_INVALID_OPCODE;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync return offInstr;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync }
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync uint8_t reg = MODRM_REG(modrm);
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync pOp = &g_aMapX86_Group2[idx+reg];
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync return disParseInstruction(offInstr, pOp, pDis);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync}
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync{
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync unsigned idx = (pDis->bOpCode - 0xF6) * 8;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync NOREF(pParam);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync uint8_t reg = MODRM_REG(modrm);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync pOp = &g_aMapX86_Group3[idx+reg];
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync return disParseInstruction(offInstr, pOp, pDis);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync}
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync{
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync NOREF(pParam);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync uint8_t reg = MODRM_REG(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group4[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp5(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
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group5[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
16a9adc14900ca18e6909679a579f6833425e030vboxsync// It would appear the ModRM byte must always be present. How else can you
16a9adc14900ca18e6909679a579f6833425e030vboxsync// determine the offset of the imm8_opcode byte otherwise?
16a9adc14900ca18e6909679a579f6833425e030vboxsync//
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync//*****************************************************************************
a3369a746b56a8966dd78619f4d191c9662f400dvboxsyncstatic size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync{
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /** @todo This code needs testing! Esp. wrt invalid opcodes. */
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint8_t ModRM = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync uint8_t opcode = disReadByte(pDis, offRet);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync offRet++;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync pOp = &g_aTwoByteMapX86_3DNow[opcode];
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync NOREF(offStrict);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return offRet;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsyncstatic size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t reg = MODRM_REG(modrm);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOp = &g_aMapX86_Group6[reg];
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync return disParseInstruction(offInstr, pOp, pDis);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync}
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync//*****************************************************************************
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync//*****************************************************************************
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncstatic size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t mod = MODRM_MOD(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t reg = MODRM_REG(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t rm = MODRM_RM(modrm);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (mod == 3 && rm == 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group7_mod11_rm000[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (mod == 3 && rm == 1)
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group7_mod11_rm001[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group7_mem[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Cannot easily skip this hack because of monitor and vmcall! */
16a9adc14900ca18e6909679a579f6833425e030vboxsync //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++;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp8(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
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOp = &g_aMapX86_Group8[reg];
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pParam);
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync uint8_t reg = MODRM_REG(modrm);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pOp = &g_aMapX86_Group9[reg];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disParseInstruction(offInstr, pOp, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NOREF(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync uint8_t reg = MODRM_REG(modrm);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pOp = &g_aMapX86_Group10[reg];
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return disParseInstruction(offInstr, pOp, pDis);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync NOREF(pParam);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint8_t modrm = disReadByte(pDis, offInstr);
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint8_t reg = MODRM_REG(modrm);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync if (pDis->fPrefix & DISPREFIX_OPSIZE)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync reg += 8; /* 2nd table */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pOp = &g_aMapX86_Group12[reg];
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync return disParseInstruction(offInstr, pOp, pDis);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync}
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync//*****************************************************************************
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsyncstatic size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync{
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync NOREF(pParam);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync uint8_t reg = MODRM_REG(modrm);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync if (pDis->fPrefix & DISPREFIX_OPSIZE)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync reg += 8; /* 2nd table */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsync pOp = &g_aMapX86_Group13[reg];
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOp, pDis);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync NOREF(pParam);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint8_t reg = MODRM_REG(modrm);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->fPrefix & DISPREFIX_OPSIZE)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync reg += 8; /* 2nd table */
76364cddabfeb143dad91862d41a5638d8860b25vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOp = &g_aMapX86_Group14[reg];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disParseInstruction(offInstr, pOp, pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t mod = MODRM_MOD(modrm);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync uint8_t reg = MODRM_REG(modrm);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync uint8_t rm = MODRM_RM(modrm);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (mod == 3 && rm == 0)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOp = &g_aMapX86_Group15_mod11_rm000[reg];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOp = &g_aMapX86_Group15_mem[reg];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOp, pDis);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pParam);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync uint8_t modrm = disReadByte(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOp, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseVex2b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(pOp); NOREF(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync PCDISOPCODE pOpCode = &g_InvalidOpcode[0];
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync uint8_t byte = disReadByte(pDis, offInstr++);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pDis->bOpCode = disReadByte(pDis, offInstr++);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pDis->bVexDestReg = VEX_2B2INT(byte);
4a23807f02e9920d92c8449bd93d84501add460avboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync // VEX.R (equivalent to REX.R)
4a23807f02e9920d92c8449bd93d84501add460avboxsync if (!(byte & 0x80) && pDis->uCpuMode == DISCPUMODE_64BIT)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* REX prefix byte */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->fPrefix |= DISPREFIX_REX;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->fRexPrefix = DISPREFIX_REX_FLAGS_R;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch(byte & 3)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 0:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpCode = g_aVexOpcodesMap[0] + pDis->bOpCode;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
5b465a7c1237993faf8bb50120d247f3f0319adavboxsync // OPSIZE 0x66 prefix
09127e6ed46502ff8a6a521713ee8ace53667683vboxsync case 1:
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync pOpCode = g_aVexOpcodesMap_66H[0] + pDis->bOpCode;
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync /* TODO: Check if we need to set this prefix */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync pDis->fPrefix |= DISPREFIX_OPSIZE;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->uCpuMode == DISCPUMODE_16BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->uOpMode = DISCPUMODE_32BIT;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // REPE 0xF3 prefix
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 2:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpCode = g_aVexOpcodesMap_F3H[0] + pDis->bOpCode;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // REPNE 0xF2 prefix
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 3:
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pOpCode = g_aVexOpcodesMap_F2H[0] + pDis->bOpCode;
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync break;
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync default:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOpCode, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic size_t ParseVex3b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NOREF(pOp); NOREF(pParam);
cba6719bd64ec749967bbe931230452664109857vboxsync
cba6719bd64ec749967bbe931230452664109857vboxsync PCDISOPCODE pOpCode = &g_InvalidOpcode[0];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint8_t byte1 = disReadByte(pDis, offInstr++);
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint8_t byte2 = disReadByte(pDis, offInstr++);
cba6719bd64ec749967bbe931230452664109857vboxsync pDis->bOpCode = disReadByte(pDis, offInstr++);
cba6719bd64ec749967bbe931230452664109857vboxsync
cba6719bd64ec749967bbe931230452664109857vboxsync pDis->bVexDestReg = VEX_2B2INT(byte2);
cba6719bd64ec749967bbe931230452664109857vboxsync uint8_t implOpcode = (byte1 & 0x1f);
cba6719bd64ec749967bbe931230452664109857vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // REX.RXB
cba6719bd64ec749967bbe931230452664109857vboxsync if (~(byte1 & 0xe0))
{
Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
pDis->fPrefix |= DISPREFIX_REX;
pDis->fRexPrefix = ~(byte1 >> 5);
}
// REX.W
if (!(byte2 & 0x80))
{
Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
pDis->fPrefix |= DISPREFIX_REX;
pDis->fRexPrefix |= DISPREFIX_REX_FLAGS_W;
}
switch(byte2 & 3)
{
case 0:
if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
{
pOpCode = g_aVexOpcodesMap[implOpcode - 1];
if (pOpCode != NULL)
pOpCode = &pOpCode[pDis->bOpCode];
else pOpCode = &g_InvalidOpcode[0];
}
break;
// OPSIZE 0x66 prefix
case 1:
if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
{
pOpCode = g_aVexOpcodesMap_66H[implOpcode - 1];
if (pOpCode != NULL)
pOpCode = &pOpCode[pDis->bOpCode];
else pOpCode = &g_InvalidOpcode[0];
/* TODO: check if we need to set this prefix */
pDis->fPrefix |= DISPREFIX_OPSIZE;
if (pDis->uCpuMode == DISCPUMODE_16BIT)
pDis->uOpMode = DISCPUMODE_32BIT;
else
pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
}
break;
// REPE 0xF3 prefix
case 2:
if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
{
pOpCode = g_aVexOpcodesMap_F3H[implOpcode - 1];
if (pOpCode != NULL)
pOpCode = &pOpCode[pDis->bOpCode];
else pOpCode = &g_InvalidOpcode[0];
}
break;
// REPNE 0xF2 prefix
case 3:
if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
{
pOpCode = g_aVexOpcodesMap_F2H[implOpcode - 1];
if (pOpCode != NULL)
pOpCode = &pOpCode[pDis->bOpCode];
else pOpCode = &g_InvalidOpcode[0];
}
break;
default:
break;
}
return disParseInstruction(offInstr, pOpCode, pDis);
}
/**
* Validates the lock sequence.
*
* The AMD manual lists the following instructions:
* ADC
* ADD
* AND
* BTC
* BTR
* BTS
* CMPXCHG
* CMPXCHG8B
* CMPXCHG16B
* DEC
* INC
* NEG
* NOT
* OR
* SBB
* SUB
* XADD
* XCHG
* XOR
*
* @param pDis Fully disassembled instruction.
*/
static void disValidateLockSequence(PDISSTATE pDis)
{
Assert(pDis->fPrefix & DISPREFIX_LOCK);
/*
* Filter out the valid lock sequences.
*/
switch (pDis->pCurInstr->uOpcode)
{
/* simple: no variations */
case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
return;
/* simple: /r - reject register destination. */
case OP_BTC:
case OP_BTR:
case OP_BTS:
case OP_CMPXCHG:
case OP_XADD:
if (pDis->ModRM.Bits.Mod == 3)
break;
return;
/*
* Lots of variants but its sufficient to check that param 1
* is a memory operand.
*/
case OP_ADC:
case OP_ADD:
case OP_AND:
case OP_DEC:
case OP_INC:
case OP_NEG:
case OP_NOT:
case OP_OR:
case OP_SBB:
case OP_SUB:
case OP_XCHG:
case OP_XOR:
if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
| DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
return;
break;
default:
break;
}
/*
* Invalid lock sequence, make it a OP_ILLUD2.
*/
pDis->pCurInstr = &g_aTwoByteMapX86[11];
Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
}
/**
* Internal worker for DISInstrEx and DISInstrWithPrefetchedBytes.
*
* @returns VBox status code.
* @param pDis Initialized disassembler state.
* @param paOneByteMap The one byte opcode map to use.
* @param pcbInstr Where to store the instruction size. Can be NULL.
*/
static int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
{
/*
* Parse byte by byte.
*/
size_t offInstr = 0;
for (;;)
{
uint8_t codebyte = disReadByte(pDis, offInstr++);
uint8_t opcode = paOneByteMap[codebyte].uOpcode;
/* Hardcoded assumption about OP_* values!! */
if (opcode <= OP_LAST_PREFIX)
{
/* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
if (opcode != OP_REX)
{
/* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
pDis->bLastPrefix = opcode;
pDis->fPrefix &= ~DISPREFIX_REX;
}
switch (opcode)
{
case OP_INVALID:
if (pcbInstr)
*pcbInstr = (uint32_t)offInstr;
return pDis->rc = VERR_DIS_INVALID_OPCODE;
// segment override prefix byte
case OP_SEG:
pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
#if 0 /* Try be accurate in our reporting, shouldn't break anything... :-) */
/* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
if ( pDis->uCpuMode != DISCPUMODE_64BIT
|| pDis->idxSegPrefix >= DISSELREG_FS)
pDis->fPrefix |= DISPREFIX_SEG;
#else
pDis->fPrefix |= DISPREFIX_SEG;
#endif
continue; //fetch the next byte
// lock prefix byte
case OP_LOCK:
pDis->fPrefix |= DISPREFIX_LOCK;
continue; //fetch the next byte
// address size override prefix byte
case OP_ADDRSIZE:
pDis->fPrefix |= DISPREFIX_ADDRSIZE;
if (pDis->uCpuMode == DISCPUMODE_16BIT)
pDis->uAddrMode = DISCPUMODE_32BIT;
else
if (pDis->uCpuMode == DISCPUMODE_32BIT)
pDis->uAddrMode = DISCPUMODE_16BIT;
else
pDis->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
continue; //fetch the next byte
// operand size override prefix byte
case OP_OPSIZE:
pDis->fPrefix |= DISPREFIX_OPSIZE;
if (pDis->uCpuMode == DISCPUMODE_16BIT)
pDis->uOpMode = DISCPUMODE_32BIT;
else
pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
continue; //fetch the next byte
// rep and repne are not really prefixes, but we'll treat them as such
case OP_REPE:
pDis->fPrefix |= DISPREFIX_REP;
continue; //fetch the next byte
case OP_REPNE:
pDis->fPrefix |= DISPREFIX_REPNE;
continue; //fetch the next byte
case OP_REX:
Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
/* REX prefix byte */
pDis->fPrefix |= DISPREFIX_REX;
pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
continue; //fetch the next byte
default:
break;
}
}
/* Check if this is a VEX prefix. Not for 32-bit mode. */
if ((opcode == OP_LES || opcode == OP_LDS)
&& (disReadByte(pDis, offInstr) & 0xc0) == 0xc0
&& (opcode != OP_LES || pDis->uCpuMode == DISCPUMODE_64BIT || !(disReadByte(pDis, offInstr + 1) & 0x80)))
{
paOneByteMap = g_aOneByteMapX64;
}
/* first opcode byte. */
pDis->bOpCode = codebyte;
pDis->cbPrefix = (uint8_t)offInstr - 1;
offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
break;
}
pDis->cbInstr = (uint8_t)offInstr;
if (pcbInstr)
*pcbInstr = (uint32_t)offInstr;
if (pDis->fPrefix & DISPREFIX_LOCK)
disValidateLockSequence(pDis);
return pDis->rc;
}
/**
* Inlined worker that initializes the disassembler state.
*
* @returns The primary opcode map to use.
* @param pDis The disassembler state.
* @param uInstrAddr The instruction address.
* @param enmCpuMode The CPU mode.
* @param fFilter The instruction filter settings.
* @param pfnReadBytes The byte reader, can be NULL.
* @param pvUser The the user data for the reader.
*/
DECL_FORCE_INLINE(PCDISOPCODE)
disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
PFNDISREADBYTES pfnReadBytes, void *pvUser)
{
RT_ZERO(*pDis);
#ifdef VBOX_STRICT /* poison */
pDis->Param1.Base.idxGenReg = 0xc1;
pDis->Param2.Base.idxGenReg = 0xc2;
pDis->Param3.Base.idxGenReg = 0xc3;
pDis->Param1.Index.idxGenReg = 0xc4;
pDis->Param2.Index.idxGenReg = 0xc5;
pDis->Param3.Index.idxGenReg = 0xc6;
pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
pDis->Param1.uScale = 28;
pDis->Param2.uScale = 29;
pDis->Param3.uScale = 30;
#endif
pDis->fPrefix = DISPREFIX_NONE;
pDis->idxSegPrefix = DISSELREG_DS;
pDis->rc = VINF_SUCCESS;
pDis->pfnDisasmFnTable = g_apfnFullDisasm;
pDis->uInstrAddr = uInstrAddr;
pDis->fFilter = fFilter;
pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
pDis->pvUser = pvUser;
pDis->uCpuMode = enmCpuMode;
PCDISOPCODE paOneByteMap;
if (enmCpuMode == DISCPUMODE_64BIT)
{
pDis->uAddrMode = DISCPUMODE_64BIT;
pDis->uOpMode = DISCPUMODE_32BIT;
paOneByteMap = g_aOneByteMapX64;
}
else
{
pDis->uAddrMode = enmCpuMode;
pDis->uOpMode = enmCpuMode;
paOneByteMap = g_aOneByteMapX86;
}
return paOneByteMap;
}
/**
* Reads some bytes into the cache.
*
* While this will set DISSTATE::rc on failure, the caller should disregard
* this since that is what would happen if we didn't prefetch bytes prior to the
* instruction parsing.
*
* @param pDis The disassembler state.
*/
DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
{
/*
* Read some bytes into the cache. (If this fail we continue as nothing
* has gone wrong since this is what would happen if we didn't precharge
* the cache here.)
*/
int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
if (RT_SUCCESS(rc))
{
Assert(pDis->cbCachedInstr >= 1);
Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
}
else
{
Log(("Initial read failed with rc=%Rrc!!\n", rc));
pDis->rc = rc;
}
}
/**
* Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
*
* @returns VBox status code.
* @param uInstrAddr Address of the instruction to decode. What this means
* is left to the pfnReadBytes function.
* @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
* @param pfnReadBytes Callback for reading instruction bytes.
* @param fFilter Instruction type filter.
* @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
* @param pDis Pointer to disassembler state (output).
* @param pcbInstr Where to store the size of the instruction. (This
* is also stored in PDISSTATE::cbInstr.) Optional.
*/
DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
PFNDISREADBYTES pfnReadBytes, void *pvUser,
PDISSTATE pDis, uint32_t *pcbInstr)
{
PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
disPrefetchBytes(pDis);
return disInstrWorker(pDis, paOneByteMap, pcbInstr);
}
/**
* Disassembles on instruction partially or fully from prefetched bytes, details
* in @a pDis and length in @a pcbInstr.
*
* @returns VBox status code.
* @param uInstrAddr Address of the instruction to decode. What this means
* is left to the pfnReadBytes function.
* @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
* @param pvPrefetched Pointer to the prefetched bytes.
* @param cbPrefetched The number of valid bytes pointed to by @a
* pbPrefetched.
* @param pfnReadBytes Callback for reading instruction bytes.
* @param fFilter Instruction type filter.
* @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
* @param pDis Pointer to disassembler state (output).
* @param pcbInstr Where to store the size of the instruction. (This
* is also stored in PDISSTATE::cbInstr.) Optional.
*/
DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
void const *pvPrefetched, size_t cbPretched,
PFNDISREADBYTES pfnReadBytes, void *pvUser,
PDISSTATE pDis, uint32_t *pcbInstr)
{
PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
if (!cbPretched)
disPrefetchBytes(pDis);
else
{
if (cbPretched >= sizeof(pDis->abInstr))
{
memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
}
else
{
memcpy(pDis->abInstr, pvPrefetched, cbPretched);
pDis->cbCachedInstr = (uint8_t)cbPretched;
}
}
return disInstrWorker(pDis, paOneByteMap, pcbInstr);
}
/**
* Parses one guest instruction.
*
* The result is found in pDis and pcbInstr.
*
* @returns VBox status code.
* @param uInstrAddr Address of the instruction to decode. What this means
* is left to the pfnReadBytes function.
* @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
* @param pfnReadBytes Callback for reading instruction bytes.
* @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
* @param pDis Pointer to disassembler state (output).
* @param pcbInstr Where to store the size of the instruction.
* NULL is allowed. This is also stored in
* PDISSTATE::cbInstr.
*/
DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
PDISSTATE pDis, uint32_t *pcbInstr)
{
return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
}
/**
* Parses one guest instruction.
*
* The result is found in pDis and pcbInstr.
*
* @returns VBox status code.
* @param pvInstr Address of the instruction to decode. This is a
* real address in the current context that can be
* accessed without faulting. (Consider
* DISInstrWithReader if this isn't the case.)
* @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
* @param pfnReadBytes Callback for reading instruction bytes.
* @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
* @param pDis Pointer to disassembler state (output).
* @param pcbInstr Where to store the size of the instruction.
* NULL is allowed. This is also stored in
* PDISSTATE::cbInstr.
*/
DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
{
return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);
}