summaryrefslogtreecommitdiffstats
path: root/src/VBox/Disassembler
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Disassembler
parentInitial commit. (diff)
downloadvirtualbox-upstream/7.0.14-dfsg.tar.xz
virtualbox-upstream/7.0.14-dfsg.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Disassembler')
-rw-r--r--src/VBox/Disassembler/.scm-settings30
-rw-r--r--src/VBox/Disassembler/Disasm.cpp126
-rw-r--r--src/VBox/Disassembler/DisasmCore.cpp3000
-rw-r--r--src/VBox/Disassembler/DisasmFormatBytes.cpp97
-rw-r--r--src/VBox/Disassembler/DisasmFormatYasm.cpp1765
-rw-r--r--src/VBox/Disassembler/DisasmInternal.h262
-rw-r--r--src/VBox/Disassembler/DisasmMisc.cpp175
-rw-r--r--src/VBox/Disassembler/DisasmReg.cpp685
-rw-r--r--src/VBox/Disassembler/DisasmTables.cpp4320
-rw-r--r--src/VBox/Disassembler/DisasmTablesX64.cpp369
-rw-r--r--src/VBox/Disassembler/Makefile.kmk91
-rw-r--r--src/VBox/Disassembler/testcase/Makefile.kmk271
-rw-r--r--src/VBox/Disassembler/testcase/tstAsm.mac68
-rw-r--r--src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm91
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm41
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmLock-1.asm685
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmLock-2.asm547
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmLock-3.asm56
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm113
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm58
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm49
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmPop-1.asm46
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmPush-1.asm46
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmRegs-1.asm119
-rw-r--r--src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm63
-rw-r--r--src/VBox/Disassembler/testcase/tstBinFnstsw-1.binbin0 -> 3 bytes
-rw-r--r--src/VBox/Disassembler/testcase/tstBinMovzx-1.bin1
-rw-r--r--src/VBox/Disassembler/testcase/tstDisasm-1.cpp214
-rw-r--r--src/VBox/Disassembler/testcase/tstDisasm-1A.asm474
-rw-r--r--src/VBox/Disassembler/testcase/tstDisasm-2.cpp693
30 files changed, 14555 insertions, 0 deletions
diff --git a/src/VBox/Disassembler/.scm-settings b/src/VBox/Disassembler/.scm-settings
new file mode 100644
index 00000000..32b0a169
--- /dev/null
+++ b/src/VBox/Disassembler/.scm-settings
@@ -0,0 +1,30 @@
+# $Id: .scm-settings $
+## @file
+# Source code massager settings for the diassembler.
+#
+
+#
+# Copyright (C) 2010-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+--filter-out-files *.bin
+/*.h: --guard-relative-to-dir .
+
diff --git a/src/VBox/Disassembler/Disasm.cpp b/src/VBox/Disassembler/Disasm.cpp
new file mode 100644
index 00000000..734cbfb0
--- /dev/null
+++ b/src/VBox/Disassembler/Disasm.cpp
@@ -0,0 +1,126 @@
+/* $Id: Disasm.cpp $ */
+/** @file
+ * VBox disassembler - Disassemble and optionally format.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DIS
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include <iprt/errcore.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include "DisasmInternal.h"
+
+
+/**
+ * Disassembles one instruction
+ *
+ * @returns VBox error code
+ * @param pvInstr Pointer to the instruction to disassemble.
+ * @param enmCpuMode The CPU state.
+ * @param pDis The disassembler state (output).
+ * @param pcbInstr Where to store the size of the instruction. NULL is
+ * allowed.
+ * @param pszOutput Storage for disassembled instruction
+ * @param cbOutput Size of the output buffer.
+ *
+ * @todo Define output callback.
+ */
+DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr,
+ char *pszOutput, size_t cbOutput)
+{
+ return DISInstrToStrEx((uintptr_t)pvInstr, enmCpuMode, NULL, NULL, DISOPTYPE_ALL,
+ pDis, pcbInstr, pszOutput, cbOutput);
+}
+
+/**
+ * Disassembles one instruction with a byte fetcher caller.
+ *
+ * @returns VBox error code
+ * @param uInstrAddr Pointer to the structure to disassemble.
+ * @param enmCpuMode The CPU mode.
+ * @param pfnCallback The byte fetcher callback.
+ * @param pvUser The user argument (found in
+ * DISSTATE::pvUser).
+ * @param pDis The disassembler state (output).
+ * @param pcbInstr Where to store the size of the instruction. NULL is
+ * allowed.
+ * @param pszOutput Storage for disassembled instruction.
+ * @param cbOutput Size of the output buffer.
+ *
+ * @todo Define output callback.
+ */
+DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
+ PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput)
+
+{
+ return DISInstrToStrEx(uInstrAddr, enmCpuMode, pfnReadBytes, pvUser, DISOPTYPE_ALL,
+ pDis, pcbInstr, pszOutput, cbOutput);
+}
+
+/**
+ * Disassembles one instruction; only fully disassembly an instruction if it matches the filter criteria
+ *
+ * @returns VBox error code
+ * @param uInstrAddr Pointer to the structure to disassemble.
+ * @param enmCpuMode The CPU mode.
+ * @param pfnCallback The byte fetcher callback.
+ * @param uFilter Instruction filter.
+ * @param pDis Where to return the disassembled instruction info.
+ * @param pcbInstr Where to store the size of the instruction. NULL is
+ * allowed.
+ * @param pszOutput Storage for disassembled instruction.
+ * @param cbOutput Size of the output buffer.
+ *
+ * @todo Define output callback.
+ */
+DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
+ PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
+ PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput)
+{
+ /* Don't filter if formatting is desired. */
+ if (uFilter != DISOPTYPE_ALL && pszOutput && cbOutput)
+ uFilter = DISOPTYPE_ALL;
+
+ int rc = DISInstrEx(uInstrAddr, enmCpuMode, uFilter, pfnReadBytes, pvUser, pDis, pcbInstr);
+ if (RT_SUCCESS(rc) && pszOutput && cbOutput)
+ {
+ size_t cch = DISFormatYasmEx(pDis, pszOutput, cbOutput,
+ DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED
+ | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT,
+ NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
+ if (cch + 2 <= cbOutput)
+ {
+ pszOutput[cch++] = '\n';
+ pszOutput[cch] = '\0';
+ }
+ }
+ return rc;
+}
+
diff --git a/src/VBox/Disassembler/DisasmCore.cpp b/src/VBox/Disassembler/DisasmCore.cpp
new file mode 100644
index 00000000..c2613523
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmCore.cpp
@@ -0,0 +1,3000 @@
+/* $Id: DisasmCore.cpp $ */
+/** @file
+ * VBox Disassembler - Core Components.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DIS
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/param.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#include "DisasmInternal.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/** This must be less or equal to DISSTATE::abInstr.
+ * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */
+#define DIS_MAX_INSTR_LENGTH 15
+
+/** Whether we can do unaligned access. */
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+# define DIS_HOST_UNALIGNED_ACCESS_OK
+#endif
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+/** @name Parsers
+ * @{ */
+static FNDISPARSE ParseIllegal;
+static FNDISPARSE ParseModRM;
+static FNDISPARSE ParseModRM_SizeOnly;
+static FNDISPARSE UseModRM;
+static FNDISPARSE ParseImmByte;
+static FNDISPARSE ParseImmByte_SizeOnly;
+static FNDISPARSE ParseImmByteSX;
+static FNDISPARSE ParseImmByteSX_SizeOnly;
+static FNDISPARSE ParseImmBRel;
+static FNDISPARSE ParseImmBRel_SizeOnly;
+static FNDISPARSE ParseImmUshort;
+static FNDISPARSE ParseImmUshort_SizeOnly;
+static FNDISPARSE ParseImmV;
+static FNDISPARSE ParseImmV_SizeOnly;
+static FNDISPARSE ParseImmVRel;
+static FNDISPARSE ParseImmVRel_SizeOnly;
+static FNDISPARSE ParseImmZ;
+static FNDISPARSE ParseImmZ_SizeOnly;
+
+static FNDISPARSE ParseImmAddr;
+static FNDISPARSE ParseImmAddr_SizeOnly;
+static FNDISPARSE ParseImmAddrF;
+static FNDISPARSE ParseImmAddrF_SizeOnly;
+static FNDISPARSE ParseFixedReg;
+static FNDISPARSE ParseImmUlong;
+static FNDISPARSE ParseImmUlong_SizeOnly;
+static FNDISPARSE ParseImmQword;
+static FNDISPARSE ParseImmQword_SizeOnly;
+static FNDISPARSE ParseInvOpModRm;
+
+static FNDISPARSE ParseTwoByteEsc;
+static FNDISPARSE ParseThreeByteEsc4;
+static FNDISPARSE ParseThreeByteEsc5;
+static FNDISPARSE ParseGrp1;
+static FNDISPARSE ParseShiftGrp2;
+static FNDISPARSE ParseGrp3;
+static FNDISPARSE ParseGrp4;
+static FNDISPARSE ParseGrp5;
+static FNDISPARSE Parse3DNow;
+static FNDISPARSE ParseGrp6;
+static FNDISPARSE ParseGrp7;
+static FNDISPARSE ParseGrp8;
+static FNDISPARSE ParseGrp9;
+static FNDISPARSE ParseGrp10;
+static FNDISPARSE ParseGrp12;
+static FNDISPARSE ParseGrp13;
+static FNDISPARSE ParseGrp14;
+static FNDISPARSE ParseGrp15;
+static FNDISPARSE ParseGrp16;
+static FNDISPARSE ParseGrp17;
+static FNDISPARSE ParseModFence;
+static FNDISPARSE ParseNopPause;
+static FNDISPARSE ParseVex2b;
+static FNDISPARSE ParseVex3b;
+static FNDISPARSE ParseVexDest;
+
+static FNDISPARSE ParseYv;
+static FNDISPARSE ParseYb;
+static FNDISPARSE ParseXv;
+static FNDISPARSE ParseXb;
+
+/** Floating point parsing */
+static FNDISPARSE ParseEscFP;
+/** @} */
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Parser opcode table for full disassembly. */
+static PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
+{
+ ParseIllegal,
+ ParseModRM,
+ UseModRM,
+ ParseImmByte,
+ ParseImmBRel,
+ ParseImmUshort,
+ ParseImmV,
+ ParseImmVRel,
+ ParseImmAddr,
+ ParseFixedReg,
+ ParseImmUlong,
+ ParseImmQword,
+ ParseTwoByteEsc,
+ ParseGrp1,
+ ParseShiftGrp2,
+ ParseGrp3,
+ ParseGrp4,
+ ParseGrp5,
+ Parse3DNow,
+ ParseGrp6,
+ ParseGrp7,
+ ParseGrp8,
+ ParseGrp9,
+ ParseGrp10,
+ ParseGrp12,
+ ParseGrp13,
+ ParseGrp14,
+ ParseGrp15,
+ ParseGrp16,
+ ParseGrp17,
+ ParseModFence,
+ ParseYv,
+ ParseYb,
+ ParseXv,
+ ParseXb,
+ ParseEscFP,
+ ParseNopPause,
+ ParseImmByteSX,
+ ParseImmZ,
+ ParseThreeByteEsc4,
+ ParseThreeByteEsc5,
+ ParseImmAddrF,
+ ParseInvOpModRm,
+ ParseVex2b,
+ ParseVex3b,
+ ParseVexDest
+};
+
+/** Parser opcode table for only calculating instruction size. */
+static PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
+{
+ ParseIllegal,
+ ParseModRM_SizeOnly,
+ UseModRM,
+ ParseImmByte_SizeOnly,
+ ParseImmBRel_SizeOnly,
+ ParseImmUshort_SizeOnly,
+ ParseImmV_SizeOnly,
+ ParseImmVRel_SizeOnly,
+ ParseImmAddr_SizeOnly,
+ ParseFixedReg,
+ ParseImmUlong_SizeOnly,
+ ParseImmQword_SizeOnly,
+ ParseTwoByteEsc,
+ ParseGrp1,
+ ParseShiftGrp2,
+ ParseGrp3,
+ ParseGrp4,
+ ParseGrp5,
+ Parse3DNow,
+ ParseGrp6,
+ ParseGrp7,
+ ParseGrp8,
+ ParseGrp9,
+ ParseGrp10,
+ ParseGrp12,
+ ParseGrp13,
+ ParseGrp14,
+ ParseGrp15,
+ ParseGrp16,
+ ParseGrp17,
+ ParseModFence,
+ ParseYv,
+ ParseYb,
+ ParseXv,
+ ParseXb,
+ ParseEscFP,
+ ParseNopPause,
+ ParseImmByteSX_SizeOnly,
+ ParseImmZ_SizeOnly,
+ ParseThreeByteEsc4,
+ ParseThreeByteEsc5,
+ ParseImmAddrF_SizeOnly,
+ ParseInvOpModRm,
+ ParseVex2b,
+ ParseVex3b,
+ ParseVexDest
+};
+
+
+
+
+
+/********************************************************************************************************************************
+ *
+ *
+ * Read functions for getting the opcode bytes
+ *
+ *
+ ********************************************************************************************************************************/
+
+/**
+ * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}
+ */
+static DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
+{
+#if 0 /*def IN_RING0 - why? */
+ RT_NOREF_PV(cbMinRead);
+ AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));
+ RT_BZERO(&pDis->abInstr[offInstr], cbMaxRead);
+ pDis->cbCachedInstr = offInstr + cbMaxRead;
+ return VERR_DIS_NO_READ_CALLBACK;
+#else
+ uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr;
+ size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
+ uint8_t cbToRead = cbLeftOnPage >= cbMaxRead
+ ? cbMaxRead
+ : cbLeftOnPage <= cbMinRead
+ ? cbMinRead
+ : (uint8_t)cbLeftOnPage;
+ memcpy(&pDis->abInstr[offInstr], pbSrc, cbToRead);
+ pDis->cbCachedInstr = offInstr + cbToRead;
+ return VINF_SUCCESS;
+#endif
+}
+
+
+/**
+ * Read more bytes into the DISSTATE::abInstr buffer, advance
+ * DISSTATE::cbCachedInstr.
+ *
+ * Will set DISSTATE::rc on failure, but still advance cbCachedInstr.
+ *
+ * The caller shall fend off reads beyond the DISSTATE::abInstr buffer.
+ *
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the read request.
+ * @param cbMin The size of the read request that needs to be
+ * satisfied.
+ */
+DECL_NO_INLINE(static, void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin)
+{
+ Assert(cbMin + offInstr <= sizeof(pDis->abInstr));
+
+ /*
+ * Adjust the incoming request to not overlap with bytes that has already
+ * been read and to make sure we don't leave unread gaps.
+ */
+ if (offInstr < pDis->cbCachedInstr)
+ {
+ Assert(offInstr + cbMin > pDis->cbCachedInstr);
+ cbMin -= pDis->cbCachedInstr - offInstr;
+ offInstr = pDis->cbCachedInstr;
+ }
+ else if (offInstr > pDis->cbCachedInstr)
+ {
+ cbMin += offInstr - pDis->cbCachedInstr;
+ offInstr = pDis->cbCachedInstr;
+ }
+
+ /*
+ * Do the read.
+ * (No need to zero anything on failure as abInstr is already zeroed by the
+ * DISInstrEx API.)
+ */
+ int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(pDis->cbCachedInstr >= offInstr + cbMin);
+ Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
+ }
+ else
+ {
+ Log(("disReadMore failed with rc=%Rrc!!\n", rc));
+ pDis->rc = rc;
+ }
+}
+
+
+/**
+ * Function for handling a 8-bit cache miss.
+ *
+ * @returns The requested byte.
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the byte relative to the
+ * instruction.
+ */
+DECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
+{
+ if (RT_LIKELY(offInstr < DIS_MAX_INSTR_LENGTH))
+ {
+ disReadMore(pDis, (uint8_t)offInstr, 1);
+ return pDis->abInstr[offInstr];
+ }
+
+ Log(("disReadByte: too long instruction...\n"));
+ pDis->rc = VERR_DIS_TOO_LONG_INSTR;
+ ssize_t cbLeft = (ssize_t)(sizeof(pDis->abInstr) - offInstr);
+ if (cbLeft > 0)
+ return pDis->abInstr[offInstr];
+ return 0;
+}
+
+
+/**
+ * Read a byte (8-bit) instruction.
+ *
+ * @returns The requested byte.
+ * @param pDis The disassembler state.
+ * @param uAddress The address.
+ */
+DECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
+{
+ if (offInstr >= pDis->cbCachedInstr)
+ return disReadByteSlow(pDis, offInstr);
+ return pDis->abInstr[offInstr];
+}
+
+
+/**
+ * Function for handling a 16-bit cache miss.
+ *
+ * @returns The requested word.
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the word relative to the
+ * instruction.
+ */
+DECL_NO_INLINE(static, uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr)
+{
+ if (RT_LIKELY(offInstr + 2 <= DIS_MAX_INSTR_LENGTH))
+ {
+ disReadMore(pDis, (uint8_t)offInstr, 2);
+#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
+ return *(uint16_t const *)&pDis->abInstr[offInstr];
+#else
+ return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
+#endif
+ }
+
+ Log(("disReadWord: too long instruction...\n"));
+ pDis->rc = VERR_DIS_TOO_LONG_INSTR;
+ ssize_t cbLeft = (ssize_t)(sizeof(pDis->abInstr) - offInstr);
+ switch (cbLeft)
+ {
+ case 1:
+ return pDis->abInstr[offInstr];
+ default:
+ if (cbLeft >= 2)
+ return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
+ return 0;
+ }
+}
+
+
+/**
+ * Read a word (16-bit) instruction.
+ *
+ * @returns The requested word.
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the qword relative to the
+ * instruction.
+ */
+DECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
+{
+ if (offInstr + 2 > pDis->cbCachedInstr)
+ return disReadWordSlow(pDis, offInstr);
+
+#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
+ return *(uint16_t const *)&pDis->abInstr[offInstr];
+#else
+ return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
+#endif
+}
+
+
+/**
+ * Function for handling a 32-bit cache miss.
+ *
+ * @returns The requested dword.
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the dword relative to the
+ * instruction.
+ */
+DECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
+{
+ if (RT_LIKELY(offInstr + 4 <= DIS_MAX_INSTR_LENGTH))
+ {
+ disReadMore(pDis, (uint8_t)offInstr, 4);
+#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
+ return *(uint32_t const *)&pDis->abInstr[offInstr];
+#else
+ return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
+#endif
+ }
+
+ Log(("disReadDWord: too long instruction...\n"));
+ pDis->rc = VERR_DIS_TOO_LONG_INSTR;
+ ssize_t cbLeft = (ssize_t)(sizeof(pDis->abInstr) - offInstr);
+ switch (cbLeft)
+ {
+ case 1:
+ return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
+ case 2:
+ return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
+ case 3:
+ return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
+ default:
+ if (cbLeft >= 4)
+ return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
+ return 0;
+ }
+}
+
+
+/**
+ * Read a dword (32-bit) instruction.
+ *
+ * @returns The requested dword.
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the qword relative to the
+ * instruction.
+ */
+DECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
+{
+ if (offInstr + 4 > pDis->cbCachedInstr)
+ return disReadDWordSlow(pDis, offInstr);
+
+#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
+ return *(uint32_t const *)&pDis->abInstr[offInstr];
+#else
+ return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
+#endif
+}
+
+
+/**
+ * Function for handling a 64-bit cache miss.
+ *
+ * @returns The requested qword.
+ * @param pDis The disassembler state.
+ * @param offInstr The offset of the qword relative to the
+ * instruction.
+ */
+DECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
+{
+ if (RT_LIKELY(offInstr + 8 <= DIS_MAX_INSTR_LENGTH))
+ {
+ disReadMore(pDis, (uint8_t)offInstr, 8);
+#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
+ return *(uint64_t const *)&pDis->abInstr[offInstr];
+#else
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
+ pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
+#endif
+ }
+
+ Log(("disReadQWord: too long instruction...\n"));
+ pDis->rc = VERR_DIS_TOO_LONG_INSTR;
+ ssize_t cbLeft = (ssize_t)(sizeof(pDis->abInstr) - offInstr);
+ switch (cbLeft)
+ {
+ case 1:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
+ case 2:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
+ case 3:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], 0, 0, 0, 0, 0);
+ case 4:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ 0, 0, 0, 0);
+ case 5:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ pDis->abInstr[offInstr + 4], 0, 0, 0);
+ case 6:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
+ 0, 0);
+ case 7:
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
+ pDis->abInstr[offInstr + 6], 0);
+ default:
+ if (cbLeft >= 8)
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
+ pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
+ return 0;
+ }
+}
+
+
+/**
+ * Read a qword (64-bit) instruction.
+ *
+ * @returns The requested qword.
+ * @param pDis The disassembler state.
+ * @param uAddress The address.
+ */
+DECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
+{
+ if (offInstr + 8 > pDis->cbCachedInstr)
+ return disReadQWordSlow(pDis, offInstr);
+
+#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
+ return *(uint64_t const *)&pDis->abInstr[offInstr];
+#else
+ return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
+ pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
+ pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
+ pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
+#endif
+}
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+static size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
+{
+ Assert(pOp); Assert(pDis);
+
+ // Store the opcode format string for disasmPrintf
+ pDis->pCurInstr = pOp;
+
+ /*
+ * Apply filter to instruction type to determine if a full disassembly is required.
+ * Note! Multibyte opcodes are always marked harmless until the final byte.
+ */
+ bool fFiltered;
+ if ((pOp->fOpType & pDis->fFilter) == 0)
+ {
+ fFiltered = true;
+ pDis->pfnDisasmFnTable = g_apfnCalcSize;
+ }
+ else
+ {
+ /* Not filtered out -> full disassembly */
+ fFiltered = false;
+ pDis->pfnDisasmFnTable = g_apfnFullDisasm;
+ }
+
+ // Should contain the parameter type on input
+ pDis->Param1.fParam = pOp->fParam1;
+ pDis->Param2.fParam = pOp->fParam2;
+ pDis->Param3.fParam = pOp->fParam3;
+ pDis->Param4.fParam = pOp->fParam4;
+
+ /* Correct the operand size if the instruction is marked as forced or default 64 bits */
+ if (!(pOp->fOpType & (DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_FORCED_32_OP_SIZE_X86)))
+ { /* probably likely */ }
+ else
+ {
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ {
+ if (pOp->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
+ pDis->uOpMode = DISCPUMODE_64BIT;
+ else if ( (pOp->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
+ && !(pDis->fPrefix & DISPREFIX_OPSIZE))
+ pDis->uOpMode = DISCPUMODE_64BIT;
+ }
+ else if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
+ {
+ /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
+ Assert(pDis->uCpuMode != DISCPUMODE_64BIT);
+ pDis->uOpMode = DISCPUMODE_32BIT;
+ }
+ }
+
+ if (pOp->idxParse1 != IDX_ParseNop)
+ {
+ offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
+ if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
+ }
+
+ if (pOp->idxParse2 != IDX_ParseNop)
+ {
+ offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
+ if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
+ }
+
+ if (pOp->idxParse3 != IDX_ParseNop)
+ {
+ offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
+ if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
+ }
+
+ if (pOp->idxParse4 != IDX_ParseNop)
+ {
+ offInstr = pDis->pfnDisasmFnTable[pOp->idxParse4](offInstr, pOp, pDis, &pDis->Param4);
+ if (fFiltered == false) pDis->Param4.cb = DISGetParamSize(pDis, &pDis->Param4);
+ }
+ // else simple one byte instruction
+
+ return offInstr;
+}
+//*****************************************************************************
+/* Floating point opcode parsing */
+//*****************************************************************************
+static size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ PCDISOPCODE fpop;
+ RT_NOREF_PV(pOp);
+
+ uint8_t ModRM = disReadByte(pDis, offInstr);
+ uint8_t index = pDis->bOpCode - 0xD8;
+ if (ModRM <= 0xBF)
+ {
+ fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
+ pDis->pCurInstr = fpop;
+
+ // Should contain the parameter type on input
+ pDis->Param1.fParam = fpop->fParam1;
+ pDis->Param2.fParam = fpop->fParam2;
+ }
+ else
+ {
+ fpop = &(g_apMapX86_FP_High[index])[ModRM - 0xC0];
+ pDis->pCurInstr = fpop;
+ }
+
+ /*
+ * Apply filter to instruction type to determine if a full disassembly is required.
+ * @note Multibyte opcodes are always marked harmless until the final byte.
+ */
+ if ((fpop->fOpType & pDis->fFilter) == 0)
+ pDis->pfnDisasmFnTable = g_apfnCalcSize;
+ else
+ /* Not filtered out -> full disassembly */
+ pDis->pfnDisasmFnTable = g_apfnFullDisasm;
+
+ /* Correct the operand size if the instruction is marked as forced or default 64 bits */
+ if ( pDis->uCpuMode != DISCPUMODE_64BIT
+ || !(fpop->fOpType & (DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_DEFAULT_64_OP_SIZE)))
+ { /* probably likely */ }
+ else
+ {
+ /* Note: redundant, but just in case this ever changes */
+ if (fpop->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
+ pDis->uOpMode = DISCPUMODE_64BIT;
+ else if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
+ && !(pDis->fPrefix & DISPREFIX_OPSIZE))
+ pDis->uOpMode = DISCPUMODE_64BIT;
+ }
+
+ // Little hack to make sure the ModRM byte is included in the returned size
+ if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
+ offInstr++; //ModRM byte
+
+ if (fpop->idxParse1 != IDX_ParseNop)
+ offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
+
+ if (fpop->idxParse2 != IDX_ParseNop)
+ offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
+
+ return offInstr;
+}
+
+
+/********************************************************************************************************************************
+ *
+ *
+ * SIB byte: (not 16-bit mode)
+ * 7 - 6 5 - 3 2-0
+ * Scale Index Base
+ *
+ *
+ ********************************************************************************************************************************/
+static void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ unsigned scale = pDis->SIB.Bits.Scale;
+ uint8_t base = pDis->SIB.Bits.Base;
+ uint8_t index = pDis->SIB.Bits.Index;
+
+ unsigned regtype, vregtype;
+ /* There's no way to distinguish between SIB and VSIB
+ * and having special parameter to parse explicitly VSIB
+ * is not an options since only one instruction (gather)
+ * supports it currently. May be changed in the future. */
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ regtype = DISUSE_REG_GEN32;
+ else
+ regtype = DISUSE_REG_GEN64;
+ if (pDis->pCurInstr->uOpcode == OP_GATHER)
+ vregtype = (VEXREG_IS256B(pDis->bVexDestReg) ? DISUSE_REG_YMM : DISUSE_REG_XMM);
+ else
+ vregtype = regtype;
+
+ if (index != 4)
+ {
+ pParam->fUse |= DISUSE_INDEX | vregtype;
+ pParam->Index.idxGenReg = index;
+
+ if (scale != 0)
+ {
+ pParam->fUse |= DISUSE_SCALE;
+ pParam->uScale = (uint8_t)(1 << scale);
+ }
+ }
+
+ if (base == 5 && pDis->ModRM.Bits.Mod == 0)
+ {
+ // [scaled index] + disp32
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ pParam->fUse |= DISUSE_DISPLACEMENT32;
+ pParam->uDisp.i32 = pDis->i32SibDisp;
+ }
+ else
+ { /* sign-extend to 64 bits */
+ pParam->fUse |= DISUSE_DISPLACEMENT64;
+ pParam->uDisp.i64 = pDis->i32SibDisp;
+ }
+ }
+ else
+ {
+ pParam->fUse |= DISUSE_BASE | regtype;
+ pParam->Base.idxGenReg = base;
+ }
+ return; /* Already fetched everything in ParseSIB; no size returned */
+}
+
+
+static size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ uint8_t SIB = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ pDis->SIB.Bits.Base = SIB_BASE(SIB);
+ pDis->SIB.Bits.Index = SIB_INDEX(SIB);
+ pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
+
+ if (pDis->fPrefix & DISPREFIX_REX)
+ {
+ /* REX.B extends the Base field if not scaled index + disp32 */
+ if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
+ pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
+
+ pDis->SIB.Bits.Index |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3;
+ }
+
+ if ( pDis->SIB.Bits.Base == 5
+ && pDis->ModRM.Bits.Mod == 0)
+ {
+ /* Additional 32 bits displacement. No change in long mode. */
+ pDis->i32SibDisp = (int32_t)disReadDWord(pDis, offInstr);
+ offInstr += 4;
+ }
+ return offInstr;
+}
+
+
+static size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ uint8_t SIB = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ pDis->SIB.Bits.Base = SIB_BASE(SIB);
+ pDis->SIB.Bits.Index = SIB_INDEX(SIB);
+ pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
+
+ if (pDis->fPrefix & DISPREFIX_REX)
+ {
+ /* REX.B extends the Base field. */
+ pDis->SIB.Bits.Base |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
+ /* REX.X extends the Index field. */
+ pDis->SIB.Bits.Index |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
+ }
+
+ if ( pDis->SIB.Bits.Base == 5
+ && pDis->ModRM.Bits.Mod == 0)
+ {
+ /* Additional 32 bits displacement. No change in long mode. */
+ offInstr += 4;
+ }
+ return offInstr;
+}
+
+
+
+/********************************************************************************************************************************
+ *
+ *
+ * ModR/M byte:
+ * 7 - 6 5 - 3 2-0
+ * Mod Reg/Opcode R/M
+ *
+ *
+ ********************************************************************************************************************************/
+static void disasmModRMReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, int fRegAddr)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pDis);
+
+#ifdef LOG_ENABLED
+ unsigned type = OP_PARM_VTYPE(pParam->fParam);
+#endif
+ unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
+ if (fRegAddr)
+ subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
+ else if (subtype == OP_PARM_v || subtype == OP_PARM_NONE || subtype == OP_PARM_y)
+ {
+ switch (pDis->uOpMode)
+ {
+ case DISCPUMODE_32BIT:
+ subtype = OP_PARM_d;
+ break;
+ case DISCPUMODE_64BIT:
+ subtype = OP_PARM_q;
+ break;
+ case DISCPUMODE_16BIT:
+ if (subtype != OP_PARM_y) /** @todo r=bird: This cannot be right! OP_PARM_y should translate to OP_PARM_d (32-bit), shouldn't it? */
+ subtype = OP_PARM_w;
+ break;
+ default:
+ /* make gcc happy */
+ break;
+ }
+ }
+
+ switch (subtype)
+ {
+ case OP_PARM_b:
+ Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
+
+ /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
+ /* Intel 64 and IA-32 Architectures Software Developer's Manual: 3.4.1.1 */
+ if ( (pDis->fPrefix & DISPREFIX_REX)
+ && idx >= DISGREG_AH
+ && idx <= DISGREG_BH)
+ {
+ idx += (DISGREG_SPL - DISGREG_AH);
+ }
+
+ pParam->fUse |= DISUSE_REG_GEN8;
+ pParam->Base.idxGenReg = (uint8_t)idx;
+ break;
+
+ case OP_PARM_w:
+ Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
+
+ pParam->fUse |= DISUSE_REG_GEN16;
+ pParam->Base.idxGenReg = (uint8_t)idx;
+ break;
+
+ case OP_PARM_d:
+ Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
+
+ if ( !(pOp->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE) /* Tweak for vpmovmskb & pmovmskb. */
+ || pDis->uOpMode != DISCPUMODE_64BIT)
+ pParam->fUse |= DISUSE_REG_GEN32;
+ else
+ pParam->fUse |= DISUSE_REG_GEN64;
+ pParam->Base.idxGenReg = (uint8_t)idx;
+ break;
+
+ case OP_PARM_q:
+ pParam->fUse |= DISUSE_REG_GEN64;
+ pParam->Base.idxGenReg = (uint8_t)idx;
+ break;
+
+ default:
+ Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
+ pDis->rc = VERR_DIS_INVALID_MODRM;
+ break;
+ }
+}
+
+
+static void disasmModRMReg16(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ static const uint8_t s_auBaseModRMReg16[8] =
+ { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX };
+
+ RT_NOREF_PV(pDis); RT_NOREF_PV(pOp);
+ pParam->fUse |= DISUSE_REG_GEN16;
+ pParam->Base.idxGenReg = s_auBaseModRMReg16[idx];
+ if (idx < 4)
+ {
+ static const uint8_t s_auIndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI };
+ pParam->fUse |= DISUSE_INDEX;
+ pParam->Index.idxGenReg = s_auIndexModRMReg16[idx];
+ }
+}
+
+
+static void disasmModRMSReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ if (idx >= DISSELREG_END)
+ {
+ Log(("disasmModRMSReg %d failed!!\n", idx));
+ pDis->rc = VERR_DIS_INVALID_PARAMETER;
+ return;
+ }
+
+ pParam->fUse |= DISUSE_REG_SEG;
+ pParam->Base.idxSegReg = (uint8_t)idx;
+}
+
+
+static size_t UseModRM(size_t const offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ unsigned vtype = OP_PARM_VTYPE(pParam->fParam);
+ uint8_t reg = pDis->ModRM.Bits.Reg;
+ uint8_t mod = pDis->ModRM.Bits.Mod;
+ uint8_t rm = pDis->ModRM.Bits.Rm;
+
+ switch (vtype)
+ {
+ case OP_PARM_G: //general purpose register
+ disasmModRMReg(reg, pOp, pDis, pParam, 0);
+ return offInstr;
+
+ default:
+ if (IS_OP_PARM_RARE(vtype))
+ {
+ switch (vtype)
+ {
+ case OP_PARM_C: //control register
+ pParam->fUse |= DISUSE_REG_CR;
+
+ if ( pDis->pCurInstr->uOpcode == OP_MOV_CR
+ && pDis->uOpMode == DISCPUMODE_32BIT
+ && (pDis->fPrefix & DISPREFIX_LOCK))
+ {
+ pDis->fPrefix &= ~DISPREFIX_LOCK;
+ pParam->Base.idxCtrlReg = DISCREG_CR8;
+ }
+ else
+ pParam->Base.idxCtrlReg = reg;
+ return offInstr;
+
+ case OP_PARM_D: //debug register
+ pParam->fUse |= DISUSE_REG_DBG;
+ pParam->Base.idxDbgReg = reg;
+ return offInstr;
+
+ case OP_PARM_Q: //MMX or memory operand
+ if (mod != 3)
+ break; /* memory operand */
+ reg = rm; /* the RM field specifies the xmm register */
+ RT_FALL_THRU();
+
+ case OP_PARM_P: //MMX register
+ reg &= 7; /* REX.R has no effect here */
+ pParam->fUse |= DISUSE_REG_MMX;
+ pParam->Base.idxMmxReg = reg;
+ return offInstr;
+
+ case OP_PARM_S: //segment register
+ reg &= 7; /* REX.R has no effect here */
+ disasmModRMSReg(reg, pOp, pDis, pParam);
+ pParam->fUse |= DISUSE_REG_SEG;
+ return offInstr;
+
+ case OP_PARM_T: //test register
+ reg &= 7; /* REX.R has no effect here */
+ pParam->fUse |= DISUSE_REG_TEST;
+ pParam->Base.idxTestReg = reg;
+ return offInstr;
+
+ case OP_PARM_W: //XMM register or memory operand
+ if (mod != 3)
+ break; /* memory operand */
+ RT_FALL_THRU();
+
+ case OP_PARM_U: // XMM/YMM register
+ reg = rm; /* the RM field specifies the xmm register */
+ RT_FALL_THRU();
+
+ case OP_PARM_V: //XMM register
+ if (VEXREG_IS256B(pDis->bVexDestReg)
+ && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_dq
+ && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_q
+ && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_d
+ && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_w)
+ {
+ // Use YMM register if VEX.L is set.
+ pParam->fUse |= DISUSE_REG_YMM;
+ pParam->Base.idxYmmReg = reg;
+ }
+ else
+ {
+ pParam->fUse |= DISUSE_REG_XMM;
+ pParam->Base.idxXmmReg = reg;
+ }
+ return offInstr;
+ }
+ }
+ }
+
+ /** @todo bound */
+
+ if (pDis->uAddrMode != DISCPUMODE_16BIT)
+ {
+ Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
+
+ /*
+ * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
+ */
+ switch (mod)
+ {
+ case 0: //effective address
+ if (rm == 4) /* SIB byte follows ModRM */
+ UseSIB(pDis, pParam);
+ else
+ if (rm == 5)
+ {
+ /* 32 bits displacement */
+ if (pDis->uCpuMode != DISCPUMODE_64BIT)
+ {
+ pParam->fUse |= DISUSE_DISPLACEMENT32;
+ pParam->uDisp.i32 = pDis->i32SibDisp;
+ }
+ else
+ {
+ pParam->fUse |= DISUSE_RIPDISPLACEMENT32;
+ pParam->uDisp.i32 = pDis->i32SibDisp;
+ }
+ }
+ else
+ { //register address
+ pParam->fUse |= DISUSE_BASE;
+ disasmModRMReg(rm, pOp, pDis, pParam, 1);
+ }
+ break;
+
+ case 1: //effective address + 8 bits displacement
+ if (rm == 4) /* SIB byte follows ModRM */
+ UseSIB(pDis, pParam);
+ else
+ {
+ pParam->fUse |= DISUSE_BASE;
+ disasmModRMReg(rm, pOp, pDis, pParam, 1);
+ }
+ pParam->uDisp.i8 = pDis->i32SibDisp;
+ pParam->fUse |= DISUSE_DISPLACEMENT8;
+ break;
+
+ case 2: //effective address + 32 bits displacement
+ if (rm == 4) /* SIB byte follows ModRM */
+ UseSIB(pDis, pParam);
+ else
+ {
+ pParam->fUse |= DISUSE_BASE;
+ disasmModRMReg(rm, pOp, pDis, pParam, 1);
+ }
+ pParam->uDisp.i32 = pDis->i32SibDisp;
+ pParam->fUse |= DISUSE_DISPLACEMENT32;
+ break;
+
+ case 3: //registers
+ disasmModRMReg(rm, pOp, pDis, pParam, 0);
+ break;
+ }
+ }
+ else
+ {//16 bits addressing mode
+ switch (mod)
+ {
+ case 0: //effective address
+ if (rm == 6)
+ {//16 bits displacement
+ pParam->uDisp.i16 = pDis->i32SibDisp;
+ pParam->fUse |= DISUSE_DISPLACEMENT16;
+ }
+ else
+ {
+ pParam->fUse |= DISUSE_BASE;
+ disasmModRMReg16(rm, pOp, pDis, pParam);
+ }
+ break;
+
+ case 1: //effective address + 8 bits displacement
+ disasmModRMReg16(rm, pOp, pDis, pParam);
+ pParam->uDisp.i8 = pDis->i32SibDisp;
+ pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT8;
+ break;
+
+ case 2: //effective address + 16 bits displacement
+ disasmModRMReg16(rm, pOp, pDis, pParam);
+ pParam->uDisp.i16 = pDis->i32SibDisp;
+ pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT16;
+ break;
+
+ case 3: //registers
+ disasmModRMReg(rm, pOp, pDis, pParam, 0);
+ break;
+ }
+ }
+ return offInstr;
+}
+//*****************************************************************************
+// Query the size of the ModRM parameters and fetch the immediate data (if any)
+//*****************************************************************************
+static size_t QueryModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ uint8_t mod = pDis->ModRM.Bits.Mod;
+ uint8_t rm = pDis->ModRM.Bits.Rm;
+
+ if (pDis->uAddrMode != DISCPUMODE_16BIT)
+ {
+ Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
+
+ /*
+ * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
+ */
+ if (mod != 3 && rm == 4) /* SIB byte follows ModRM */
+ offInstr = ParseSIB(offInstr, pOp, pDis, pParam);
+
+ switch (mod)
+ {
+ case 0: /* Effective address */
+ if (rm == 5) /* 32 bits displacement */
+ {
+ pDis->i32SibDisp = (int32_t)disReadDWord(pDis, offInstr);
+ offInstr += 4;
+ }
+ /* else register address */
+ break;
+
+ case 1: /* Effective address + 8 bits displacement */
+ pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
+ offInstr++;
+ break;
+
+ case 2: /* Effective address + 32 bits displacement */
+ pDis->i32SibDisp = (int32_t)disReadDWord(pDis, offInstr);
+ offInstr += 4;
+ break;
+
+ case 3: /* registers */
+ break;
+ }
+ }
+ else
+ {
+ /* 16 bits mode */
+ switch (mod)
+ {
+ case 0: /* Effective address */
+ if (rm == 6)
+ {
+ pDis->i32SibDisp = disReadWord(pDis, offInstr);
+ offInstr += 2;
+ }
+ /* else register address */
+ break;
+
+ case 1: /* Effective address + 8 bits displacement */
+ pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
+ offInstr++;
+ break;
+
+ case 2: /* Effective address + 32 bits displacement */
+ pDis->i32SibDisp = (int16_t)disReadWord(pDis, offInstr);
+ offInstr += 2;
+ break;
+
+ case 3: /* registers */
+ break;
+ }
+ }
+ return offInstr;
+}
+//*****************************************************************************
+// Parse the ModRM parameters and fetch the immediate data (if any)
+//*****************************************************************************
+static size_t QueryModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ uint8_t mod = pDis->ModRM.Bits.Mod;
+ uint8_t rm = pDis->ModRM.Bits.Rm;
+
+ if (pDis->uAddrMode != DISCPUMODE_16BIT)
+ {
+ Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
+ /*
+ * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
+ */
+ if (mod != 3 && rm == 4)
+ { /* SIB byte follows ModRM */
+ offInstr = ParseSIB_SizeOnly(offInstr, pOp, pDis, pParam);
+ }
+
+ switch (mod)
+ {
+ case 0: //effective address
+ if (rm == 5) /* 32 bits displacement */
+ offInstr += 4;
+ /* else register address */
+ break;
+
+ case 1: /* Effective address + 8 bits displacement */
+ offInstr += 1;
+ break;
+
+ case 2: /* Effective address + 32 bits displacement */
+ offInstr += 4;
+ break;
+
+ case 3: /* registers */
+ break;
+ }
+ }
+ else
+ {
+ /* 16 bits mode */
+ switch (mod)
+ {
+ case 0: //effective address
+ if (rm == 6)
+ offInstr += 2;
+ /* else register address */
+ break;
+
+ case 1: /* Effective address + 8 bits displacement */
+ offInstr++;
+ break;
+
+ case 2: /* Effective address + 32 bits displacement */
+ offInstr += 2;
+ break;
+
+ case 3: /* registers */
+ break;
+ }
+ }
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ AssertFailed();
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ uint8_t ModRM = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
+ pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
+ pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
+
+ /* Disregard the mod bits for certain instructions (mov crx, mov drx).
+ *
+ * From the AMD manual:
+ * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
+ * encoding of the MOD field in the MODR/M byte.
+ */
+ if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
+ pDis->ModRM.Bits.Mod = 3;
+
+ if (pDis->fPrefix & DISPREFIX_REX)
+ {
+ Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
+
+ /* REX.R extends the Reg field. */
+ pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
+
+ /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
+ if (!( pDis->ModRM.Bits.Mod != 3
+ && pDis->ModRM.Bits.Rm == 4)
+ &&
+ !( pDis->ModRM.Bits.Mod == 0
+ && pDis->ModRM.Bits.Rm == 5))
+ {
+ pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
+ }
+ }
+ offInstr = QueryModRM(offInstr, pOp, pDis, pParam);
+
+ return UseModRM(offInstr, pOp, pDis, pParam);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ uint8_t ModRM = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
+ pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
+ pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
+
+ /* Disregard the mod bits for certain instructions (mov crx, mov drx).
+ *
+ * From the AMD manual:
+ * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
+ * encoding of the MOD field in the MODR/M byte.
+ */
+ if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
+ pDis->ModRM.Bits.Mod = 3;
+
+ if (pDis->fPrefix & DISPREFIX_REX)
+ {
+ Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
+
+ /* REX.R extends the Reg field. */
+ pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
+
+ /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
+ if (!( pDis->ModRM.Bits.Mod != 3
+ && pDis->ModRM.Bits.Rm == 4)
+ &&
+ !( pDis->ModRM.Bits.Mod == 0
+ && pDis->ModRM.Bits.Rm == 5))
+ {
+ pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
+ }
+ }
+
+ offInstr = QueryModRM_SizeOnly(offInstr, pOp, pDis, pParam);
+
+ /* UseModRM is not necessary here; we're only interested in the opcode size */
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseModFence(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ /* Note! Only used in group 15, so we must account for the mod/rm byte. */
+ return offInstr + 1;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmByte(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ uint8_t byte = disReadByte(pDis, offInstr);
+ if (pParam->fParam == OP_PARM_Lx)
+ {
+ pParam->fUse |= (VEXREG_IS256B(pDis->bVexDestReg) ? DISUSE_REG_YMM : DISUSE_REG_XMM);
+
+ // Ignore MSB in 32-bit mode.
+ if (pDis->uCpuMode == DISCPUMODE_32BIT)
+ byte &= 0x7f;
+
+ pParam->Base.idxXmmReg = byte >> 4;
+ }
+ else
+ {
+ pParam->uValue = byte;
+ pParam->fUse |= DISUSE_IMMEDIATE8;
+ pParam->cb = sizeof(uint8_t);
+ }
+ return offInstr + 1;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmByte_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ return offInstr + 1;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmByteSX(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ {
+ pParam->uValue = (uint32_t)(int8_t)disReadByte(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE32_SX8;
+ pParam->cb = sizeof(uint32_t);
+ }
+ else
+ if (pDis->uOpMode == DISCPUMODE_64BIT)
+ {
+ pParam->uValue = (uint64_t)(int8_t)disReadByte(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE64_SX8;
+ pParam->cb = sizeof(uint64_t);
+ }
+ else
+ {
+ pParam->uValue = (uint16_t)(int8_t)disReadByte(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE16_SX8;
+ pParam->cb = sizeof(uint16_t);
+ }
+ return offInstr + 1;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmByteSX_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ return offInstr + 1;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmUshort(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ pParam->uValue = disReadWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE16;
+ pParam->cb = sizeof(uint16_t);
+ return offInstr + 2;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmUshort_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ return offInstr + 2;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmUlong(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE32;
+ pParam->cb = sizeof(uint32_t);
+ return offInstr + 4;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmUlong_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ return offInstr + 4;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmQword(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ pParam->uValue = disReadQWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE64;
+ pParam->cb = sizeof(uint64_t);
+ return offInstr + 8;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmQword_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ return offInstr + 8;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmV(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ {
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE32;
+ pParam->cb = sizeof(uint32_t);
+ return offInstr + 4;
+ }
+
+ if (pDis->uOpMode == DISCPUMODE_64BIT)
+ {
+ pParam->uValue = disReadQWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE64;
+ pParam->cb = sizeof(uint64_t);
+ return offInstr + 8;
+ }
+
+ pParam->uValue = disReadWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE16;
+ pParam->cb = sizeof(uint16_t);
+ return offInstr + 2;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmV_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ return offInstr + 4;
+ if (pDis->uOpMode == DISCPUMODE_64BIT)
+ return offInstr + 8;
+ return offInstr + 2;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmZ(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
+ if (pDis->uOpMode == DISCPUMODE_16BIT)
+ {
+ pParam->uValue = disReadWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE16;
+ pParam->cb = sizeof(uint16_t);
+ return offInstr + 2;
+ }
+
+ /* 64 bits op mode means *sign* extend to 64 bits. */
+ if (pDis->uOpMode == DISCPUMODE_64BIT)
+ {
+ pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE64;
+ pParam->cb = sizeof(uint64_t);
+ }
+ else
+ {
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE32;
+ pParam->cb = sizeof(uint32_t);
+ }
+ return offInstr + 4;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmZ_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+ /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
+ if (pDis->uOpMode == DISCPUMODE_16BIT)
+ return offInstr + 2;
+ return offInstr + 4;
+}
+
+//*****************************************************************************
+// Relative displacement for branches (rel. to next instruction)
+//*****************************************************************************
+static size_t ParseImmBRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ pParam->uValue = disReadByte(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE8_REL;
+ pParam->cb = sizeof(uint8_t);
+ return offInstr + 1;
+}
+//*****************************************************************************
+// Relative displacement for branches (rel. to next instruction)
+//*****************************************************************************
+static size_t ParseImmBRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
+ return offInstr + 1;
+}
+//*****************************************************************************
+// Relative displacement for branches (rel. to next instruction)
+//*****************************************************************************
+static size_t ParseImmVRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ {
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE32_REL;
+ pParam->cb = sizeof(int32_t);
+ return offInstr + 4;
+ }
+
+ if (pDis->uOpMode == DISCPUMODE_64BIT)
+ {
+ /* 32 bits relative immediate sign extended to 64 bits. */
+ pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE64_REL;
+ pParam->cb = sizeof(int64_t);
+ return offInstr + 4;
+ }
+
+ pParam->uValue = disReadWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE16_REL;
+ pParam->cb = sizeof(int16_t);
+ return offInstr + 2;
+}
+//*****************************************************************************
+// Relative displacement for branches (rel. to next instruction)
+//*****************************************************************************
+static size_t ParseImmVRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+ if (pDis->uOpMode == DISCPUMODE_16BIT)
+ return offInstr + 2;
+ /* Both 32 & 64 bits mode use 32 bits relative immediates. */
+ return offInstr + 4;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmAddr(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
+ {
+ /* far 16:32 pointer */
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
+ pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
+ pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
+ return offInstr + 4 + 2;
+ }
+
+ /*
+ * near 32 bits pointer
+ *
+ * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
+ * so we treat it like displacement.
+ */
+ pParam->uDisp.u32 = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_DISPLACEMENT32;
+ pParam->cb = sizeof(uint32_t);
+ return offInstr + 4;
+ }
+
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ {
+ /*
+ * near 64 bits pointer
+ *
+ * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
+ * so we treat it like displacement.
+ */
+ Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
+ pParam->uDisp.u64 = disReadQWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_DISPLACEMENT64;
+ pParam->cb = sizeof(uint64_t);
+ return offInstr + 8;
+ }
+ if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
+ {
+ /* far 16:16 pointer */
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
+ pParam->cb = 2*sizeof(uint16_t);
+ return offInstr + 4;
+ }
+
+ /*
+ * near 16 bits pointer
+ *
+ * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
+ * so we treat it like displacement.
+ */
+ pParam->uDisp.i16 = disReadWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_DISPLACEMENT16;
+ pParam->cb = sizeof(uint16_t);
+ return offInstr + 2;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp);
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
+ return offInstr + 4 + 2; /* far 16:32 pointer */
+ return offInstr + 4; /* near 32 bits pointer */
+ }
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ {
+ Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
+ return offInstr + 8;
+ }
+ if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
+ return offInstr + 4; /* far 16:16 pointer */
+ return offInstr + 2; /* near 16 bits pointer */
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+ // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
+ Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
+ Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ {
+ // far 16:32 pointer
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
+ pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
+ pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
+ return offInstr + 4 + 2;
+ }
+
+ // far 16:16 pointer
+ pParam->uValue = disReadDWord(pDis, offInstr);
+ pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
+ pParam->cb = 2*sizeof(uint16_t);
+ return offInstr + 2 + 2;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr); RT_NOREF_PV(pOp);
+ // immediate far pointers - only 16:16 or 16:32
+ Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
+ Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p); RT_NOREF_PV(pParam);
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ return offInstr + 4 + 2; /* far 16:32 pointer */
+ return offInstr + 2 + 2; /* far 16:16 pointer */
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(offInstr);
+
+ /*
+ * Sets up flags for stored in OPC fixed registers.
+ */
+
+ if (pParam->fParam == OP_PARM_NONE)
+ {
+ /* No parameter at all. */
+ return offInstr;
+ }
+
+ AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
+ AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
+ AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
+ AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
+
+ if (pParam->fParam <= OP_PARM_REG_GEN32_END)
+ {
+ /* 32-bit EAX..EDI registers. */
+ if (pDis->uOpMode == DISCPUMODE_32BIT)
+ {
+ /* Use 32-bit registers. */
+ pParam->Base.idxGenReg = (uint8_t)(pParam->fParam - OP_PARM_REG_GEN32_START);
+ pParam->fUse |= DISUSE_REG_GEN32;
+ pParam->cb = 4;
+ }
+ else if (pDis->uOpMode == DISCPUMODE_64BIT)
+ {
+ /* Use 64-bit registers. */
+ pParam->Base.idxGenReg = (uint8_t)(pParam->fParam - OP_PARM_REG_GEN32_START);
+ pParam->fUse |= DISUSE_REG_GEN64;
+ pParam->cb = 8;
+ }
+ else
+ {
+ /* Use 16-bit registers. */
+ pParam->Base.idxGenReg = (uint8_t)(pParam->fParam - OP_PARM_REG_GEN32_START);
+ pParam->fUse |= DISUSE_REG_GEN16;
+ pParam->cb = 2;
+ pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
+ }
+
+ if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
+ && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
+ && (pDis->fPrefix & DISPREFIX_REX)
+ && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B))
+ {
+ Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
+ pParam->Base.idxGenReg += 8;
+ }
+ }
+ else if (pParam->fParam <= OP_PARM_REG_SEG_END)
+ {
+ /* Segment ES..GS registers. */
+ pParam->Base.idxSegReg = (uint8_t)(pParam->fParam - OP_PARM_REG_SEG_START);
+ pParam->fUse |= DISUSE_REG_SEG;
+ pParam->cb = 2;
+ }
+ else if (pParam->fParam <= OP_PARM_REG_GEN16_END)
+ {
+ /* 16-bit AX..DI registers. */
+ pParam->Base.idxGenReg = (uint8_t)(pParam->fParam - OP_PARM_REG_GEN16_START);
+ pParam->fUse |= DISUSE_REG_GEN16;
+ pParam->cb = 2;
+ }
+ else if (pParam->fParam <= OP_PARM_REG_GEN8_END)
+ {
+ /* 8-bit AL..DL, AH..DH registers. */
+ pParam->Base.idxGenReg = (uint8_t)(pParam->fParam - OP_PARM_REG_GEN8_START);
+ pParam->fUse |= DISUSE_REG_GEN8;
+ pParam->cb = 1;
+
+ if ( pDis->uCpuMode == DISCPUMODE_64BIT
+ && (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
+ && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
+ && (pDis->fPrefix & DISPREFIX_REX))
+ {
+ if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)
+ pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
+ else if ( pParam->Base.idxGenReg >= DISGREG_AH
+ && pParam->Base.idxGenReg <= DISGREG_BH)
+ pParam->Base.idxGenReg += DISGREG_SPL - DISGREG_AH;
+ }
+ }
+ else if (pParam->fParam <= OP_PARM_REG_FP_END)
+ {
+ /* FPU registers. */
+ pParam->Base.idxFpuReg = (uint8_t)(pParam->fParam - OP_PARM_REG_FP_START);
+ pParam->fUse |= DISUSE_REG_FP;
+ pParam->cb = 10;
+ }
+ Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
+
+ /* else - not supported for now registers. */
+
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+
+ pParam->fUse |= DISUSE_POINTER_DS_BASED;
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_ESI;
+ pParam->fUse |= DISUSE_REG_GEN32;
+ }
+ else
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_RSI;
+ pParam->fUse |= DISUSE_REG_GEN64;
+ }
+ else
+ {
+ pParam->Base.idxGenReg = DISGREG_SI;
+ pParam->fUse |= DISUSE_REG_GEN16;
+ }
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+
+ pParam->fUse |= DISUSE_POINTER_DS_BASED;
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_ESI;
+ pParam->fUse |= DISUSE_REG_GEN32;
+ }
+ else
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_RSI;
+ pParam->fUse |= DISUSE_REG_GEN64;
+ }
+ else
+ {
+ pParam->Base.idxGenReg = DISGREG_SI;
+ pParam->fUse |= DISUSE_REG_GEN16;
+ }
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+
+ pParam->fUse |= DISUSE_POINTER_ES_BASED;
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_EDI;
+ pParam->fUse |= DISUSE_REG_GEN32;
+ }
+ else
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_RDI;
+ pParam->fUse |= DISUSE_REG_GEN64;
+ }
+ else
+ {
+ pParam->Base.idxGenReg = DISGREG_DI;
+ pParam->fUse |= DISUSE_REG_GEN16;
+ }
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+
+ pParam->fUse |= DISUSE_POINTER_ES_BASED;
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_EDI;
+ pParam->fUse |= DISUSE_REG_GEN32;
+ }
+ else
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ {
+ pParam->Base.idxGenReg = DISGREG_RDI;
+ pParam->fUse |= DISUSE_REG_GEN64;
+ }
+ else
+ {
+ pParam->Base.idxGenReg = DISGREG_DI;
+ pParam->fUse |= DISUSE_REG_GEN16;
+ }
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pDis); RT_NOREF_PV(pParam);
+ /* This is used to avoid a bunch of special hacks to get the ModRM byte
+ included when encountering invalid opcodes in groups. */
+ return offInstr + 1;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseVexDest(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp);
+
+ unsigned type = OP_PARM_VTYPE(pParam->fParam);
+ switch (type)
+ {
+ case OP_PARM_H: //XMM or YMM register
+ if (VEXREG_IS256B(pDis->bVexDestReg))
+ {
+ pParam->fUse |= DISUSE_REG_YMM;
+ pParam->Base.idxYmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
+ }
+ else
+ {
+ pParam->fUse |= DISUSE_REG_XMM;
+ pParam->Base.idxXmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
+ }
+ break;
+
+ case OP_PARM_B: // Always OP_PARM_By. Change if it is not so.
+ if (pDis->bVexWFlag && pDis->uCpuMode == DISCPUMODE_64BIT)
+ pParam->fUse |= DISUSE_REG_GEN64;
+ else
+ pParam->fUse |= DISUSE_REG_GEN32;
+ /// @todo Check if the register number is correct
+ pParam->Base.idxGenReg = (pDis->bVexDestReg >> 1) ^ 0xf;
+ break;
+ }
+
+ return offInstr;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ /* 2nd byte */
+ pDis->bOpCode = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ /* default to the non-prefixed table. */
+ PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
+
+ /* Handle opcode table extensions that rely on the opsize, repe or repne prefix byte. */
+ /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
+ if (pDis->bLastPrefix)
+ {
+ switch (pDis->bLastPrefix)
+ {
+ case OP_OPSIZE: /* 0x66 */
+ if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+ pOpcode = &g_aTwoByteMapX86_PF66[pDis->bOpCode];
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_OPSIZE;
+
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ {
+ pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
+ }
+ else
+ pDis->uOpMode = pDis->uCpuMode;
+ }
+ break;
+
+ case OP_REPNE: /* 0xF2 */
+ if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+ pOpcode = &g_aTwoByteMapX86_PFF2[pDis->bOpCode];
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_REPNE;
+ }
+ break;
+
+ case OP_REPE: /* 0xF3 */
+ if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+ pOpcode = &g_aTwoByteMapX86_PFF3[pDis->bOpCode];
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_REP;
+ }
+ break;
+ }
+ }
+
+ return disParseInstruction(offInstr, pOpcode, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ /* 3rd byte */
+ pDis->bOpCode = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ /* default to the non-prefixed table. */
+ PCDISOPCODE pOpcode;
+ if (g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4])
+ {
+ pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+ }
+ else
+ pOpcode = &g_InvalidOpcode[0];
+
+ /* Handle opcode table extensions that rely on the address, repne prefix byte. */
+ /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
+ switch (pDis->bLastPrefix)
+ {
+ case OP_OPSIZE: /* 0x66 */
+ if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
+ {
+ pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+
+ if (pOpcode->uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_OPSIZE;
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ {
+ pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
+ }
+ else
+ pDis->uOpMode = pDis->uCpuMode;
+
+ }
+ }
+ break;
+
+ case OP_REPNE: /* 0xF2 */
+ if ((pDis->fPrefix & DISPREFIX_OPSIZE) && g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4])
+ {
+ /* 0x66F2 */
+ pOpcode = g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+
+ if (pOpcode->uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_REPNE;
+ pDis->fPrefix &= ~DISPREFIX_OPSIZE;
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ {
+ pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
+ }
+ else
+ pDis->uOpMode = pDis->uCpuMode;
+ }
+ }
+ else if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
+ {
+ pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+
+ if (pOpcode->uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_REPNE;
+ }
+ }
+ break;
+
+ case OP_REPE: /* 0xF3 */
+ if (g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4])
+ {
+ pOpcode = g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+
+ if (pOpcode->uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_REP;
+ }
+ }
+ }
+
+ return disParseInstruction(offInstr, pOpcode, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ /* 3rd byte */
+ pDis->bOpCode = disReadByte(pDis, offInstr);
+ offInstr++;
+
+ /* default to the non-prefixed table. */
+ PCDISOPCODE pOpcode;
+ if (g_apThreeByteMapX86_0F3A[pDis->bOpCode >> 4])
+ {
+ pOpcode = g_apThreeByteMapX86_0F3A[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+ }
+ else
+ pOpcode = &g_InvalidOpcode[0];
+
+ /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
+ if (pDis->bLastPrefix == OP_OPSIZE && g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
+ {
+ pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
+ pOpcode = &pOpcode[pDis->bOpCode & 0xf];
+
+ if (pOpcode->uOpcode != OP_INVALID)
+ {
+ /* Table entry is valid, so use the extension table. */
+
+ /* Cancel prefix changes. */
+ pDis->fPrefix &= ~DISPREFIX_OPSIZE;
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ {
+ pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
+ }
+ else
+ pDis->uOpMode = pDis->uCpuMode;
+
+ }
+ }
+
+ return disParseInstruction(offInstr, pOpcode, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ if (pDis->fPrefix & DISPREFIX_REP)
+ {
+ pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
+ pDis->fPrefix &= ~DISPREFIX_REP;
+ }
+ else
+ pOp = &g_aMapX86_NopPause[0]; /* NOP */
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp1(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+ unsigned idx = (pDis->bOpCode - 0x80) * 8;
+
+ pOp = &g_aMapX86_Group1[idx+reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ unsigned idx;
+ switch (pDis->bOpCode)
+ {
+ case 0xC0:
+ case 0xC1:
+ idx = (pDis->bOpCode - 0xC0)*8;
+ break;
+
+ case 0xD0:
+ case 0xD1:
+ case 0xD2:
+ case 0xD3:
+ idx = (pDis->bOpCode - 0xD0 + 2)*8;
+ break;
+
+ default:
+ Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
+ pDis->rc = VERR_DIS_INVALID_OPCODE;
+ return offInstr;
+ }
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group2[idx+reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ unsigned idx = (pDis->bOpCode - 0xF6) * 8;
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group3[idx+reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group4[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group5[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
+// It would appear the ModRM byte must always be present. How else can you
+// determine the offset of the imm8_opcode byte otherwise?
+//
+//*****************************************************************************
+static size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ /** @todo This code needs testing! Esp. wrt invalid opcodes. */
+
+ uint8_t ModRM = disReadByte(pDis, offInstr);
+ pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
+ pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
+ pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
+
+ size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
+
+ uint8_t opcode = disReadByte(pDis, offRet);
+ offRet++;
+ pOp = &g_aTwoByteMapX86_3DNow[opcode];
+
+ size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
+
+ AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
+ ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
+ RT_NOREF_PV(offStrict);
+
+ return offRet;
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group6[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t mod = MODRM_MOD(modrm);
+ uint8_t reg = MODRM_REG(modrm);
+ uint8_t rm = MODRM_RM(modrm);
+
+ if (mod == 3 && rm == 0)
+ pOp = &g_aMapX86_Group7_mod11_rm000[reg];
+ else
+ if (mod == 3 && rm == 1)
+ pOp = &g_aMapX86_Group7_mod11_rm001[reg];
+ else
+ pOp = &g_aMapX86_Group7_mem[reg];
+
+ /* Cannot easily skip this hack because of monitor and vmcall! */
+ //little hack to make sure the ModRM byte is included in the returned size
+ if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
+ offInstr++;
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group8[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group9[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ pOp = &g_aMapX86_Group10[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+
+ if (pDis->fPrefix & DISPREFIX_OPSIZE)
+ reg += 8; /* 2nd table */
+
+ pOp = &g_aMapX86_Group12[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+ if (pDis->fPrefix & DISPREFIX_OPSIZE)
+ reg += 8; /* 2nd table */
+
+ pOp = &g_aMapX86_Group13[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t reg = MODRM_REG(modrm);
+ if (pDis->fPrefix & DISPREFIX_OPSIZE)
+ reg += 8; /* 2nd table */
+
+ pOp = &g_aMapX86_Group14[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ uint8_t mod = MODRM_MOD(modrm);
+ uint8_t reg = MODRM_REG(modrm);
+ uint8_t rm = MODRM_RM(modrm);
+
+ if (mod == 3 && rm == 0)
+ pOp = &g_aMapX86_Group15_mod11_rm000[reg];
+ else
+ pOp = &g_aMapX86_Group15_mem[reg];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t modrm = disReadByte(pDis, offInstr);
+ pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+
+
+/**
+ * Parses (vex) group 17.
+ */
+static size_t ParseGrp17(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pParam);
+
+ uint8_t const bRm = disReadByte(pDis, offInstr);
+ pOp = &g_aMapX86_Group17[(MODRM_REG(bRm) << 1) | (pDis->bVexDestReg & 1)];
+
+ return disParseInstruction(offInstr, pOp, pDis);
+}
+
+
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseVex2b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ uint8_t byte = disReadByte(pDis, offInstr++);
+ pDis->bOpCode = disReadByte(pDis, offInstr++);
+
+ pDis->bVexDestReg = VEX_2B2INT(byte);
+
+ // VEX.R (equivalent to REX.R)
+ if (pDis->uCpuMode == DISCPUMODE_64BIT && !(byte & 0x80))
+ {
+ /* REX prefix byte */
+ pDis->fPrefix |= DISPREFIX_REX;
+ pDis->fRexPrefix = DISPREFIX_REX_FLAGS_R;
+ }
+
+ PCDISOPMAPDESC const pRange = g_aapVexOpcodesMapRanges[byte & 3][1];
+ unsigned const idxOpcode = pDis->bOpCode - pRange->idxFirst;
+ PCDISOPCODE pOpCode;
+ if (idxOpcode < pRange->cOpcodes)
+ pOpCode = &pRange->papOpcodes[idxOpcode];
+ else
+ pOpCode = &g_InvalidOpcode[0];
+
+ return disParseInstruction(offInstr, pOpCode, pDis);
+}
+//*****************************************************************************
+//*****************************************************************************
+static size_t ParseVex3b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
+{
+ RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
+
+ uint8_t byte1 = disReadByte(pDis, offInstr++);
+ uint8_t byte2 = disReadByte(pDis, offInstr++);
+ pDis->bOpCode = disReadByte(pDis, offInstr++);
+ pDis->bVexDestReg = VEX_2B2INT(byte2); /** @todo r=bird: why on earth ~vvvv + L; this is obfuscation non-sense. Either split the shit up or just store byte2 raw here! */
+
+ // VEX.W
+ pDis->bVexWFlag = !!(byte2 & 0x80); /** @todo r=bird: why a whole byte for this one flag? bVexWFlag and bVexDestReg makes little sense. */
+
+ /* Hack alert! Assume VEX.W rules over any 66h prefix and that no VEX
+ encoded instructions ever uses the regular uOpMode w/o VEX.W. */
+ pDis->uOpMode = (byte2 & 0x80) && pDis->uCpuMode == DISCPUMODE_64BIT ? DISCPUMODE_64BIT : DISCPUMODE_32BIT;
+
+ // VEX.~R~X~B => REX.RXB
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ {
+ pDis->fRexPrefix |= (byte1 >> 5) ^ 7;
+ if (pDis->fRexPrefix)
+ pDis->fPrefix |= DISPREFIX_REX;
+ }
+
+ PCDISOPCODE pOpCode;
+ uint8_t const idxVexMap = byte1 & 0x1f;
+ if (idxVexMap < RT_ELEMENTS(g_aapVexOpcodesMapRanges[byte2 & 3]))
+ {
+ PCDISOPMAPDESC const pRange = g_aapVexOpcodesMapRanges[byte2 & 3][idxVexMap];
+ unsigned const idxOpcode = pDis->bOpCode - pRange->idxFirst;
+ if (idxOpcode < pRange->cOpcodes)
+ pOpCode = &pRange->papOpcodes[idxOpcode];
+ else
+ pOpCode = &g_InvalidOpcode[0];
+ }
+ else
+ pOpCode = &g_InvalidOpcode[0];
+
+ 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 const bCode = disReadByte(pDis, offInstr++);
+ enum OPCODES const enmOpcode = (enum OPCODES)paOneByteMap[bCode].uOpcode;
+
+ /* Hardcoded assumption about OP_* values!! */
+ if (enmOpcode <= OP_LAST_PREFIX)
+ {
+ /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
+ if (enmOpcode != OP_REX)
+ {
+ /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
+ pDis->bLastPrefix = (uint8_t)enmOpcode;
+ pDis->fPrefix &= ~DISPREFIX_REX;
+ }
+
+ switch (enmOpcode)
+ {
+ 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 = (uint8_t)(paOneByteMap[bCode].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 = (uint8_t)DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[bCode].fParam1);
+ if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
+ pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
+ continue; //fetch the next byte
+ default:
+ AssertFailed();
+ break;
+ }
+ }
+
+ /* Check if this is a VEX prefix. Not for 32-bit mode. */
+ if (pDis->uCpuMode != DISCPUMODE_64BIT
+ && (enmOpcode == OP_LES || enmOpcode == OP_LDS)
+ && (disReadByte(pDis, offInstr) & 0xc0) == 0xc0)
+ {
+ paOneByteMap = g_aOneByteMapX64;
+ }
+
+ /* first opcode byte. */
+ pDis->bOpCode = bCode;
+ pDis->cbPrefix = (uint8_t)offInstr - 1;
+
+ offInstr = disParseInstruction(offInstr, &paOneByteMap[bCode], 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 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 = (uint8_t)enmCpuMode;
+ PCDISOPCODE paOneByteMap;
+ if (enmCpuMode == DISCPUMODE_64BIT)
+ {
+ pDis->uAddrMode = DISCPUMODE_64BIT;
+ pDis->uOpMode = DISCPUMODE_32BIT;
+ paOneByteMap = g_aOneByteMapX64;
+ }
+ else
+ {
+ pDis->uAddrMode = (uint8_t)enmCpuMode;
+ pDis->uOpMode = (uint8_t)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);
+}
+
diff --git a/src/VBox/Disassembler/DisasmFormatBytes.cpp b/src/VBox/Disassembler/DisasmFormatBytes.cpp
new file mode 100644
index 00000000..f012d15b
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmFormatBytes.cpp
@@ -0,0 +1,97 @@
+/* $Id: DisasmFormatBytes.cpp $ */
+/** @file
+ * VBox Disassembler - Helper for formatting the opcode bytes.
+ */
+
+/*
+ * Copyright (C) 2008-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "DisasmInternal.h"
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+
+
+/**
+ * Helper function for formatting the opcode bytes.
+ *
+ * @returns The number of output bytes.
+ *
+ * @param pDis Pointer to the disassembler state.
+ * @param pszDst The output buffer.
+ * @param cchDst The size of the output buffer.
+ * @param fFlags The flags passed to the formatter.
+ */
+size_t disFormatBytes(PCDISSTATE pDis, char *pszDst, size_t cchDst, uint32_t fFlags)
+{
+ size_t cchOutput = 0;
+ uint32_t cb = pDis->cbInstr;
+ AssertStmt(cb <= 16, cb = 16);
+
+#define PUT_C(ch) \
+ do { \
+ cchOutput++; \
+ if (cchDst > 1) \
+ { \
+ cchDst--; \
+ *pszDst++ = (ch); \
+ } \
+ } while (0)
+#define PUT_NUM(cch, fmt, num) \
+ do { \
+ cchOutput += (cch); \
+ if (cchDst > 1) \
+ { \
+ const size_t cchTmp = RTStrPrintf(pszDst, cchDst, fmt, (num)); \
+ pszDst += cchTmp; \
+ cchDst -= cchTmp; \
+ } \
+ } while (0)
+
+
+ if (fFlags & DIS_FMT_FLAGS_BYTES_BRACKETS)
+ PUT_C('[');
+
+ for (uint32_t i = 0; i < cb; i++)
+ {
+ if (i != 0 && (fFlags & DIS_FMT_FLAGS_BYTES_SPACED))
+ PUT_NUM(3, " %02x", pDis->abInstr[i]);
+ else
+ PUT_NUM(2, "%02x", pDis->abInstr[i]);
+ }
+
+ if (fFlags & DIS_FMT_FLAGS_BYTES_BRACKETS)
+ PUT_C(']');
+
+ /* Terminate it just in case. */
+ if (cchDst >= 1)
+ *pszDst = '\0';
+
+#undef PUT_C
+#undef PUT_NUM
+ return cchOutput;
+}
+
diff --git a/src/VBox/Disassembler/DisasmFormatYasm.cpp b/src/VBox/Disassembler/DisasmFormatYasm.cpp
new file mode 100644
index 00000000..4be9e043
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmFormatYasm.cpp
@@ -0,0 +1,1765 @@
+/* $Id: DisasmFormatYasm.cpp $ */
+/** @file
+ * VBox Disassembler - Yasm(/Nasm) Style Formatter.
+ */
+
+/*
+ * Copyright (C) 2008-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include "DisasmInternal.h"
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+static const char g_szSpaces[] =
+" ";
+static const char g_aszYasmRegGen8[20][5] =
+{
+ "al\0\0", "cl\0\0", "dl\0\0", "bl\0\0", "ah\0\0", "ch\0\0", "dh\0\0", "bh\0\0", "r8b\0", "r9b\0", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "spl\0", "bpl\0", "sil\0", "dil\0"
+};
+static const char g_aszYasmRegGen16[16][5] =
+{
+ "ax\0\0", "cx\0\0", "dx\0\0", "bx\0\0", "sp\0\0", "bp\0\0", "si\0\0", "di\0\0", "r8w\0", "r9w\0", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
+};
+#if 0 /* unused */
+static const char g_aszYasmRegGen1616[8][6] =
+{
+ "bx+si", "bx+di", "bp+si", "bp+di", "si\0\0\0", "di\0\0\0", "bp\0\0\0", "bx\0\0\0"
+};
+#endif
+static const char g_aszYasmRegGen32[16][5] =
+{
+ "eax\0", "ecx\0", "edx\0", "ebx\0", "esp\0", "ebp\0", "esi\0", "edi\0", "r8d\0", "r9d\0", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+};
+static const char g_aszYasmRegGen64[16][4] =
+{
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8\0", "r9\0", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+static const char g_aszYasmRegSeg[6][3] =
+{
+ "es", "cs", "ss", "ds", "fs", "gs"
+};
+static const char g_aszYasmRegFP[8][4] =
+{
+ "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
+};
+static const char g_aszYasmRegMMX[8][4] =
+{
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
+};
+static const char g_aszYasmRegXMM[16][6] =
+{
+ "xmm0\0", "xmm1\0", "xmm2\0", "xmm3\0", "xmm4\0", "xmm5\0", "xmm6\0", "xmm7\0", "xmm8\0", "xmm9\0", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
+};
+static const char g_aszYasmRegYMM[16][6] =
+{
+ "ymm0\0", "ymm1\0", "ymm2\0", "ymm3\0", "ymm4\0", "ymm5\0", "ymm6\0", "ymm7\0", "ymm8\0", "ymm9\0", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"
+};
+static const char g_aszYasmRegCRx[16][5] =
+{
+ "cr0\0", "cr1\0", "cr2\0", "cr3\0", "cr4\0", "cr5\0", "cr6\0", "cr7\0", "cr8\0", "cr9\0", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15"
+};
+static const char g_aszYasmRegDRx[16][5] =
+{
+ "dr0\0", "dr1\0", "dr2\0", "dr3\0", "dr4\0", "dr5\0", "dr6\0", "dr7\0", "dr8\0", "dr9\0", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
+};
+static const char g_aszYasmRegTRx[16][5] =
+{
+ "tr0\0", "tr1\0", "tr2\0", "tr3\0", "tr4\0", "tr5\0", "tr6\0", "tr7\0", "tr8\0", "tr9\0", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15"
+};
+
+
+
+/**
+ * Gets the base register name for the given parameter.
+ *
+ * @returns Pointer to the register name.
+ * @param pDis The disassembler state.
+ * @param pParam The parameter.
+ * @param pcchReg Where to store the length of the name.
+ */
+static const char *disasmFormatYasmBaseReg(PCDISSTATE pDis, PCDISOPPARAM pParam, size_t *pcchReg)
+{
+ RT_NOREF_PV(pDis);
+
+ switch (pParam->fUse & ( DISUSE_REG_GEN8 | DISUSE_REG_GEN16 | DISUSE_REG_GEN32 | DISUSE_REG_GEN64
+ | DISUSE_REG_FP | DISUSE_REG_MMX | DISUSE_REG_XMM | DISUSE_REG_YMM
+ | DISUSE_REG_CR | DISUSE_REG_DBG | DISUSE_REG_SEG | DISUSE_REG_TEST))
+
+ {
+ case DISUSE_REG_GEN8:
+ {
+ Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen8));
+ const char *psz = g_aszYasmRegGen8[pParam->Base.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ case DISUSE_REG_GEN16:
+ {
+ Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen16));
+ const char *psz = g_aszYasmRegGen16[pParam->Base.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ // VSIB
+ case DISUSE_REG_XMM | DISUSE_REG_GEN32:
+ case DISUSE_REG_YMM | DISUSE_REG_GEN32:
+ case DISUSE_REG_GEN32:
+ {
+ Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen32));
+ const char *psz = g_aszYasmRegGen32[pParam->Base.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ // VSIB
+ case DISUSE_REG_XMM | DISUSE_REG_GEN64:
+ case DISUSE_REG_YMM | DISUSE_REG_GEN64:
+ case DISUSE_REG_GEN64:
+ {
+ Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen64));
+ const char *psz = g_aszYasmRegGen64[pParam->Base.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ case DISUSE_REG_FP:
+ {
+ Assert(pParam->Base.idxFpuReg < RT_ELEMENTS(g_aszYasmRegFP));
+ const char *psz = g_aszYasmRegFP[pParam->Base.idxFpuReg];
+ *pcchReg = 3;
+ return psz;
+ }
+
+ case DISUSE_REG_MMX:
+ {
+ Assert(pParam->Base.idxMmxReg < RT_ELEMENTS(g_aszYasmRegMMX));
+ const char *psz = g_aszYasmRegMMX[pParam->Base.idxMmxReg];
+ *pcchReg = 3;
+ return psz;
+ }
+
+ case DISUSE_REG_XMM:
+ {
+ Assert(pParam->Base.idxXmmReg < RT_ELEMENTS(g_aszYasmRegXMM));
+ const char *psz = g_aszYasmRegXMM[pParam->Base.idxXmmReg];
+ *pcchReg = 4 + !!psz[4];
+ return psz;
+ }
+
+ case DISUSE_REG_YMM:
+ {
+ Assert(pParam->Base.idxYmmReg < RT_ELEMENTS(g_aszYasmRegYMM));
+ const char *psz = g_aszYasmRegYMM[pParam->Base.idxYmmReg];
+ *pcchReg = 4 + !!psz[4];
+ return psz;
+ }
+
+ case DISUSE_REG_CR:
+ {
+ Assert(pParam->Base.idxCtrlReg < RT_ELEMENTS(g_aszYasmRegCRx));
+ const char *psz = g_aszYasmRegCRx[pParam->Base.idxCtrlReg];
+ *pcchReg = 3;
+ return psz;
+ }
+
+ case DISUSE_REG_DBG:
+ {
+ Assert(pParam->Base.idxDbgReg < RT_ELEMENTS(g_aszYasmRegDRx));
+ const char *psz = g_aszYasmRegDRx[pParam->Base.idxDbgReg];
+ *pcchReg = 3;
+ return psz;
+ }
+
+ case DISUSE_REG_SEG:
+ {
+ Assert(pParam->Base.idxSegReg < RT_ELEMENTS(g_aszYasmRegCRx));
+ const char *psz = g_aszYasmRegSeg[pParam->Base.idxSegReg];
+ *pcchReg = 2;
+ return psz;
+ }
+
+ case DISUSE_REG_TEST:
+ {
+ Assert(pParam->Base.idxTestReg < RT_ELEMENTS(g_aszYasmRegTRx));
+ const char *psz = g_aszYasmRegTRx[pParam->Base.idxTestReg];
+ *pcchReg = 3;
+ return psz;
+ }
+
+ default:
+ AssertMsgFailed(("%#x\n", pParam->fUse));
+ *pcchReg = 3;
+ return "r??";
+ }
+}
+
+
+/**
+ * Gets the index register name for the given parameter.
+ *
+ * @returns The index register name.
+ * @param pDis The disassembler state.
+ * @param pParam The parameter.
+ * @param pcchReg Where to store the length of the name.
+ */
+static const char *disasmFormatYasmIndexReg(PCDISSTATE pDis, PCDISOPPARAM pParam, size_t *pcchReg)
+{
+ if (pParam->fUse & DISUSE_REG_XMM)
+ {
+ Assert(pParam->Index.idxXmmReg < RT_ELEMENTS(g_aszYasmRegXMM));
+ const char *psz = g_aszYasmRegXMM[pParam->Index.idxXmmReg];
+ *pcchReg = 4 + !!psz[4];
+ return psz;
+ }
+ else if (pParam->fUse & DISUSE_REG_YMM)
+ {
+ Assert(pParam->Index.idxYmmReg < RT_ELEMENTS(g_aszYasmRegYMM));
+ const char *psz = g_aszYasmRegYMM[pParam->Index.idxYmmReg];
+ *pcchReg = 4 + !!psz[4];
+ return psz;
+
+ }
+ else
+ switch (pDis->uAddrMode)
+ {
+ case DISCPUMODE_16BIT:
+ {
+ Assert(pParam->Index.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen16));
+ const char *psz = g_aszYasmRegGen16[pParam->Index.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ case DISCPUMODE_32BIT:
+ {
+ Assert(pParam->Index.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen32));
+ const char *psz = g_aszYasmRegGen32[pParam->Index.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ case DISCPUMODE_64BIT:
+ {
+ Assert(pParam->Index.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen64));
+ const char *psz = g_aszYasmRegGen64[pParam->Index.idxGenReg];
+ *pcchReg = 2 + !!psz[2] + !!psz[3];
+ return psz;
+ }
+
+ default:
+ AssertMsgFailed(("%#x %#x\n", pParam->fUse, pDis->uAddrMode));
+ *pcchReg = 3;
+ return "r??";
+ }
+}
+
+
+/**
+ * Formats the current instruction in Yasm (/ Nasm) style.
+ *
+ *
+ * @returns The number of output characters. If this is >= cchBuf, then the content
+ * of pszBuf will be truncated.
+ * @param pDis Pointer to the disassembler state.
+ * @param pszBuf The output buffer.
+ * @param cchBuf The size of the output buffer.
+ * @param fFlags Format flags, see DIS_FORMAT_FLAGS_*.
+ * @param pfnGetSymbol Get symbol name for a jmp or call target address. Optional.
+ * @param pvUser User argument for pfnGetSymbol.
+ */
+DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags,
+ PFNDISGETSYMBOL pfnGetSymbol, void *pvUser)
+{
+/** @todo monitor and mwait aren't formatted correctly in 64-bit mode. */
+ /*
+ * Input validation and massaging.
+ */
+ AssertPtr(pDis);
+ AssertPtrNull(pszBuf);
+ Assert(pszBuf || !cchBuf);
+ AssertPtrNull(pfnGetSymbol);
+ AssertMsg(DIS_FMT_FLAGS_IS_VALID(fFlags), ("%#x\n", fFlags));
+ if (fFlags & DIS_FMT_FLAGS_ADDR_COMMENT)
+ fFlags = (fFlags & ~DIS_FMT_FLAGS_ADDR_LEFT) | DIS_FMT_FLAGS_ADDR_RIGHT;
+ if (fFlags & DIS_FMT_FLAGS_BYTES_COMMENT)
+ fFlags = (fFlags & ~DIS_FMT_FLAGS_BYTES_LEFT) | DIS_FMT_FLAGS_BYTES_RIGHT;
+
+ PCDISOPCODE const pOp = pDis->pCurInstr;
+
+ /*
+ * Output macros
+ */
+ char *pszDst = pszBuf;
+ size_t cchDst = cchBuf;
+ size_t cchOutput = 0;
+#define PUT_C(ch) \
+ do { \
+ cchOutput++; \
+ if (cchDst > 1) \
+ { \
+ cchDst--; \
+ *pszDst++ = (ch); \
+ } \
+ } while (0)
+#define PUT_STR(pszSrc, cchSrc) \
+ do { \
+ cchOutput += (cchSrc); \
+ if (cchDst > (cchSrc)) \
+ { \
+ memcpy(pszDst, (pszSrc), (cchSrc)); \
+ pszDst += (cchSrc); \
+ cchDst -= (cchSrc); \
+ } \
+ else if (cchDst > 1) \
+ { \
+ memcpy(pszDst, (pszSrc), cchDst - 1); \
+ pszDst += cchDst - 1; \
+ cchDst = 1; \
+ } \
+ } while (0)
+#define PUT_SZ(sz) \
+ PUT_STR((sz), sizeof(sz) - 1)
+#define PUT_SZ_STRICT(szStrict, szRelaxed) \
+ do { if (fFlags & DIS_FMT_FLAGS_STRICT) PUT_SZ(szStrict); else PUT_SZ(szRelaxed); } while (0)
+#define PUT_PSZ(psz) \
+ do { const size_t cchTmp = strlen(psz); PUT_STR((psz), cchTmp); } while (0)
+#define PUT_NUM(cch, fmt, num) \
+ do { \
+ cchOutput += (cch); \
+ if (cchDst > 1) \
+ { \
+ const size_t cchTmp = RTStrPrintf(pszDst, cchDst, fmt, (num)); \
+ pszDst += cchTmp; \
+ cchDst -= cchTmp; \
+ Assert(cchTmp == (cch) || cchDst == 1); \
+ } \
+ } while (0)
+/** @todo add two flags for choosing between %X / %x and h / 0x. */
+#define PUT_NUM_8(num) PUT_NUM(4, "0%02xh", (uint8_t)(num))
+#define PUT_NUM_16(num) PUT_NUM(6, "0%04xh", (uint16_t)(num))
+#define PUT_NUM_32(num) PUT_NUM(10, "0%08xh", (uint32_t)(num))
+#define PUT_NUM_64(num) PUT_NUM(18, "0%016RX64h", (uint64_t)(num))
+
+#define PUT_NUM_SIGN(cch, fmt, num, stype, utype) \
+ do { \
+ if ((stype)(num) >= 0) \
+ { \
+ PUT_C('+'); \
+ PUT_NUM(cch, fmt, (utype)(num)); \
+ } \
+ else \
+ { \
+ PUT_C('-'); \
+ PUT_NUM(cch, fmt, (utype)-(stype)(num)); \
+ } \
+ } while (0)
+#define PUT_NUM_S8(num) PUT_NUM_SIGN(4, "0%02xh", num, int8_t, uint8_t)
+#define PUT_NUM_S16(num) PUT_NUM_SIGN(6, "0%04xh", num, int16_t, uint16_t)
+#define PUT_NUM_S32(num) PUT_NUM_SIGN(10, "0%08xh", num, int32_t, uint32_t)
+#define PUT_NUM_S64(num) PUT_NUM_SIGN(18, "0%016RX64h", num, int64_t, uint64_t)
+
+#define PUT_SYMBOL_TWO(a_rcSym, a_szStart, a_chEnd) \
+ do { \
+ if (RT_SUCCESS(a_rcSym)) \
+ { \
+ PUT_SZ(a_szStart); \
+ PUT_PSZ(szSymbol); \
+ if (off != 0) \
+ { \
+ if ((int8_t)off == off) \
+ PUT_NUM_S8(off); \
+ else if ((int16_t)off == off) \
+ PUT_NUM_S16(off); \
+ else if ((int32_t)off == off) \
+ PUT_NUM_S32(off); \
+ else \
+ PUT_NUM_S64(off); \
+ } \
+ PUT_C(a_chEnd); \
+ } \
+ } while (0)
+
+#define PUT_SYMBOL(a_uSeg, a_uAddr, a_szStart, a_chEnd) \
+ do { \
+ if (pfnGetSymbol) \
+ { \
+ int rcSym = pfnGetSymbol(pDis, a_uSeg, a_uAddr, szSymbol, sizeof(szSymbol), &off, pvUser); \
+ PUT_SYMBOL_TWO(rcSym, a_szStart, a_chEnd); \
+ } \
+ } while (0)
+
+
+ /*
+ * The address?
+ */
+ if (fFlags & DIS_FMT_FLAGS_ADDR_LEFT)
+ {
+#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
+ if (pDis->uInstrAddr >= _4G)
+ PUT_NUM(9, "%08x`", (uint32_t)(pDis->uInstrAddr >> 32));
+#endif
+ PUT_NUM(8, "%08x", (uint32_t)pDis->uInstrAddr);
+ PUT_C(' ');
+ }
+
+ /*
+ * The opcode bytes?
+ */
+ if (fFlags & DIS_FMT_FLAGS_BYTES_LEFT)
+ {
+ size_t cchTmp = disFormatBytes(pDis, pszDst, cchDst, fFlags);
+ cchOutput += cchTmp;
+ if (cchDst > 1)
+ {
+ if (cchTmp <= cchDst)
+ {
+ cchDst -= cchTmp;
+ pszDst += cchTmp;
+ }
+ else
+ {
+ pszDst += cchDst - 1;
+ cchDst = 1;
+ }
+ }
+
+ /* Some padding to align the instruction. */
+ size_t cchPadding = (7 * (2 + !!(fFlags & DIS_FMT_FLAGS_BYTES_SPACED)))
+ + !!(fFlags & DIS_FMT_FLAGS_BYTES_BRACKETS) * 2
+ + 2;
+ cchPadding = cchTmp + 1 >= cchPadding ? 1 : cchPadding - cchTmp;
+ PUT_STR(g_szSpaces, cchPadding);
+ }
+
+
+ /*
+ * Filter out invalid opcodes first as they need special
+ * treatment. UD2 is an exception and should be handled normally.
+ */
+ size_t const offInstruction = cchOutput;
+ if ( pOp->uOpcode == OP_INVALID
+ || ( pOp->uOpcode == OP_ILLUD2
+ && (pDis->fPrefix & DISPREFIX_LOCK)))
+ PUT_SZ("Illegal opcode");
+ else
+ {
+ /*
+ * Prefixes
+ */
+ if (pDis->fPrefix & DISPREFIX_LOCK)
+ PUT_SZ("lock ");
+ if (pDis->fPrefix & DISPREFIX_REP)
+ PUT_SZ("rep ");
+ else if(pDis->fPrefix & DISPREFIX_REPNE)
+ PUT_SZ("repne ");
+
+ /*
+ * Adjust the format string to the correct mnemonic
+ * or to avoid things the assembler cannot handle correctly.
+ */
+ char szTmpFmt[48];
+ const char *pszFmt = pOp->pszOpcode;
+ bool fIgnoresOpSize = false;
+ bool fMayNeedAddrSize = false;
+ switch (pOp->uOpcode)
+ {
+ case OP_JECXZ:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "jcxz %Jb" : pDis->uOpMode == DISCPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
+ break;
+ case OP_PUSHF:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "pushfw" : pDis->uOpMode == DISCPUMODE_32BIT ? "pushfd" : "pushfq";
+ break;
+ case OP_POPF:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "popfw" : pDis->uOpMode == DISCPUMODE_32BIT ? "popfd" : "popfq";
+ break;
+ case OP_PUSHA:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "pushaw" : "pushad";
+ break;
+ case OP_POPA:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "popaw" : "popad";
+ break;
+ case OP_INSB:
+ pszFmt = "insb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_INSWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "insw" : pDis->uOpMode == DISCPUMODE_32BIT ? "insd" : "insq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_OUTSB:
+ pszFmt = "outsb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_OUTSWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "outsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "outsd" : "outsq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_MOVSB:
+ pszFmt = "movsb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_MOVSWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "movsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "movsd" : "movsq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_CMPSB:
+ pszFmt = "cmpsb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_CMPWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "cmpsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "cmpsd" : "cmpsq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_SCASB:
+ pszFmt = "scasb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_SCASWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "scasw" : pDis->uOpMode == DISCPUMODE_32BIT ? "scasd" : "scasq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_LODSB:
+ pszFmt = "lodsb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_LODSWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "lodsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "lodsd" : "lodsq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_STOSB:
+ pszFmt = "stosb";
+ fIgnoresOpSize = fMayNeedAddrSize = true;
+ break;
+ case OP_STOSWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "stosw" : pDis->uOpMode == DISCPUMODE_32BIT ? "stosd" : "stosq";
+ fMayNeedAddrSize = true;
+ break;
+ case OP_CBW:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "cbw" : pDis->uOpMode == DISCPUMODE_32BIT ? "cwde" : "cdqe";
+ break;
+ case OP_CWD:
+ pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "cwd" : pDis->uOpMode == DISCPUMODE_32BIT ? "cdq" : "cqo";
+ break;
+ case OP_SHL:
+ Assert(pszFmt[3] == '/');
+ pszFmt += 4;
+ break;
+ case OP_XLAT:
+ pszFmt = "xlatb";
+ break;
+ case OP_INT3:
+ pszFmt = "int3";
+ break;
+
+ /*
+ * Don't know how to tell yasm to generate complicated nop stuff, so 'db' it.
+ */
+ case OP_NOP:
+ if (pDis->bOpCode == 0x90)
+ /* fine, fine */;
+ else if (pszFmt[sizeof("nop %Ev") - 1] == '/' && pszFmt[sizeof("nop %Ev")] == 'p')
+ pszFmt = "prefetch %Eb";
+ else if (pDis->bOpCode == 0x1f)
+ {
+ Assert(pDis->cbInstr >= 3);
+ PUT_SZ("db 00fh, 01fh,");
+ PUT_NUM_8(MAKE_MODRM(pDis->ModRM.Bits.Mod, pDis->ModRM.Bits.Reg, pDis->ModRM.Bits.Rm));
+ for (unsigned i = 3; i < pDis->cbInstr; i++)
+ {
+ PUT_C(',');
+ PUT_NUM_8(0x90); /// @todo fixme.
+ }
+ pszFmt = "";
+ }
+ break;
+
+ default:
+ /* ST(X) -> stX (floating point) */
+ if (*pszFmt == 'f' && strchr(pszFmt, '('))
+ {
+ char *pszFmtDst = szTmpFmt;
+ char ch;
+ do
+ {
+ ch = *pszFmt++;
+ if (ch == 'S' && pszFmt[0] == 'T' && pszFmt[1] == '(')
+ {
+ *pszFmtDst++ = 's';
+ *pszFmtDst++ = 't';
+ pszFmt += 2;
+ ch = *pszFmt;
+ Assert(pszFmt[1] == ')');
+ pszFmt += 2;
+ *pszFmtDst++ = ch;
+ }
+ else
+ *pszFmtDst++ = ch;
+ } while (ch != '\0');
+ pszFmt = szTmpFmt;
+ }
+ if (strchr("#@&", *pszFmt))
+ {
+ const char *pszDelim = strchr(pszFmt, '/');
+ const char *pszSpace = (pszDelim ? strchr(pszDelim, ' ') : NULL);
+ if (pszDelim != NULL)
+ {
+ char *pszFmtDst = szTmpFmt;
+ if (pszSpace == NULL) pszSpace = strchr(pszDelim, 0);
+ if ( (*pszFmt == '#' && !pDis->bVexWFlag) /** @todo check this*/
+ || (*pszFmt == '@' && !VEXREG_IS256B(pDis->bVexDestReg))
+ || (*pszFmt == '&' && ( DISUSE_IS_EFFECTIVE_ADDR(pDis->Param1.fUse)
+ || DISUSE_IS_EFFECTIVE_ADDR(pDis->Param2.fUse)
+ || DISUSE_IS_EFFECTIVE_ADDR(pDis->Param3.fUse)
+ || DISUSE_IS_EFFECTIVE_ADDR(pDis->Param4.fUse))))
+ {
+ strncpy(pszFmtDst, pszFmt + 1, pszDelim - pszFmt - 1);
+ pszFmtDst += pszDelim - pszFmt - 1;
+ }
+ else
+ {
+ strncpy(pszFmtDst, pszDelim + 1, pszSpace - pszDelim - 1);
+ pszFmtDst += pszSpace - pszDelim - 1;
+ }
+ strcpy (pszFmtDst, pszSpace);
+ pszFmt = szTmpFmt;
+ }
+ }
+ break;
+
+ /*
+ * Horrible hacks.
+ */
+ case OP_FLD:
+ if (pDis->bOpCode == 0xdb) /* m80fp workaround. */
+ *(int *)&pDis->Param1.fParam &= ~0x1f; /* make it pure OP_PARM_M */
+ break;
+ case OP_LAR: /* hack w -> v, probably not correct. */
+ *(int *)&pDis->Param2.fParam &= ~0x1f;
+ *(int *)&pDis->Param2.fParam |= OP_PARM_v;
+ break;
+ }
+
+ /*
+ * Add operand size and address prefixes for outsb, movsb, etc.
+ */
+ if (pDis->fPrefix & (DISPREFIX_OPSIZE | DISPREFIX_ADDRSIZE))
+ {
+ if (fIgnoresOpSize && (pDis->fPrefix & DISPREFIX_OPSIZE) )
+ {
+ if (pDis->uCpuMode == DISCPUMODE_16BIT)
+ PUT_SZ("o32 ");
+ else
+ PUT_SZ("o16 ");
+ }
+ if (fMayNeedAddrSize && (pDis->fPrefix & DISPREFIX_ADDRSIZE) )
+ {
+ if (pDis->uCpuMode == DISCPUMODE_16BIT)
+ PUT_SZ("a32 ");
+ else
+ PUT_SZ("a16 ");
+ }
+ }
+
+ /*
+ * Formatting context and associated macros.
+ */
+ PCDISOPPARAM pParam = &pDis->Param1;
+ int iParam = 1;
+
+#define PUT_FAR() \
+ do { \
+ if ( OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p \
+ && pOp->uOpcode != OP_LDS /* table bugs? */ \
+ && pOp->uOpcode != OP_LES \
+ && pOp->uOpcode != OP_LFS \
+ && pOp->uOpcode != OP_LGS \
+ && pOp->uOpcode != OP_LSS ) \
+ PUT_SZ("far "); \
+ } while (0)
+ /** @todo mov ah,ch ends up with a byte 'override'... - check if this wasn't fixed. */
+ /** @todo drop the work/dword/qword override when the src/dst is a register (except for movsx/movzx). */
+#define PUT_SIZE_OVERRIDE() \
+ do { \
+ switch (OP_PARM_VSUBTYPE(pParam->fParam)) \
+ { \
+ case OP_PARM_v: \
+ case OP_PARM_y: \
+ switch (pDis->uOpMode) \
+ { \
+ case DISCPUMODE_16BIT: if (OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_y) PUT_SZ("word "); break; \
+ case DISCPUMODE_32BIT: \
+ if (pDis->pCurInstr->uOpcode != OP_GATHER || pDis->bVexWFlag) { PUT_SZ("dword "); break; } \
+ RT_FALL_THRU(); \
+ case DISCPUMODE_64BIT: PUT_SZ("qword "); break; \
+ default: break; \
+ } \
+ break; \
+ case OP_PARM_b: PUT_SZ("byte "); break; \
+ case OP_PARM_w: \
+ if ( OP_PARM_VTYPE(pParam->fParam) == OP_PARM_W \
+ || OP_PARM_VTYPE(pParam->fParam) == OP_PARM_M) \
+ { \
+ if (VEXREG_IS256B(pDis->bVexDestReg)) PUT_SZ("dword "); \
+ else PUT_SZ("word "); \
+ } \
+ break; \
+ case OP_PARM_d: \
+ if ( OP_PARM_VTYPE(pParam->fParam) == OP_PARM_W \
+ || OP_PARM_VTYPE(pParam->fParam) == OP_PARM_M) \
+ { \
+ if (VEXREG_IS256B(pDis->bVexDestReg)) PUT_SZ("qword "); \
+ else PUT_SZ("dword "); \
+ } \
+ break; \
+ case OP_PARM_q: \
+ if ( OP_PARM_VTYPE(pParam->fParam) == OP_PARM_W \
+ || OP_PARM_VTYPE(pParam->fParam) == OP_PARM_M) \
+ { \
+ if (VEXREG_IS256B(pDis->bVexDestReg)) PUT_SZ("oword "); \
+ else PUT_SZ("qword "); \
+ } \
+ break; \
+ case OP_PARM_ps: \
+ case OP_PARM_pd: \
+ case OP_PARM_x: if (VEXREG_IS256B(pDis->bVexDestReg)) { PUT_SZ("yword "); break; } RT_FALL_THRU(); \
+ case OP_PARM_ss: \
+ case OP_PARM_sd: \
+ case OP_PARM_dq: PUT_SZ("oword "); break; \
+ case OP_PARM_qq: PUT_SZ("yword "); break; \
+ case OP_PARM_p: break; /* see PUT_FAR */ \
+ case OP_PARM_s: if (pParam->fUse & DISUSE_REG_FP) PUT_SZ("tword "); break; /* ?? */ \
+ case OP_PARM_z: break; \
+ case OP_PARM_NONE: \
+ if ( OP_PARM_VTYPE(pParam->fParam) == OP_PARM_M \
+ && ((pParam->fUse & DISUSE_REG_FP) || pOp->uOpcode == OP_FLD)) \
+ PUT_SZ("tword "); \
+ break; \
+ default: break; /*no pointer type specified/necessary*/ \
+ } \
+ } while (0)
+ static const char s_szSegPrefix[6][4] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
+#define PUT_SEGMENT_OVERRIDE() \
+ do { \
+ if (pDis->fPrefix & DISPREFIX_SEG) \
+ PUT_STR(s_szSegPrefix[pDis->idxSegPrefix], 3); \
+ } while (0)
+
+
+ /*
+ * Segment prefixing for instructions that doesn't do memory access.
+ */
+ if ( (pDis->fPrefix & DISPREFIX_SEG)
+ && !DISUSE_IS_EFFECTIVE_ADDR(pDis->Param1.fUse)
+ && !DISUSE_IS_EFFECTIVE_ADDR(pDis->Param2.fUse)
+ && !DISUSE_IS_EFFECTIVE_ADDR(pDis->Param3.fUse))
+ {
+ PUT_STR(s_szSegPrefix[pDis->idxSegPrefix], 2);
+ PUT_C(' ');
+ }
+
+
+ /*
+ * The formatting loop.
+ */
+ RTINTPTR off;
+ char szSymbol[128];
+ char ch;
+ while ((ch = *pszFmt++) != '\0')
+ {
+ if (ch == '%')
+ {
+ ch = *pszFmt++;
+ switch (ch)
+ {
+ /*
+ * ModRM - Register only / VEX.vvvv.
+ */
+ case 'C': /* Control register (ParseModRM / UseModRM). */
+ case 'D': /* Debug register (ParseModRM / UseModRM). */
+ case 'G': /* ModRM selects general register (ParseModRM / UseModRM). */
+ case 'S': /* ModRM byte selects a segment register (ParseModRM / UseModRM). */
+ case 'T': /* ModRM byte selects a test register (ParseModRM / UseModRM). */
+ case 'V': /* ModRM byte selects an XMM/SSE register (ParseModRM / UseModRM). */
+ case 'P': /* ModRM byte selects MMX register (ParseModRM / UseModRM). */
+ case 'H': /* The VEX.vvvv field of the VEX prefix selects a XMM/YMM register. */
+ case 'B': /* The VEX.vvvv field of the VEX prefix selects a general register (ParseVexDest). */
+ case 'L': /* The upper 4 bits of the 8-bit immediate selects a XMM/YMM register. */
+ {
+ pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
+ Assert(!(pParam->fUse & (DISUSE_INDEX | DISUSE_SCALE) /* No SIB here... */));
+ Assert(!(pParam->fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32)));
+
+ size_t cchReg;
+ const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
+ PUT_STR(pszReg, cchReg);
+ break;
+ }
+
+ /*
+ * ModRM - Register or memory.
+ */
+ case 'E': /* ModRM specifies parameter (ParseModRM / UseModRM / UseSIB). */
+ case 'Q': /* ModRM byte selects MMX register or memory address (ParseModRM / UseModRM). */
+ case 'R': /* ModRM byte may only refer to a general register (ParseModRM / UseModRM). */
+ case 'W': /* ModRM byte selects an XMM/SSE register or a memory address (ParseModRM / UseModRM). */
+ case 'U': /* ModRM byte may only refer to a XMM/SSE register (ParseModRM / UseModRM). */
+ case 'M': /* ModRM byte may only refer to memory (ParseModRM / UseModRM). */
+ {
+ pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
+
+ PUT_FAR();
+ uint32_t const fUse = pParam->fUse;
+ if (DISUSE_IS_EFFECTIVE_ADDR(fUse))
+ {
+ /* Work around mov seg,[mem16] and mov [mem16],seg as these always make a 16-bit mem
+ while the register variants deals with 16, 32 & 64 in the normal fashion. */
+ if ( pParam->fParam != OP_PARM_Ev
+ || pOp->uOpcode != OP_MOV
+ || ( pOp->fParam1 != OP_PARM_Sw
+ && pOp->fParam2 != OP_PARM_Sw))
+ PUT_SIZE_OVERRIDE();
+ PUT_C('[');
+ }
+ if ( (fFlags & DIS_FMT_FLAGS_STRICT)
+ && (fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32)))
+ {
+ if ( (fUse & DISUSE_DISPLACEMENT8)
+ && !pParam->uDisp.i8)
+ PUT_SZ("byte ");
+ else if ( (fUse & DISUSE_DISPLACEMENT16)
+ && (int8_t)pParam->uDisp.i16 == (int16_t)pParam->uDisp.i16)
+ PUT_SZ("word ");
+ else if ( (fUse & DISUSE_DISPLACEMENT32)
+ && (int16_t)pParam->uDisp.i32 == (int32_t)pParam->uDisp.i32) //??
+ PUT_SZ("dword ");
+ else if ( (fUse & DISUSE_DISPLACEMENT64)
+ && (pDis->SIB.Bits.Base != 5 || pDis->ModRM.Bits.Mod != 0)
+ && (int32_t)pParam->uDisp.i64 == (int64_t)pParam->uDisp.i64) //??
+ PUT_SZ("qword ");
+ }
+ if (DISUSE_IS_EFFECTIVE_ADDR(fUse))
+ PUT_SEGMENT_OVERRIDE();
+
+ bool fBase = (fUse & DISUSE_BASE) /* When exactly is DISUSE_BASE supposed to be set? disasmModRMReg doesn't set it. */
+ || ( (fUse & ( DISUSE_REG_GEN8
+ | DISUSE_REG_GEN16
+ | DISUSE_REG_GEN32
+ | DISUSE_REG_GEN64
+ | DISUSE_REG_FP
+ | DISUSE_REG_MMX
+ | DISUSE_REG_XMM
+ | DISUSE_REG_YMM
+ | DISUSE_REG_CR
+ | DISUSE_REG_DBG
+ | DISUSE_REG_SEG
+ | DISUSE_REG_TEST ))
+ && !DISUSE_IS_EFFECTIVE_ADDR(fUse));
+ if (fBase)
+ {
+ size_t cchReg;
+ const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
+ PUT_STR(pszReg, cchReg);
+ }
+
+ if (fUse & DISUSE_INDEX)
+ {
+ if (fBase)
+ PUT_C('+');
+
+ size_t cchReg;
+ const char *pszReg = disasmFormatYasmIndexReg(pDis, pParam, &cchReg);
+ PUT_STR(pszReg, cchReg);
+
+ if (fUse & DISUSE_SCALE)
+ {
+ PUT_C('*');
+ PUT_C('0' + pParam->uScale);
+ }
+ }
+ else
+ Assert(!(fUse & DISUSE_SCALE));
+
+ int64_t off2 = 0;
+ if (fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32))
+ {
+ if (fUse & DISUSE_DISPLACEMENT8)
+ off2 = pParam->uDisp.i8;
+ else if (fUse & DISUSE_DISPLACEMENT16)
+ off2 = pParam->uDisp.i16;
+ else if (fUse & (DISUSE_DISPLACEMENT32 | DISUSE_RIPDISPLACEMENT32))
+ off2 = pParam->uDisp.i32;
+ else if (fUse & DISUSE_DISPLACEMENT64)
+ off2 = pParam->uDisp.i64;
+ else
+ {
+ AssertFailed();
+ off2 = 0;
+ }
+
+ int64_t off3 = off2;
+ if (fBase || (fUse & (DISUSE_INDEX | DISUSE_RIPDISPLACEMENT32)))
+ {
+ PUT_C(off3 >= 0 ? '+' : '-');
+ if (off3 < 0)
+ off3 = -off3;
+ }
+ if (fUse & DISUSE_DISPLACEMENT8)
+ PUT_NUM_8( off3);
+ else if (fUse & DISUSE_DISPLACEMENT16)
+ PUT_NUM_16(off3);
+ else if (fUse & DISUSE_DISPLACEMENT32)
+ PUT_NUM_32(off3);
+ else if (fUse & DISUSE_DISPLACEMENT64)
+ PUT_NUM_64(off3);
+ else
+ {
+ PUT_NUM_32(off3);
+ PUT_SZ(" wrt rip (");
+ off2 += pDis->uInstrAddr + pDis->cbInstr;
+ PUT_NUM_64(off2);
+ if (pfnGetSymbol)
+ PUT_SYMBOL((pDis->fPrefix & DISPREFIX_SEG)
+ ? DIS_FMT_SEL_FROM_REG(pDis->idxSegPrefix)
+ : DIS_FMT_SEL_FROM_REG(DISSELREG_DS),
+ pDis->uAddrMode == DISCPUMODE_64BIT
+ ? (uint64_t)off2
+ : pDis->uAddrMode == DISCPUMODE_32BIT
+ ? (uint32_t)off2
+ : (uint16_t)off2,
+ " = ",
+ ')');
+ else
+ PUT_C(')');
+ }
+ }
+
+ if (DISUSE_IS_EFFECTIVE_ADDR(fUse))
+ {
+ if (pfnGetSymbol && !fBase && !(fUse & (DISUSE_INDEX | DISUSE_RIPDISPLACEMENT32)) && off2 != 0)
+ PUT_SYMBOL((pDis->fPrefix & DISPREFIX_SEG)
+ ? DIS_FMT_SEL_FROM_REG(pDis->idxSegPrefix)
+ : DIS_FMT_SEL_FROM_REG(DISSELREG_DS),
+ pDis->uAddrMode == DISCPUMODE_64BIT
+ ? (uint64_t)off2
+ : pDis->uAddrMode == DISCPUMODE_32BIT
+ ? (uint32_t)off2
+ : (uint16_t)off2,
+ " (=",
+ ')');
+ PUT_C(']');
+ }
+ break;
+ }
+
+ case 'F': /* Eflags register (0 - popf/pushf only, avoided in adjustments above). */
+ AssertFailed();
+ break;
+
+ case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
+ Assert(*pszFmt == 'b' || *pszFmt == 'v' || *pszFmt == 'w' || *pszFmt == 'z'); pszFmt++;
+ switch (pParam->fUse & ( DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE64
+ | DISUSE_IMMEDIATE16_SX8 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE64_SX8))
+ {
+ case DISUSE_IMMEDIATE8:
+ if ( (fFlags & DIS_FMT_FLAGS_STRICT)
+ && ( (pOp->fParam1 >= OP_PARM_REG_GEN8_START && pOp->fParam1 <= OP_PARM_REG_GEN8_END)
+ || (pOp->fParam2 >= OP_PARM_REG_GEN8_START && pOp->fParam2 <= OP_PARM_REG_GEN8_END))
+ )
+ PUT_SZ("strict byte ");
+ PUT_NUM_8(pParam->uValue);
+ break;
+
+ case DISUSE_IMMEDIATE16:
+ if ( pDis->uCpuMode != pDis->uOpMode
+ || ( (fFlags & DIS_FMT_FLAGS_STRICT)
+ && ( (int8_t)pParam->uValue == (int16_t)pParam->uValue
+ || (pOp->fParam1 >= OP_PARM_REG_GEN16_START && pOp->fParam1 <= OP_PARM_REG_GEN16_END)
+ || (pOp->fParam2 >= OP_PARM_REG_GEN16_START && pOp->fParam2 <= OP_PARM_REG_GEN16_END))
+ )
+ )
+ {
+ if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_b)
+ PUT_SZ_STRICT("strict byte ", "byte ");
+ else if ( OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_v
+ || OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_z)
+ PUT_SZ_STRICT("strict word ", "word ");
+ }
+ PUT_NUM_16(pParam->uValue);
+ break;
+
+ case DISUSE_IMMEDIATE16_SX8:
+ if ( !(pDis->fPrefix & DISPREFIX_OPSIZE)
+ || pDis->pCurInstr->uOpcode != OP_PUSH)
+ PUT_SZ_STRICT("strict byte ", "byte ");
+ else
+ PUT_SZ("word ");
+ PUT_NUM_16(pParam->uValue);
+ break;
+
+ case DISUSE_IMMEDIATE32:
+ if ( pDis->uOpMode != (pDis->uCpuMode == DISCPUMODE_16BIT ? DISCPUMODE_16BIT : DISCPUMODE_32BIT) /* not perfect */
+ || ( (fFlags & DIS_FMT_FLAGS_STRICT)
+ && ( (int8_t)pParam->uValue == (int32_t)pParam->uValue
+ || (pOp->fParam1 >= OP_PARM_REG_GEN32_START && pOp->fParam1 <= OP_PARM_REG_GEN32_END)
+ || (pOp->fParam2 >= OP_PARM_REG_GEN32_START && pOp->fParam2 <= OP_PARM_REG_GEN32_END))
+ )
+ )
+ {
+ if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_b)
+ PUT_SZ_STRICT("strict byte ", "byte ");
+ else if ( OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_v
+ || OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_z)
+ PUT_SZ_STRICT("strict dword ", "dword ");
+ }
+ PUT_NUM_32(pParam->uValue);
+ if (pDis->uCpuMode == DISCPUMODE_32BIT)
+ PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uValue, " (=", ')');
+ break;
+
+ case DISUSE_IMMEDIATE32_SX8:
+ if ( !(pDis->fPrefix & DISPREFIX_OPSIZE)
+ || pDis->pCurInstr->uOpcode != OP_PUSH)
+ PUT_SZ_STRICT("strict byte ", "byte ");
+ else
+ PUT_SZ("dword ");
+ PUT_NUM_32(pParam->uValue);
+ break;
+
+ case DISUSE_IMMEDIATE64_SX8:
+ if ( !(pDis->fPrefix & DISPREFIX_OPSIZE)
+ || pDis->pCurInstr->uOpcode != OP_PUSH)
+ PUT_SZ_STRICT("strict byte ", "byte ");
+ else
+ PUT_SZ("qword ");
+ PUT_NUM_64(pParam->uValue);
+ break;
+
+ case DISUSE_IMMEDIATE64:
+ PUT_NUM_64(pParam->uValue);
+ break;
+
+ default:
+ AssertFailed();
+ break;
+ }
+ break;
+
+ case 'J': /* Relative jump offset (ParseImmBRel + ParseImmVRel). */
+ {
+ int32_t offDisplacement;
+ Assert(iParam == 1);
+ bool fPrefix = (fFlags & DIS_FMT_FLAGS_STRICT)
+ && pOp->uOpcode != OP_CALL
+ && pOp->uOpcode != OP_LOOP
+ && pOp->uOpcode != OP_LOOPE
+ && pOp->uOpcode != OP_LOOPNE
+ && pOp->uOpcode != OP_JECXZ;
+ if (pOp->uOpcode == OP_CALL)
+ fFlags &= ~DIS_FMT_FLAGS_RELATIVE_BRANCH;
+
+ if (pParam->fUse & DISUSE_IMMEDIATE8_REL)
+ {
+ if (fPrefix)
+ PUT_SZ("short ");
+ offDisplacement = (int8_t)pParam->uValue;
+ Assert(*pszFmt == 'b'); pszFmt++;
+
+ if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
+ PUT_NUM_S8(offDisplacement);
+ }
+ else if (pParam->fUse & DISUSE_IMMEDIATE16_REL)
+ {
+ if (fPrefix)
+ PUT_SZ("near ");
+ offDisplacement = (int16_t)pParam->uValue;
+ Assert(*pszFmt == 'v'); pszFmt++;
+
+ if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
+ PUT_NUM_S16(offDisplacement);
+ }
+ else
+ {
+ if (fPrefix)
+ PUT_SZ("near ");
+ offDisplacement = (int32_t)pParam->uValue;
+ Assert(pParam->fUse & (DISUSE_IMMEDIATE32_REL | DISUSE_IMMEDIATE64_REL));
+ Assert(*pszFmt == 'v'); pszFmt++;
+
+ if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
+ PUT_NUM_S32(offDisplacement);
+ }
+ if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
+ PUT_SZ(" (");
+
+ RTUINTPTR uTrgAddr = pDis->uInstrAddr + pDis->cbInstr + offDisplacement;
+ if (pDis->uCpuMode == DISCPUMODE_16BIT)
+ PUT_NUM_16(uTrgAddr);
+ else if (pDis->uCpuMode == DISCPUMODE_32BIT)
+ PUT_NUM_32(uTrgAddr);
+ else
+ PUT_NUM_64(uTrgAddr);
+
+ if (fFlags & DIS_FMT_FLAGS_RELATIVE_BRANCH)
+ {
+ PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, " = ", ' ');
+ PUT_C(')');
+ }
+ else
+ PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, " (", ')');
+ break;
+ }
+
+ case 'A': /* Direct (jump/call) address (ParseImmAddr). */
+ {
+ Assert(*pszFmt == 'p'); pszFmt++;
+ PUT_FAR();
+ PUT_SIZE_OVERRIDE();
+ PUT_SEGMENT_OVERRIDE();
+ off = 0;
+ int rc = VERR_SYMBOL_NOT_FOUND;
+ switch (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16 | DISUSE_IMMEDIATE_ADDR_16_32 | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT16))
+ {
+ case DISUSE_IMMEDIATE_ADDR_16_16:
+ PUT_NUM_16(pParam->uValue >> 16);
+ PUT_C(':');
+ PUT_NUM_16(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint16_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_IMMEDIATE_ADDR_16_32:
+ PUT_NUM_16(pParam->uValue >> 32);
+ PUT_C(':');
+ PUT_NUM_32(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint32_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_DISPLACEMENT16:
+ PUT_NUM_16(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint16_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_DISPLACEMENT32:
+ PUT_NUM_32(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint32_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_DISPLACEMENT64:
+ PUT_NUM_64(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint64_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ default:
+ AssertFailed();
+ break;
+ }
+
+ PUT_SYMBOL_TWO(rc, " [", ']');
+ break;
+ }
+
+ case 'O': /* No ModRM byte (ParseImmAddr). */
+ {
+ Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
+ PUT_FAR();
+ PUT_SIZE_OVERRIDE();
+ PUT_C('[');
+ PUT_SEGMENT_OVERRIDE();
+ off = 0;
+ int rc = VERR_SYMBOL_NOT_FOUND;
+ switch (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16 | DISUSE_IMMEDIATE_ADDR_16_32 | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT16))
+ {
+ case DISUSE_IMMEDIATE_ADDR_16_16:
+ PUT_NUM_16(pParam->uValue >> 16);
+ PUT_C(':');
+ PUT_NUM_16(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint16_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_IMMEDIATE_ADDR_16_32:
+ PUT_NUM_16(pParam->uValue >> 32);
+ PUT_C(':');
+ PUT_NUM_32(pParam->uValue);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint32_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_DISPLACEMENT16:
+ PUT_NUM_16(pParam->uDisp.i16);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u16, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_DISPLACEMENT32:
+ PUT_NUM_32(pParam->uDisp.i32);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u32, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ case DISUSE_DISPLACEMENT64:
+ PUT_NUM_64(pParam->uDisp.i64);
+ if (pfnGetSymbol)
+ rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u64, szSymbol, sizeof(szSymbol), &off, pvUser);
+ break;
+ default:
+ AssertFailed();
+ break;
+ }
+ PUT_C(']');
+
+ PUT_SYMBOL_TWO(rc, " (", ')');
+ break;
+ }
+
+ case 'X': /* DS:SI (ParseXb, ParseXv). */
+ case 'Y': /* ES:DI (ParseYb, ParseYv). */
+ {
+ Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
+ PUT_FAR();
+ PUT_SIZE_OVERRIDE();
+ PUT_C('[');
+ if (pParam->fUse & DISUSE_POINTER_DS_BASED)
+ PUT_SZ("ds:");
+ else
+ PUT_SZ("es:");
+
+ size_t cchReg;
+ const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
+ PUT_STR(pszReg, cchReg);
+ PUT_C(']');
+ break;
+ }
+
+ case 'e': /* Register based on operand size (e.g. %eAX, %eAH) (ParseFixedReg). */
+ {
+ Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2]));
+ pszFmt += 2;
+ size_t cchReg;
+ const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
+ PUT_STR(pszReg, cchReg);
+ break;
+ }
+
+ default:
+ AssertMsgFailed(("%c%s!\n", ch, pszFmt));
+ break;
+ }
+ AssertMsg(*pszFmt == ',' || *pszFmt == '\0', ("%c%s\n", ch, pszFmt));
+ }
+ else
+ {
+ PUT_C(ch);
+ if (ch == ',')
+ {
+ Assert(*pszFmt != ' ');
+ PUT_C(' ');
+ switch (++iParam)
+ {
+ case 2: pParam = &pDis->Param2; break;
+ case 3: pParam = &pDis->Param3; break;
+ case 4: pParam = &pDis->Param4; break;
+ default: pParam = NULL; break;
+ }
+ }
+ }
+ } /* while more to format */
+ }
+
+ /*
+ * Any additional output to the right of the instruction?
+ */
+ if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
+ {
+ /* some up front padding. */
+ size_t cchPadding = cchOutput - offInstruction;
+ cchPadding = cchPadding + 1 >= 42 ? 1 : 42 - cchPadding;
+ PUT_STR(g_szSpaces, cchPadding);
+
+ /* comment? */
+ if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
+ PUT_SZ(";");
+
+ /*
+ * The address?
+ */
+ if (fFlags & DIS_FMT_FLAGS_ADDR_RIGHT)
+ {
+ PUT_C(' ');
+#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
+ if (pDis->uInstrAddr >= _4G)
+ PUT_NUM(9, "%08x`", (uint32_t)(pDis->uInstrAddr >> 32));
+#endif
+ PUT_NUM(8, "%08x", (uint32_t)pDis->uInstrAddr);
+ }
+
+ /*
+ * Opcode bytes?
+ */
+ if (fFlags & DIS_FMT_FLAGS_BYTES_RIGHT)
+ {
+ PUT_C(' ');
+ size_t cchTmp = disFormatBytes(pDis, pszDst, cchDst, fFlags);
+ cchOutput += cchTmp;
+ if (cchTmp >= cchDst)
+ cchTmp = cchDst - (cchDst != 0);
+ cchDst -= cchTmp;
+ pszDst += cchTmp;
+ }
+ }
+
+ /*
+ * Terminate it - on overflow we'll have reserved one byte for this.
+ */
+ if (cchDst > 0)
+ *pszDst = '\0';
+ else
+ Assert(!cchBuf);
+
+ /* clean up macros */
+#undef PUT_PSZ
+#undef PUT_SZ
+#undef PUT_STR
+#undef PUT_C
+ return cchOutput;
+}
+
+
+/**
+ * Formats the current instruction in Yasm (/ Nasm) style.
+ *
+ * This is a simplified version of DISFormatYasmEx() provided for your convenience.
+ *
+ *
+ * @returns The number of output characters. If this is >= cchBuf, then the content
+ * of pszBuf will be truncated.
+ * @param pDis Pointer to the disassembler state.
+ * @param pszBuf The output buffer.
+ * @param cchBuf The size of the output buffer.
+ */
+DISDECL(size_t) DISFormatYasm(PCDISSTATE pDis, char *pszBuf, size_t cchBuf)
+{
+ return DISFormatYasmEx(pDis, pszBuf, cchBuf, 0 /* fFlags */, NULL /* pfnGetSymbol */, NULL /* pvUser */);
+}
+
+
+/**
+ * Checks if the encoding of the given disassembled instruction is something we
+ * can never get YASM to produce.
+ *
+ * @returns true if it's odd, false if it isn't.
+ * @param pDis The disassembler output. The byte fetcher callback will
+ * be used if present as we might need to fetch opcode
+ * bytes.
+ */
+DISDECL(bool) DISFormatYasmIsOddEncoding(PDISSTATE pDis)
+{
+ /*
+ * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.
+ */
+ if ( pDis->uAddrMode != DISCPUMODE_16BIT /// @todo correct?
+ && pDis->ModRM.Bits.Rm == 4
+ && pDis->ModRM.Bits.Mod != 3)
+ {
+ /* No scaled index SIB (index=4), except for ESP. */
+ if ( pDis->SIB.Bits.Index == 4
+ && pDis->SIB.Bits.Base != 4)
+ return true;
+
+ /* EBP + displacement */
+ if ( pDis->ModRM.Bits.Mod != 0
+ && pDis->SIB.Bits.Base == 5
+ && pDis->SIB.Bits.Scale == 0)
+ return true;
+ }
+
+ /*
+ * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!
+ */
+ if ( pDis->pCurInstr->uOpcode == OP_SHL
+ && pDis->ModRM.Bits.Reg == 6)
+ return true;
+
+ /*
+ * Check for multiple prefixes of the same kind.
+ */
+ uint8_t off1stSeg = UINT8_MAX;
+ uint8_t offOpSize = UINT8_MAX;
+ uint8_t offAddrSize = UINT8_MAX;
+ uint32_t fPrefixes = 0;
+ for (uint32_t offOpcode = 0; offOpcode < RT_ELEMENTS(pDis->abInstr); offOpcode++)
+ {
+ uint32_t f;
+ switch (pDis->abInstr[offOpcode])
+ {
+ case 0xf0:
+ f = DISPREFIX_LOCK;
+ break;
+
+ case 0xf2:
+ case 0xf3:
+ f = DISPREFIX_REP; /* yes, both */
+ break;
+
+ case 0x2e:
+ case 0x3e:
+ case 0x26:
+ case 0x36:
+ case 0x64:
+ case 0x65:
+ if (off1stSeg == UINT8_MAX)
+ off1stSeg = offOpcode;
+ f = DISPREFIX_SEG;
+ break;
+
+ case 0x66:
+ if (offOpSize == UINT8_MAX)
+ offOpSize = offOpcode;
+ f = DISPREFIX_OPSIZE;
+ break;
+
+ case 0x67:
+ if (offAddrSize == UINT8_MAX)
+ offAddrSize = offOpcode;
+ f = DISPREFIX_ADDRSIZE;
+ break;
+
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ f = pDis->uCpuMode == DISCPUMODE_64BIT ? DISPREFIX_REX : 0;
+ break;
+
+ default:
+ f = 0;
+ break;
+ }
+ if (!f)
+ break; /* done */
+ if (fPrefixes & f)
+ return true;
+ fPrefixes |= f;
+ }
+
+ /* segment overrides are fun */
+ if (fPrefixes & DISPREFIX_SEG)
+ {
+ /* no effective address which it may apply to. */
+ Assert((pDis->fPrefix & DISPREFIX_SEG) || pDis->uCpuMode == DISCPUMODE_64BIT);
+ if ( !DISUSE_IS_EFFECTIVE_ADDR(pDis->Param1.fUse)
+ && !DISUSE_IS_EFFECTIVE_ADDR(pDis->Param2.fUse)
+ && !DISUSE_IS_EFFECTIVE_ADDR(pDis->Param3.fUse))
+ return true;
+
+ /* Yasm puts the segment prefixes before the operand prefix with no
+ way of overriding it. */
+ if (offOpSize < off1stSeg)
+ return true;
+ }
+
+ /* fixed register + addr override doesn't go down all that well. */
+ if (fPrefixes & DISPREFIX_ADDRSIZE)
+ {
+ Assert(pDis->fPrefix & DISPREFIX_ADDRSIZE);
+ if ( pDis->pCurInstr->fParam3 == OP_PARM_NONE
+ && pDis->pCurInstr->fParam2 == OP_PARM_NONE
+ && ( pDis->pCurInstr->fParam1 >= OP_PARM_REG_GEN32_START
+ && pDis->pCurInstr->fParam1 <= OP_PARM_REG_GEN32_END))
+ return true;
+ }
+
+ /* Almost all prefixes are bad for jumps. */
+ if (fPrefixes)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ /* nop w/ prefix(es). */
+ case OP_NOP:
+ return true;
+
+ case OP_JMP:
+ if ( pDis->pCurInstr->fParam1 != OP_PARM_Jb
+ && pDis->pCurInstr->fParam1 != OP_PARM_Jv)
+ break;
+ RT_FALL_THRU();
+ case OP_JO:
+ case OP_JNO:
+ case OP_JC:
+ case OP_JNC:
+ case OP_JE:
+ case OP_JNE:
+ case OP_JBE:
+ case OP_JNBE:
+ case OP_JS:
+ case OP_JNS:
+ case OP_JP:
+ case OP_JNP:
+ case OP_JL:
+ case OP_JNL:
+ case OP_JLE:
+ case OP_JNLE:
+ /** @todo branch hinting 0x2e/0x3e... */
+ return true;
+ }
+
+ }
+
+ /* All but the segment prefix is bad news for push/pop. */
+ if (fPrefixes & ~DISPREFIX_SEG)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_POP:
+ case OP_PUSH:
+ if ( pDis->pCurInstr->fParam1 >= OP_PARM_REG_SEG_START
+ && pDis->pCurInstr->fParam1 <= OP_PARM_REG_SEG_END)
+ return true;
+ if ( (fPrefixes & ~DISPREFIX_OPSIZE)
+ && pDis->pCurInstr->fParam1 >= OP_PARM_REG_GEN32_START
+ && pDis->pCurInstr->fParam1 <= OP_PARM_REG_GEN32_END)
+ return true;
+ break;
+
+ case OP_POPA:
+ case OP_POPF:
+ case OP_PUSHA:
+ case OP_PUSHF:
+ if (fPrefixes & ~DISPREFIX_OPSIZE)
+ return true;
+ break;
+ }
+ }
+
+ /* Implicit 8-bit register instructions doesn't mix with operand size. */
+ if ( (fPrefixes & DISPREFIX_OPSIZE)
+ && ( ( pDis->pCurInstr->fParam1 == OP_PARM_Gb /* r8 */
+ && pDis->pCurInstr->fParam2 == OP_PARM_Eb /* r8/mem8 */)
+ || ( pDis->pCurInstr->fParam2 == OP_PARM_Gb /* r8 */
+ && pDis->pCurInstr->fParam1 == OP_PARM_Eb /* r8/mem8 */))
+ )
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_ADD:
+ case OP_OR:
+ case OP_ADC:
+ case OP_SBB:
+ case OP_AND:
+ case OP_SUB:
+ case OP_XOR:
+ case OP_CMP:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ /* Instructions taking no address or operand which thus may be annoyingly
+ difficult to format for yasm. */
+ if (fPrefixes)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_STI:
+ case OP_STC:
+ case OP_CLI:
+ case OP_CLD:
+ case OP_CLC:
+ case OP_INT:
+ case OP_INT3:
+ case OP_INTO:
+ case OP_HLT:
+ /** @todo Many more to can be added here. */
+ return true;
+ default:
+ break;
+ }
+ }
+
+ /* FPU and other instructions that ignores operand size override. */
+ if (fPrefixes & DISPREFIX_OPSIZE)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ /* FPU: */
+ case OP_FIADD:
+ case OP_FIMUL:
+ case OP_FISUB:
+ case OP_FISUBR:
+ case OP_FIDIV:
+ case OP_FIDIVR:
+ /** @todo there are many more. */
+ return true;
+
+ case OP_MOV:
+ /** @todo could be that we're not disassembling these correctly. */
+ if (pDis->pCurInstr->fParam1 == OP_PARM_Sw)
+ return true;
+ /** @todo what about the other way? */
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ /*
+ * Check for the version of xyz reg,reg instruction that the assembler doesn't use.
+ *
+ * For example:
+ * expected: 1aee sbb ch, dh ; SBB r8, r/m8
+ * yasm: 18F5 sbb ch, dh ; SBB r/m8, r8
+ */
+ if (pDis->ModRM.Bits.Mod == 3 /* reg,reg */)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_ADD:
+ case OP_OR:
+ case OP_ADC:
+ case OP_SBB:
+ case OP_AND:
+ case OP_SUB:
+ case OP_XOR:
+ case OP_CMP:
+ if ( ( pDis->pCurInstr->fParam1 == OP_PARM_Gb /* r8 */
+ && pDis->pCurInstr->fParam2 == OP_PARM_Eb /* r8/mem8 */)
+ || ( pDis->pCurInstr->fParam1 == OP_PARM_Gv /* rX */
+ && pDis->pCurInstr->fParam2 == OP_PARM_Ev /* rX/memX */))
+ return true;
+
+ /* 82 (see table A-6). */
+ if (pDis->bOpCode == 0x82)
+ return true;
+ break;
+
+ /* ff /0, fe /0, ff /1, fe /0 */
+ case OP_DEC:
+ case OP_INC:
+ return true;
+
+ case OP_POP:
+ case OP_PUSH:
+ Assert(pDis->bOpCode == 0x8f);
+ return true;
+
+ case OP_MOV:
+ if ( pDis->bOpCode == 0x8a
+ || pDis->bOpCode == 0x8b)
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* shl eax,1 will be assembled to the form without the immediate byte. */
+ if ( pDis->pCurInstr->fParam2 == OP_PARM_Ib
+ && (uint8_t)pDis->Param2.uValue == 1)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_SHL:
+ case OP_SHR:
+ case OP_SAR:
+ case OP_RCL:
+ case OP_RCR:
+ case OP_ROL:
+ case OP_ROR:
+ return true;
+ }
+ }
+
+ /* And some more - see table A-6. */
+ if (pDis->bOpCode == 0x82)
+ {
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_ADD:
+ case OP_OR:
+ case OP_ADC:
+ case OP_SBB:
+ case OP_AND:
+ case OP_SUB:
+ case OP_XOR:
+ case OP_CMP:
+ return true;
+ break;
+ }
+ }
+
+
+ /* check for REX.X = 1 without SIB. */
+
+ /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual
+ says (intel doesn't appear to care). */
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ case OP_SETO:
+ case OP_SETNO:
+ case OP_SETC:
+ case OP_SETNC:
+ case OP_SETE:
+ case OP_SETNE:
+ case OP_SETBE:
+ case OP_SETNBE:
+ case OP_SETS:
+ case OP_SETNS:
+ case OP_SETP:
+ case OP_SETNP:
+ case OP_SETL:
+ case OP_SETNL:
+ case OP_SETLE:
+ case OP_SETNLE:
+ AssertMsg(pDis->bOpCode >= 0x90 && pDis->bOpCode <= 0x9f, ("%#x\n", pDis->bOpCode));
+ if (pDis->ModRM.Bits.Reg != 2)
+ return true;
+ break;
+ }
+
+ /*
+ * The MOVZX reg32,mem16 instruction without an operand size prefix
+ * doesn't quite make sense...
+ */
+ if ( pDis->pCurInstr->uOpcode == OP_MOVZX
+ && pDis->bOpCode == 0xB7
+ && (pDis->uCpuMode == DISCPUMODE_16BIT) != !!(fPrefixes & DISPREFIX_OPSIZE))
+ return true;
+
+ /*
+ * YASM doesn't do ICEBP/INT1/INT01, unlike NASM.
+ */
+ if (pDis->bOpCode == 0xF1)
+ return true;
+
+ return false;
+}
+
diff --git a/src/VBox/Disassembler/DisasmInternal.h b/src/VBox/Disassembler/DisasmInternal.h
new file mode 100644
index 00000000..cf233fb5
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmInternal.h
@@ -0,0 +1,262 @@
+/* $Id: DisasmInternal.h $ */
+/** @file
+ * VBox disassembler - Internal header.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_DisasmInternal_h
+#define VBOX_INCLUDED_SRC_DisasmInternal_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/dis.h>
+
+
+/** @defgroup grp_dis_int Internals.
+ * @ingroup grp_dis
+ * @{
+ */
+
+/** @name Index into g_apfnCalcSize and g_apfnFullDisasm.
+ * @{ */
+enum IDX_Parse
+{
+ IDX_ParseNop = 0,
+ IDX_ParseModRM,
+ IDX_UseModRM,
+ IDX_ParseImmByte,
+ IDX_ParseImmBRel,
+ IDX_ParseImmUshort,
+ IDX_ParseImmV,
+ IDX_ParseImmVRel,
+ IDX_ParseImmAddr,
+ IDX_ParseFixedReg,
+ IDX_ParseImmUlong,
+ IDX_ParseImmQword,
+ IDX_ParseTwoByteEsc,
+ IDX_ParseGrp1,
+ IDX_ParseShiftGrp2,
+ IDX_ParseGrp3,
+ IDX_ParseGrp4,
+ IDX_ParseGrp5,
+ IDX_Parse3DNow,
+ IDX_ParseGrp6,
+ IDX_ParseGrp7,
+ IDX_ParseGrp8,
+ IDX_ParseGrp9,
+ IDX_ParseGrp10,
+ IDX_ParseGrp12,
+ IDX_ParseGrp13,
+ IDX_ParseGrp14,
+ IDX_ParseGrp15,
+ IDX_ParseGrp16,
+ IDX_ParseGrp17,
+ IDX_ParseModFence,
+ IDX_ParseYv,
+ IDX_ParseYb,
+ IDX_ParseXv,
+ IDX_ParseXb,
+ IDX_ParseEscFP,
+ IDX_ParseNopPause,
+ IDX_ParseImmByteSX,
+ IDX_ParseImmZ,
+ IDX_ParseThreeByteEsc4,
+ IDX_ParseThreeByteEsc5,
+ IDX_ParseImmAddrF,
+ IDX_ParseInvOpModRM,
+ IDX_ParseVex2b,
+ IDX_ParseVex3b,
+ IDX_ParseVexDest,
+ IDX_ParseMax
+};
+AssertCompile(IDX_ParseMax < 64 /* Packed DISOPCODE assumption. */);
+/** @} */
+
+/**
+ * Opcode map descriptor.
+ *
+ * This is used a number of places to save storage space where there are lots of
+ * invalid instructions and the beginning or end of the map.
+ */
+typedef struct DISOPMAPDESC
+{
+ /** Pointer to the opcodes described by this structure. */
+ PCDISOPCODE papOpcodes;
+#if ARCH_BITS <= 32
+ uint16_t
+#else
+ uint32_t
+#endif
+ /** The map index corresponding to the first papOpcodes entry. */
+ idxFirst,
+ /** Number of opcodes in the map. */
+ cOpcodes;
+} DISOPMAPDESC;
+/** Pointer to a const opcode map descriptor. */
+typedef DISOPMAPDESC const *PCDISOPMAPDESC;
+
+/** @name Opcode maps.
+ * @{ */
+extern const DISOPCODE g_InvalidOpcode[1];
+
+extern const DISOPCODE g_aOneByteMapX86[256];
+extern const DISOPCODE g_aOneByteMapX64[256];
+extern const DISOPCODE g_aTwoByteMapX86[256];
+
+/** Two byte opcode map with prefix 0x66 */
+extern const DISOPCODE g_aTwoByteMapX86_PF66[256];
+
+/** Two byte opcode map with prefix 0xF2 */
+extern const DISOPCODE g_aTwoByteMapX86_PFF2[256];
+
+/** Two byte opcode map with prefix 0xF3 */
+extern const DISOPCODE g_aTwoByteMapX86_PFF3[256];
+
+/** Three byte opcode map (0xF 0x38) */
+extern PCDISOPCODE const g_apThreeByteMapX86_0F38[16];
+
+/** Three byte opcode map with prefix 0x66 (0xF 0x38) */
+extern PCDISOPCODE const g_apThreeByteMapX86_660F38[16];
+
+/** Three byte opcode map with prefix 0xF2 (0xF 0x38) */
+extern PCDISOPCODE const g_apThreeByteMapX86_F20F38[16];
+
+/** Three byte opcode map with prefix 0xF3 (0xF 0x38) */
+extern PCDISOPCODE const g_apThreeByteMapX86_F30F38[16];
+
+extern PCDISOPCODE const g_apThreeByteMapX86_0F3A[16];
+
+/** Three byte opcode map with prefix 0x66 (0xF 0x3A) */
+extern PCDISOPCODE const g_apThreeByteMapX86_660F3A[16];
+
+/** Three byte opcode map with prefixes 0x66 0xF2 (0xF 0x38) */
+extern PCDISOPCODE const g_apThreeByteMapX86_66F20F38[16];
+
+/** VEX opcodes table defined by [VEX.m-mmmm - 1].
+ * 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 00b */
+extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_None[3];
+
+/** VEX opcodes table defined by [VEX.m-mmmm - 1].
+ * 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 01b (66h) */
+extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_66H[3];
+
+/** 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 10b (F3h) */
+extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_F3H[3];
+
+/** 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 11b (F2h) */
+extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_F2H[3];
+
+/** Two dimmentional map descriptor array: first index is by VEX.pp (prefix),
+ * second by the VEX.mmmm (map).
+ * The latter has to be bounced checked as we only have the first 4 maps. */
+extern PCDISOPMAPDESC const g_aapVexOpcodesMapRanges[4][4];
+/** @} */
+
+/** @name Opcode extensions (Group tables)
+ * @{ */
+extern const DISOPCODE g_aMapX86_Group1[8*4];
+extern const DISOPCODE g_aMapX86_Group2[8*6];
+extern const DISOPCODE g_aMapX86_Group3[8*2];
+extern const DISOPCODE g_aMapX86_Group4[8];
+extern const DISOPCODE g_aMapX86_Group5[8];
+extern const DISOPCODE g_aMapX86_Group6[8];
+extern const DISOPCODE g_aMapX86_Group7_mem[8];
+extern const DISOPCODE g_aMapX86_Group7_mod11_rm000[8];
+extern const DISOPCODE g_aMapX86_Group7_mod11_rm001[8];
+extern const DISOPCODE g_aMapX86_Group8[8];
+extern const DISOPCODE g_aMapX86_Group9[8];
+extern const DISOPCODE g_aMapX86_Group10[8];
+extern const DISOPCODE g_aMapX86_Group11[8*2];
+extern const DISOPCODE g_aMapX86_Group12[8*2];
+extern const DISOPCODE g_aMapX86_Group13[8*2];
+extern const DISOPCODE g_aMapX86_Group14[8*2];
+extern const DISOPCODE g_aMapX86_Group15_mem[8];
+extern const DISOPCODE g_aMapX86_Group15_mod11_rm000[8];
+extern const DISOPCODE g_aMapX86_Group16[8];
+extern const DISOPCODE g_aMapX86_Group17[8*2];
+extern const DISOPCODE g_aMapX86_NopPause[2];
+/** @} */
+
+/** 3DNow! map (0x0F 0x0F prefix) */
+extern const DISOPCODE g_aTwoByteMapX86_3DNow[256];
+
+/** Floating point opcodes starting with escape byte 0xDF
+ * @{ */
+extern const DISOPCODE g_aMapX86_EscF0_Low[8];
+extern const DISOPCODE g_aMapX86_EscF0_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF1_Low[8];
+extern const DISOPCODE g_aMapX86_EscF1_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF2_Low[8];
+extern const DISOPCODE g_aMapX86_EscF2_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF3_Low[8];
+extern const DISOPCODE g_aMapX86_EscF3_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF4_Low[8];
+extern const DISOPCODE g_aMapX86_EscF4_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF5_Low[8];
+extern const DISOPCODE g_aMapX86_EscF5_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF6_Low[8];
+extern const DISOPCODE g_aMapX86_EscF6_High[16*4];
+extern const DISOPCODE g_aMapX86_EscF7_Low[8];
+extern const DISOPCODE g_aMapX86_EscF7_High[16*4];
+
+extern const PCDISOPCODE g_apMapX86_FP_Low[8];
+extern const PCDISOPCODE g_apMapX86_FP_High[8];
+/** @} */
+
+/** @def OP
+ * Wrapper which initializes an DISOPCODE.
+ * We must use this so that we can exclude unused fields in order
+ * to save precious bytes in the GC version.
+ *
+ * @internal
+ */
+#if DISOPCODE_FORMAT == 0
+# define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
+ { pszOpcode, idxParse1, idxParse2, idxParse3, 0, opcode, param1, param2, param3, 0, 0, optype }
+# define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \
+ { pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, 0, optype | DISOPTYPE_SSE }
+
+#elif DISOPCODE_FORMAT == 16
+# define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
+ { optype, opcode, idxParse1, idxParse2, param1, param2, idxParse3, param3, 0, 0 }
+# define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \
+ { optype | DISOPTYPE_SSE, opcode, idxParse1, idxParse2, param1, param2, idxParse3, param3, param4, idxParse4 }
+
+#elif DISOPCODE_FORMAT == 15
+# define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
+ { opcode, idxParse1, idxParse2, idxParse3, param1, param2, param3, optype, 0, 0 }
+# define OPVEX(pszOpcode, idxParse1, idxParse2, idxParse3, idxParse4, opcode, param1, param2, param3, param4, optype) \
+ { opcode, idxParse1, idxParse2, idxParse3, param1, param2, param3, optype | DISOPTYPE_SSE, param4, idxParse4 }
+#else
+# error Unsupported DISOPCODE_FORMAT value
+#endif
+
+
+size_t disFormatBytes(PCDISSTATE pDis, char *pszDst, size_t cchDst, uint32_t fFlags);
+
+/** @} */
+#endif /* !VBOX_INCLUDED_SRC_DisasmInternal_h */
+
diff --git a/src/VBox/Disassembler/DisasmMisc.cpp b/src/VBox/Disassembler/DisasmMisc.cpp
new file mode 100644
index 00000000..16d90e8d
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmMisc.cpp
@@ -0,0 +1,175 @@
+/* $Id: DisasmMisc.cpp $ */
+/** @file
+ * VBox disassembler- Misc Helpers.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DIS
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include <iprt/errcore.h>
+#include <VBox/log.h>
+#include <VBox/vmm/cpum.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#include "DisasmInternal.h"
+
+
+DISDECL(uint8_t) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam)
+{
+ unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
+ switch (subtype)
+ {
+ case OP_PARM_v:
+ switch (pDis->uOpMode)
+ {
+ case DISCPUMODE_32BIT:
+ return 4;
+ case DISCPUMODE_64BIT:
+ return 8;
+ case DISCPUMODE_16BIT:
+ return 2;
+ default: AssertFailed(); /* make gcc happy */ return 4;
+ }
+ break;
+
+ case OP_PARM_b:
+ return 1;
+
+ case OP_PARM_w:
+ return 2;
+
+ case OP_PARM_d:
+ return 4;
+
+ case OP_PARM_q:
+ return 8;
+
+ case OP_PARM_dq:
+ return 16;
+
+ case OP_PARM_qq:
+ return 32;
+
+ case 0: /* nop, pause, lea, wrmsr, rdmsr, etc. Most of these due to DISOPPARAM::cb being initialized in the wrong place
+ (disParseInstruction) where it will be called on intermediate stuff like IDX_ParseTwoByteEsc. The parameter
+ parsers should do it instead, though I see the potential filtering issue. */
+ //Assert( pDis->pCurInstr
+ // && ( pDis->pCurInstr->uOpcode == OP_NOP
+ // || pDis->pCurInstr->uOpcode == OP_LEA ));
+ return 0;
+
+ case OP_PARM_p: /* far pointer */
+ if (pDis->uAddrMode == DISCPUMODE_32BIT)
+ return 6; /* 16:32 */
+ if (pDis->uAddrMode == DISCPUMODE_64BIT)
+ return 12; /* 16:64 */
+ return 4; /* 16:16 */
+
+ case OP_PARM_s: /* lgdt, sgdt, lidt, sidt */
+ return pDis->uCpuMode == DISCPUMODE_64BIT ? 2 + 8 : 2 + 4;
+
+ case OP_PARM_a:
+ return pDis->uOpMode == DISCPUMODE_16BIT ? 2 + 2 : 4 + 4;
+
+ case OP_PARM_pi:
+ return 8;
+
+ case OP_PARM_sd:
+ case OP_PARM_ss:
+ return 16;
+
+ case OP_PARM_x:
+ case OP_PARM_pd:
+ case OP_PARM_ps:
+ return VEXREG_IS256B(pDis->bVexDestReg) ? 32 : 16; //??
+
+ case OP_PARM_y:
+ return pDis->uOpMode == DISCPUMODE_64BIT ? 4 : 8; //??
+
+ case OP_PARM_z:
+ if (pParam->cb)
+ return pParam->cb;
+ return pDis->uOpMode == DISCPUMODE_16BIT ? 2 : 4; //??
+
+ default:
+ if (pParam->cb)
+ return pParam->cb;
+ /// @todo dangerous!!!
+ AssertMsgFailed(("subtype=%#x fParam=%#x fUse=%#RX64 op=%#x\n", subtype, pParam->fParam, pParam->fUse,
+ pDis->pCurInstr ? pDis->pCurInstr->uOpcode : 0));
+ return 4;
+ }
+}
+
+#if 0 /* currently unused */
+DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam)
+{
+ if (pDis->fPrefix & DISPREFIX_SEG)
+ /* Use specified SEG: prefix. */
+ return (DISSELREG)pDis->idxSegPrefix;
+
+ /* Guess segment register by parameter type. */
+ if (pParam->fUse & (DISUSE_REG_GEN32|DISUSE_REG_GEN64|DISUSE_REG_GEN16))
+ {
+ AssertCompile(DISGREG_ESP == DISGREG_RSP);
+ AssertCompile(DISGREG_EBP == DISGREG_RBP);
+ AssertCompile(DISGREG_ESP == DISGREG_SP);
+ AssertCompile(DISGREG_EBP == DISGREG_BP);
+ if (pParam->Base.idxGenReg == DISGREG_ESP || pParam->Base.idxGenReg == DISGREG_EBP)
+ return DISSELREG_SS;
+ }
+ /* Default is use DS: for data access. */
+ return DISSELREG_DS;
+}
+
+
+DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis)
+{
+ Assert(pDis->fPrefix & DISPREFIX_SEG);
+ switch (pDis->idxSegPrefix)
+ {
+ case DISSELREG_ES:
+ return 0x26;
+ case DISSELREG_CS:
+ return 0x2E;
+ case DISSELREG_SS:
+ return 0x36;
+ case DISSELREG_DS:
+ return 0x3E;
+ case DISSELREG_FS:
+ return 0x64;
+ case DISSELREG_GS:
+ return 0x65;
+ default:
+ AssertFailed();
+ return 0;
+ }
+}
+#endif
diff --git a/src/VBox/Disassembler/DisasmReg.cpp b/src/VBox/Disassembler/DisasmReg.cpp
new file mode 100644
index 00000000..155e525b
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmReg.cpp
@@ -0,0 +1,685 @@
+/* $Id: DisasmReg.cpp $ */
+/** @file
+ * VBox disassembler- Register Info Helpers.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DIS
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include <iprt/errcore.h>
+#include <VBox/log.h>
+#include <VBox/vmm/cpum.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#include "DisasmInternal.h"
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/**
+ * Array for accessing 64-bit general registers in VMMREGFRAME structure
+ * by register's index from disasm.
+ */
+static const unsigned g_aReg64Index[] =
+{
+ RT_OFFSETOF(CPUMCTXCORE, rax), /* DISGREG_RAX */
+ RT_OFFSETOF(CPUMCTXCORE, rcx), /* DISGREG_RCX */
+ RT_OFFSETOF(CPUMCTXCORE, rdx), /* DISGREG_RDX */
+ RT_OFFSETOF(CPUMCTXCORE, rbx), /* DISGREG_RBX */
+ RT_OFFSETOF(CPUMCTXCORE, rsp), /* DISGREG_RSP */
+ RT_OFFSETOF(CPUMCTXCORE, rbp), /* DISGREG_RBP */
+ RT_OFFSETOF(CPUMCTXCORE, rsi), /* DISGREG_RSI */
+ RT_OFFSETOF(CPUMCTXCORE, rdi), /* DISGREG_RDI */
+ RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8 */
+ RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9 */
+ RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10 */
+ RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11 */
+ RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12 */
+ RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13 */
+ RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14 */
+ RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15 */
+};
+
+/**
+ * Macro for accessing 64-bit general purpose registers in CPUMCTXCORE structure.
+ */
+#define DIS_READ_REG64(p, idx) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]))
+#define DIS_WRITE_REG64(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]) = val)
+#define DIS_PTR_REG64(p, idx) ( (uint64_t *)((char *)(p) + g_aReg64Index[idx]))
+
+/**
+ * Array for accessing 32-bit general registers in VMMREGFRAME structure
+ * by register's index from disasm.
+ */
+static const unsigned g_aReg32Index[] =
+{
+ RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_EAX */
+ RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_ECX */
+ RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_EDX */
+ RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_EBX */
+ RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_ESP */
+ RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_EBP */
+ RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_ESI */
+ RT_OFFSETOF(CPUMCTXCORE, edi), /* DISGREG_EDI */
+ RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8D */
+ RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9D */
+ RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R1D */
+ RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11D */
+ RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12D */
+ RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13D */
+ RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14D */
+ RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15D */
+};
+
+/**
+ * Macro for accessing 32-bit general purpose registers in CPUMCTXCORE structure.
+ */
+#define DIS_READ_REG32(p, idx) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]))
+/* From http://www.cs.cmu.edu/~fp/courses/15213-s06/misc/asm64-handout.pdf:
+ * ``Perhaps unexpectedly, instructions that move or generate 32-bit register
+ * values also set the upper 32 bits of the register to zero. Consequently
+ * there is no need for an instruction movzlq.''
+ */
+#define DIS_WRITE_REG32(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg32Index[idx]) = (uint32_t)val)
+#define DIS_PTR_REG32(p, idx) ( (uint32_t *)((char *)(p) + g_aReg32Index[idx]))
+
+/**
+ * Array for accessing 16-bit general registers in CPUMCTXCORE structure
+ * by register's index from disasm.
+ */
+static const unsigned g_aReg16Index[] =
+{
+ RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_AX */
+ RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_CX */
+ RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_DX */
+ RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_BX */
+ RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_SP */
+ RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_BP */
+ RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_SI */
+ RT_OFFSETOF(CPUMCTXCORE, edi), /* DISGREG_DI */
+ RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8W */
+ RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9W */
+ RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10W */
+ RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11W */
+ RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12W */
+ RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13W */
+ RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14W */
+ RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15W */
+};
+
+/**
+ * Macro for accessing 16-bit general purpose registers in CPUMCTXCORE structure.
+ */
+#define DIS_READ_REG16(p, idx) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]))
+#define DIS_WRITE_REG16(p, idx, val) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]) = val)
+#define DIS_PTR_REG16(p, idx) ( (uint16_t *)((char *)(p) + g_aReg16Index[idx]))
+
+/**
+ * Array for accessing 8-bit general registers in CPUMCTXCORE structure
+ * by register's index from disasm.
+ */
+static const unsigned g_aReg8Index[] =
+{
+ RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_AL */
+ RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_CL */
+ RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_DL */
+ RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_BL */
+ RT_OFFSETOF_ADD(CPUMCTXCORE, eax, 1), /* DISGREG_AH */
+ RT_OFFSETOF_ADD(CPUMCTXCORE, ecx, 1), /* DISGREG_CH */
+ RT_OFFSETOF_ADD(CPUMCTXCORE, edx, 1), /* DISGREG_DH */
+ RT_OFFSETOF_ADD(CPUMCTXCORE, ebx, 1), /* DISGREG_BH */
+ RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8B */
+ RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9B */
+ RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10B*/
+ RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11B */
+ RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12B */
+ RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13B */
+ RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14B */
+ RT_OFFSETOF(CPUMCTXCORE, r15), /* DISGREG_R15B */
+ RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_SPL; with REX prefix only */
+ RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_BPL; with REX prefix only */
+ RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_SIL; with REX prefix only */
+ RT_OFFSETOF(CPUMCTXCORE, edi) /* DISGREG_DIL; with REX prefix only */
+};
+
+/**
+ * Macro for accessing 8-bit general purpose registers in CPUMCTXCORE structure.
+ */
+#define DIS_READ_REG8(p, idx) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]))
+#define DIS_WRITE_REG8(p, idx, val) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]) = val)
+#define DIS_PTR_REG8(p, idx) ( (uint8_t *)((char *)(p) + g_aReg8Index[idx]))
+
+/**
+ * Array for accessing segment registers in CPUMCTXCORE structure
+ * by register's index from disasm.
+ */
+static const unsigned g_aRegSegIndex[] =
+{
+ RT_OFFSETOF(CPUMCTXCORE, es), /* DISSELREG_ES */
+ RT_OFFSETOF(CPUMCTXCORE, cs), /* DISSELREG_CS */
+ RT_OFFSETOF(CPUMCTXCORE, ss), /* DISSELREG_SS */
+ RT_OFFSETOF(CPUMCTXCORE, ds), /* DISSELREG_DS */
+ RT_OFFSETOF(CPUMCTXCORE, fs), /* DISSELREG_FS */
+ RT_OFFSETOF(CPUMCTXCORE, gs) /* DISSELREG_GS */
+};
+
+/**
+ * Macro for accessing segment registers in CPUMCTXCORE structure.
+ */
+#define DIS_READ_REGSEG(p, idx) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])))
+#define DIS_WRITE_REGSEG(p, idx, val) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])) = val)
+
+
+
+/**
+ * Returns the value of the specified 8 bits general purpose register
+ *
+ */
+DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal)
+{
+ AssertReturnStmt(reg8 < RT_ELEMENTS(g_aReg8Index), *pVal = 0, VERR_INVALID_PARAMETER);
+
+ *pVal = DIS_READ_REG8(pCtx, reg8);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the value of the specified 16 bits general purpose register
+ *
+ */
+DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal)
+{
+ AssertReturnStmt(reg16 < RT_ELEMENTS(g_aReg16Index), *pVal = 0, VERR_INVALID_PARAMETER);
+
+ *pVal = DIS_READ_REG16(pCtx, reg16);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the value of the specified 32 bits general purpose register
+ *
+ */
+DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal)
+{
+ AssertReturnStmt(reg32 < RT_ELEMENTS(g_aReg32Index), *pVal = 0, VERR_INVALID_PARAMETER);
+
+ *pVal = DIS_READ_REG32(pCtx, reg32);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the value of the specified 64 bits general purpose register
+ *
+ */
+DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal)
+{
+ AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *pVal = 0, VERR_INVALID_PARAMETER);
+
+ *pVal = DIS_READ_REG64(pCtx, reg64);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the pointer to the specified 8 bits general purpose register
+ *
+ */
+DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg)
+{
+ AssertReturnStmt(reg8 < RT_ELEMENTS(g_aReg8Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
+
+ *ppReg = DIS_PTR_REG8(pCtx, reg8);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the pointer to the specified 16 bits general purpose register
+ *
+ */
+DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg)
+{
+ AssertReturnStmt(reg16 < RT_ELEMENTS(g_aReg16Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
+
+ *ppReg = DIS_PTR_REG16(pCtx, reg16);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the pointer to the specified 32 bits general purpose register
+ */
+DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg)
+{
+ AssertReturnStmt(reg32 < RT_ELEMENTS(g_aReg32Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
+
+ *ppReg = DIS_PTR_REG32(pCtx, reg32);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the pointer to the specified 64 bits general purpose register
+ */
+DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg)
+{
+ AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *ppReg = NULL, VERR_INVALID_PARAMETER);
+
+ *ppReg = DIS_PTR_REG64(pCtx, reg64);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the value of the specified segment register
+ */
+DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal)
+{
+ AssertReturn((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
+
+ AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
+ *pVal = DIS_READ_REGSEG(pCtx, sel);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Updates the value of the specified 64 bits general purpose register
+ *
+ */
+DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64)
+{
+ AssertReturn(reg64 < RT_ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
+
+ DIS_WRITE_REG64(pRegFrame, reg64, val64);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Updates the value of the specified 32 bits general purpose register
+ *
+ */
+DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32)
+{
+ AssertReturn(reg32 < RT_ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
+
+ DIS_WRITE_REG32(pRegFrame, reg32, val32);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Updates the value of the specified 16 bits general purpose register
+ *
+ */
+DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg16, uint16_t val16)
+{
+ AssertReturn(reg16 < RT_ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
+
+ DIS_WRITE_REG16(pRegFrame, reg16, val16);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Updates the specified 8 bits general purpose register
+ *
+ */
+DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8)
+{
+ AssertReturn(reg8 < RT_ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
+
+ DIS_WRITE_REG8(pRegFrame, reg8, val8);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Updates the specified segment register
+ *
+ */
+DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val)
+{
+ AssertReturn((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
+
+ AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
+ DIS_WRITE_REGSEG(pCtx, sel, val);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the value of the parameter in pParam
+ *
+ * @returns VBox error code
+ * @param pCtx CPU context structure pointer
+ * @param pDis Pointer to the disassembler state.
+ * @param pParam Pointer to the parameter to parse
+ * @param pParamVal Pointer to parameter value (OUT)
+ * @param parmtype Parameter type
+ *
+ * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
+ *
+ */
+DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype)
+{
+ memset(pParamVal, 0, sizeof(*pParamVal));
+
+ if (DISUSE_IS_EFFECTIVE_ADDR(pParam->fUse))
+ {
+ // Effective address
+ pParamVal->type = DISQPV_TYPE_ADDRESS;
+ pParamVal->size = pParam->cb;
+
+ if (pParam->fUse & DISUSE_BASE)
+ {
+ if (pParam->fUse & DISUSE_REG_GEN8)
+ {
+ pParamVal->flags |= DISQPV_FLAG_8;
+ if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN16)
+ {
+ pParamVal->flags |= DISQPV_FLAG_16;
+ if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN32)
+ {
+ pParamVal->flags |= DISQPV_FLAG_32;
+ if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN64)
+ {
+ pParamVal->flags |= DISQPV_FLAG_64;
+ if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ AssertFailed();
+ return VERR_INVALID_PARAMETER;
+ }
+ }
+ // Note that scale implies index (SIB byte)
+ if (pParam->fUse & DISUSE_INDEX)
+ {
+ if (pParam->fUse & DISUSE_REG_GEN16)
+ {
+ uint16_t val16;
+
+ pParamVal->flags |= DISQPV_FLAG_16;
+ if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Index.idxGenReg, &val16))) return VERR_INVALID_PARAMETER;
+
+ Assert(!(pParam->fUse & DISUSE_SCALE)); /* shouldn't be possible in 16 bits mode */
+
+ pParamVal->val.val16 += val16;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN32)
+ {
+ uint32_t val32;
+
+ pParamVal->flags |= DISQPV_FLAG_32;
+ if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Index.idxGenReg, &val32))) return VERR_INVALID_PARAMETER;
+
+ if (pParam->fUse & DISUSE_SCALE)
+ val32 *= pParam->uScale;
+
+ pParamVal->val.val32 += val32;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN64)
+ {
+ uint64_t val64;
+
+ pParamVal->flags |= DISQPV_FLAG_64;
+ if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Index.idxGenReg, &val64))) return VERR_INVALID_PARAMETER;
+
+ if (pParam->fUse & DISUSE_SCALE)
+ val64 *= pParam->uScale;
+
+ pParamVal->val.val64 += val64;
+ }
+ else
+ AssertFailed();
+ }
+
+ if (pParam->fUse & DISUSE_DISPLACEMENT8)
+ {
+ if (pDis->uCpuMode == DISCPUMODE_32BIT)
+ pParamVal->val.i32 += (int32_t)pParam->uDisp.i8;
+ else if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ pParamVal->val.i64 += (int64_t)pParam->uDisp.i8;
+ else
+ pParamVal->val.i16 += (int16_t)pParam->uDisp.i8;
+ }
+ else if (pParam->fUse & DISUSE_DISPLACEMENT16)
+ {
+ if (pDis->uCpuMode == DISCPUMODE_32BIT)
+ pParamVal->val.i32 += (int32_t)pParam->uDisp.i16;
+ else if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ pParamVal->val.i64 += (int64_t)pParam->uDisp.i16;
+ else
+ pParamVal->val.i16 += pParam->uDisp.i16;
+ }
+ else if (pParam->fUse & DISUSE_DISPLACEMENT32)
+ {
+ if (pDis->uCpuMode == DISCPUMODE_32BIT)
+ pParamVal->val.i32 += pParam->uDisp.i32;
+ else
+ pParamVal->val.i64 += pParam->uDisp.i32;
+ }
+ else if (pParam->fUse & DISUSE_DISPLACEMENT64)
+ {
+ Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
+ pParamVal->val.i64 += pParam->uDisp.i64;
+ }
+ else if (pParam->fUse & DISUSE_RIPDISPLACEMENT32)
+ {
+ Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
+ /* Relative to the RIP of the next instruction. */
+ pParamVal->val.i64 += pParam->uDisp.i32 + pCtx->rip + pDis->cbInstr;
+ }
+ return VINF_SUCCESS;
+ }
+
+ if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_GEN64|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST))
+ {
+ if (parmtype == DISQPVWHICH_DST)
+ {
+ // Caller needs to interpret the register according to the instruction (source/target, special value etc)
+ pParamVal->type = DISQPV_TYPE_REGISTER;
+ pParamVal->size = pParam->cb;
+ return VINF_SUCCESS;
+ }
+ //else DISQPVWHICH_SRC
+
+ pParamVal->type = DISQPV_TYPE_IMMEDIATE;
+
+ if (pParam->fUse & DISUSE_REG_GEN8)
+ {
+ pParamVal->flags |= DISQPV_FLAG_8;
+ pParamVal->size = sizeof(uint8_t);
+ if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN16)
+ {
+ pParamVal->flags |= DISQPV_FLAG_16;
+ pParamVal->size = sizeof(uint16_t);
+ if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN32)
+ {
+ pParamVal->flags |= DISQPV_FLAG_32;
+ pParamVal->size = sizeof(uint32_t);
+ if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN64)
+ {
+ pParamVal->flags |= DISQPV_FLAG_64;
+ pParamVal->size = sizeof(uint64_t);
+ if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ // Caller needs to interpret the register according to the instruction (source/target, special value etc)
+ pParamVal->type = DISQPV_TYPE_REGISTER;
+ }
+ Assert(!(pParam->fUse & DISUSE_IMMEDIATE));
+ return VINF_SUCCESS;
+ }
+
+ if (pParam->fUse & DISUSE_IMMEDIATE)
+ {
+ pParamVal->type = DISQPV_TYPE_IMMEDIATE;
+ if (pParam->fUse & (DISUSE_IMMEDIATE8|DISUSE_IMMEDIATE8_REL))
+ {
+ pParamVal->flags |= DISQPV_FLAG_8;
+ if (pParam->cb == 2)
+ {
+ pParamVal->size = sizeof(uint16_t);
+ pParamVal->val.val16 = (uint8_t)pParam->uValue;
+ }
+ else
+ {
+ pParamVal->size = sizeof(uint8_t);
+ pParamVal->val.val8 = (uint8_t)pParam->uValue;
+ }
+ }
+ else
+ if (pParam->fUse & (DISUSE_IMMEDIATE16|DISUSE_IMMEDIATE16_REL|DISUSE_IMMEDIATE_ADDR_0_16|DISUSE_IMMEDIATE16_SX8))
+ {
+ pParamVal->flags |= DISQPV_FLAG_16;
+ pParamVal->size = sizeof(uint16_t);
+ pParamVal->val.val16 = (uint16_t)pParam->uValue;
+ AssertMsg(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE16_SX8)), ("pParamVal->size %d vs %d EIP=%RX32\n", pParamVal->size, pParam->cb, pCtx->eip) );
+ }
+ else
+ if (pParam->fUse & (DISUSE_IMMEDIATE32|DISUSE_IMMEDIATE32_REL|DISUSE_IMMEDIATE_ADDR_0_32|DISUSE_IMMEDIATE32_SX8))
+ {
+ pParamVal->flags |= DISQPV_FLAG_32;
+ pParamVal->size = sizeof(uint32_t);
+ pParamVal->val.val32 = (uint32_t)pParam->uValue;
+ Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE32_SX8)) );
+ }
+ else
+ if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_REL | DISUSE_IMMEDIATE64_SX8))
+ {
+ pParamVal->flags |= DISQPV_FLAG_64;
+ pParamVal->size = sizeof(uint64_t);
+ pParamVal->val.val64 = pParam->uValue;
+ Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE64_SX8)) );
+ }
+ else
+ if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16))
+ {
+ pParamVal->flags |= DISQPV_FLAG_FARPTR16;
+ pParamVal->size = sizeof(uint16_t)*2;
+ pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->uValue >> 16);
+ pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->uValue);
+ Assert(pParamVal->size == pParam->cb);
+ }
+ else
+ if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_32))
+ {
+ pParamVal->flags |= DISQPV_FLAG_FARPTR32;
+ pParamVal->size = sizeof(uint16_t) + sizeof(uint32_t);
+ pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->uValue >> 32);
+ pParamVal->val.farptr.offset = (uint32_t)(pParam->uValue & 0xFFFFFFFF);
+ Assert(pParam->cb == 8);
+ }
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the pointer to a register of the parameter in pParam. We need this
+ * pointer when an interpreted instruction updates a register as a side effect.
+ * In CMPXCHG we know that only [r/e]ax is updated, but with XADD this could
+ * be every register.
+ *
+ * @returns VBox error code
+ * @param pCtx CPU context structure pointer
+ * @param pDis Pointer to the disassembler state.
+ * @param pParam Pointer to the parameter to parse
+ * @param pReg Pointer to parameter value (OUT)
+ * @param cbsize Parameter size (OUT)
+ *
+ * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
+ *
+ */
+DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize)
+{
+ NOREF(pDis);
+ if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST))
+ {
+ if (pParam->fUse & DISUSE_REG_GEN8)
+ {
+ uint8_t *pu8Reg;
+ if (RT_SUCCESS(DISPtrReg8(pCtx, pParam->Base.idxGenReg, &pu8Reg)))
+ {
+ *pcbSize = sizeof(uint8_t);
+ *ppReg = (void *)pu8Reg;
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN16)
+ {
+ uint16_t *pu16Reg;
+ if (RT_SUCCESS(DISPtrReg16(pCtx, pParam->Base.idxGenReg, &pu16Reg)))
+ {
+ *pcbSize = sizeof(uint16_t);
+ *ppReg = (void *)pu16Reg;
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN32)
+ {
+ uint32_t *pu32Reg;
+ if (RT_SUCCESS(DISPtrReg32(pCtx, pParam->Base.idxGenReg, &pu32Reg)))
+ {
+ *pcbSize = sizeof(uint32_t);
+ *ppReg = (void *)pu32Reg;
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ if (pParam->fUse & DISUSE_REG_GEN64)
+ {
+ uint64_t *pu64Reg;
+ if (RT_SUCCESS(DISPtrReg64(pCtx, pParam->Base.idxGenReg, &pu64Reg)))
+ {
+ *pcbSize = sizeof(uint64_t);
+ *ppReg = (void *)pu64Reg;
+ return VINF_SUCCESS;
+ }
+ }
+ }
+ return VERR_INVALID_PARAMETER;
+}
+
diff --git a/src/VBox/Disassembler/DisasmTables.cpp b/src/VBox/Disassembler/DisasmTables.cpp
new file mode 100644
index 00000000..d7971cdf
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmTables.cpp
@@ -0,0 +1,4320 @@
+/* $Id: DisasmTables.cpp $ */
+/** @file
+ * VBox disassembler - Tables for X86 (32-bit and 16-bit modes).
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include "DisasmInternal.h"
+
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+/// @todo Verify tables for correctness
+/// @todo opcode type (harmless, potentially dangerous, dangerous)
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+#ifndef DIS_CORE_ONLY
+static char g_szInvalidOpcode[] = "Invalid Opcode";
+#endif
+
+#define INVALID_OPCODE \
+ OP(g_szInvalidOpcode, 0, 0, 0, OP_INVALID, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INVALID)
+#define INVALID_OPCODE_BLOCK \
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,
+
+#define INVALID_OPCODE_MOD_RM(a_Index) \
+ OP(g_szInvalidOpcode, IDX_ParseInvOpModRM, 0, 0, OP_INVALID, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INVALID)
+#define INVALID_OPCODE_BLOCK_MOD_RM(a_UpperDigit) \
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 0),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 1),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 2),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 3),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 4),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 5),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 6),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 7),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 8),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## 9),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## a),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## b),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## c),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## d),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## e),\
+ INVALID_OPCODE_MOD_RM(a_UpperDigit ## f),
+
+
+/* Invalid opcode */
+const DISOPCODE g_InvalidOpcode[1] =
+{
+ INVALID_OPCODE
+};
+
+/* Tables for the elegant Intel X86 instruction set */
+const DISOPCODE g_aOneByteMapX86[256] =
+{
+ /* 0 */
+ OP("add %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_ADD, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_ADD, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("push ES", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ES, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("pop ES", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ES, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("or %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_OR, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_OR, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("push CS", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_CS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64 | DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("EscTwo0f", IDX_ParseTwoByteEsc, 0, 0, OP_2B_ESC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 1 */
+ OP("adc %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_ADC, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_ADC, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("push SS", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_SS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64 | DISOPTYPE_RRM_DANGEROUS),
+ OP("pop SS", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_SS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INHIBIT_IRQS | DISOPTYPE_INVALID_64 | DISOPTYPE_RRM_DANGEROUS),
+ OP("sbb %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_SBB, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_SBB, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("push DS", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_DS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("pop DS", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_DS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64 | DISOPTYPE_RRM_DANGEROUS),
+
+ /* 2 */
+ OP("and %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_AND, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_AND, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG ES", 0, 0, 0, OP_SEG, OP_PARM_REG_ES, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("daa", 0, 0, 0, OP_DAA, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("sub %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_SUB, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_SUB, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* Branch not taken hint prefix for branches on a Pentium 4 or Xeon CPU (or higher)! */
+ OP("SEG CS", 0, 0, 0, OP_SEG, OP_PARM_REG_CS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("das", 0, 0, 0, OP_DAS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+
+ /* 3 */
+ OP("xor %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_XOR, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_XOR, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG SS", 0, 0, 0, OP_SEG, OP_PARM_REG_SS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aaa", 0, 0, 0, OP_AAA, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("cmp %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_CMP, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_CMP, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* Branch not taken hint prefix for branches on a Pentium 4 or Xeon CPU (or higher)! */
+ OP("SEG DS", 0, 0, 0, OP_SEG, OP_PARM_REG_DS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aas", 0, 0, 0, OP_AAS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+
+ /* 4 */
+ OP("inc %eAX", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eCX", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eDX", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eBX", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eSP", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eBP", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eSI", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc %eDI", IDX_ParseFixedReg, 0, 0, OP_INC, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eAX", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eCX", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eDX", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eBX", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eSP", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eBP", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eSI", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %eDI", IDX_ParseFixedReg, 0, 0, OP_DEC, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 5 */
+ OP("push %eAX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eCX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eDX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eBX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eSP", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eBP", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eSI", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eDI", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eAX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eCX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eDX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eBX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eSP", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eBP", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eSI", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eDI", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+
+ /* 6 */
+ OP("pusha", 0, 0, 0, OP_PUSHA, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("popa", 0, 0, 0, OP_POPA, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("bound %Gv,%Ma", IDX_ParseModRM, IDX_UseModRM, 0, OP_BOUND, OP_PARM_Gv, OP_PARM_Ma, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("arpl %Ew,%Gw", IDX_ParseModRM, IDX_UseModRM, 0, OP_ARPL, OP_PARM_Ew, OP_PARM_Gw, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG FS", 0, 0, 0, OP_SEG, OP_PARM_REG_FS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG GS", 0, 0, 0, OP_SEG, OP_PARM_REG_GS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("OP SIZE", 0, 0, 0, OP_OPSIZE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ADR SIZE", 0, 0, 0, OP_ADDRSIZE,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("push %Iz", IDX_ParseImmZ, 0, 0, OP_PUSH, OP_PARM_Iz, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("imul %Gv,%Ev,%Iz", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmZ, OP_IMUL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_Iz, DISOPTYPE_HARMLESS),
+ OP("push %Ib", IDX_ParseImmByteSX, 0, 0, OP_PUSH, OP_PARM_Ib, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("imul %Gv,%Ev,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByteSX, OP_IMUL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("insb %Yb,DX", IDX_ParseYb, IDX_ParseFixedReg, 0, OP_INSB, OP_PARM_Yb, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("insw/d %Yv,DX", IDX_ParseYv, IDX_ParseFixedReg, 0, OP_INSWD, OP_PARM_Yv, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("outsb DX,%Xb", IDX_ParseFixedReg, IDX_ParseXb, 0, OP_OUTSB, OP_PARM_REG_DX, OP_PARM_Yb, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("outsw/d DX,%Xv", IDX_ParseFixedReg, IDX_ParseXv, 0, OP_OUTSWD, OP_PARM_REG_DX, OP_PARM_Yv, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+
+
+ /* 7 */
+ OP("jo %Jb", IDX_ParseImmBRel, 0, 0, OP_JO, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jno %Jb", IDX_ParseImmBRel, 0, 0, OP_JNO, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jc %Jb", IDX_ParseImmBRel, 0, 0, OP_JC, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jnc %Jb", IDX_ParseImmBRel, 0, 0, OP_JNC, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("je %Jb", IDX_ParseImmBRel, 0, 0, OP_JE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jne %Jb", IDX_ParseImmBRel, 0, 0, OP_JNE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jbe %Jb", IDX_ParseImmBRel, 0, 0, OP_JBE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jnbe %Jb", IDX_ParseImmBRel, 0, 0, OP_JNBE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("js %Jb", IDX_ParseImmBRel, 0, 0, OP_JS, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jns %Jb", IDX_ParseImmBRel, 0, 0, OP_JNS, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jp %Jb", IDX_ParseImmBRel, 0, 0, OP_JP, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jnp %Jb", IDX_ParseImmBRel, 0, 0, OP_JNP, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jl %Jb", IDX_ParseImmBRel, 0, 0, OP_JL, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jnl %Jb", IDX_ParseImmBRel, 0, 0, OP_JNL, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jle %Jb", IDX_ParseImmBRel, 0, 0, OP_JLE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("jnle %Jb", IDX_ParseImmBRel, 0, 0, OP_JNLE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+
+ /* 8 */
+ OP("Imm Grp1 %Eb,%Ib", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Imm Grp1 %Ev,%Iz", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Ev, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Imm Grp1 %Eb,%Ib", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("Imm Grp1 %Ev,%Ib", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Ev, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_TEST, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_TEST, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xchg %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XCHG, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xchg %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_XCHG, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ev,%Sw", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Sw, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("lea %Gv,%M", IDX_ParseModRM, IDX_UseModRM, 0, OP_LEA, OP_PARM_Gv, OP_PARM_M, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Sw,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Sw, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS | DISOPTYPE_INHIBIT_IRQS),
+ /** @todo this is grp 1a, actually */
+ OP("pop %Ev", IDX_ParseModRM, 0, 0, OP_POP, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 9 */
+ OP("nop/pause/xchg %eAX,%eAX", IDX_ParseNopPause, 0, 0, OP_NOP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xchg %eCX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_ECX, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eDX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EDX, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eBX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EBX, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eSP,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_ESP, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eBP,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EBP, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eSI,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_ESI, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eDI,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EDI, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("cbw", 0, 0, 0, OP_CBW, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cwd", 0, 0, 0, OP_CWD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("call %Ap", IDX_ParseImmAddrF, 0, 0, OP_CALL, OP_PARM_Ap, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_INVALID_64),
+ OP("wait", 0, 0, 0, OP_WAIT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pushf %Fv", 0, 0, 0, OP_PUSHF, OP_PARM_Fv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("popf %Fv", 0, 0, 0, OP_POPF, OP_PARM_Fv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("sahf", 0, 0, 0, OP_SAHF, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lahf", 0, 0, 0, OP_LAHF, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* A */
+ OP("mov AL,%Ob", IDX_ParseFixedReg, IDX_ParseImmAddr, 0, OP_MOV, OP_PARM_REG_AL, OP_PARM_Ob, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %eAX,%Ov", IDX_ParseFixedReg, IDX_ParseImmAddr, 0, OP_MOV, OP_PARM_REG_EAX, OP_PARM_Ov, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ob,AL", IDX_ParseImmAddr, IDX_ParseFixedReg, 0, OP_MOV, OP_PARM_Ob, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ov,%eAX", IDX_ParseImmAddr, IDX_ParseFixedReg, 0, OP_MOV, OP_PARM_Ov, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsb %Xb,%Yb", IDX_ParseXb, IDX_ParseYb, 0, OP_MOVSB, OP_PARM_Xb, OP_PARM_Yb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsw/d %Xv,%Yv", IDX_ParseXv, IDX_ParseYv, 0, OP_MOVSWD, OP_PARM_Xv, OP_PARM_Yv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmpsb %Xb,%Yb", IDX_ParseXb, IDX_ParseYb, 0, OP_CMPSB, OP_PARM_Xb, OP_PARM_Yb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmpsw/d %Xv,%Yv", IDX_ParseXv, IDX_ParseYv, 0, OP_CMPWD, OP_PARM_Xv, OP_PARM_Yv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_TEST, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_TEST, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stosb %Yb,AL", IDX_ParseYb, IDX_ParseFixedReg, 0, OP_STOSB, OP_PARM_Yb, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stosw/d %Yv,%eAX", IDX_ParseYv, IDX_ParseFixedReg, 0, OP_STOSWD, OP_PARM_Yv, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lodsb AL,%Xb", IDX_ParseFixedReg, IDX_ParseXb, 0, OP_LODSB, OP_PARM_REG_AL, OP_PARM_Xb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lodsw/d %eAX,%Xv", IDX_ParseFixedReg, IDX_ParseXv, 0, OP_LODSWD, OP_PARM_REG_EAX, OP_PARM_Xv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("scasb AL,%Xb", IDX_ParseFixedReg, IDX_ParseXb, 0, OP_SCASB, OP_PARM_REG_AL, OP_PARM_Xb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("scasw/d %eAX,%Xv", IDX_ParseFixedReg, IDX_ParseXv, 0, OP_SCASWD, OP_PARM_REG_EAX, OP_PARM_Xv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* B */
+ OP("mov AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov CL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_CL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov DL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_DL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov BL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_BL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov AH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_AH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov CH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_CH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov DH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_DH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov BH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_BH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eAX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EAX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eCX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_ECX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eDX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EDX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eBX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EBX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eSP,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_ESP, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eBP,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EBP, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eSI,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_ESI, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eDI,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EDI, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+
+ /* C */
+ OP("Shift Grp2 %Eb,%Ib", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Ev,%Ib", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Ev, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("retn %Iw", IDX_ParseImmUshort, 0, 0, OP_RETN, OP_PARM_Iw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("retn", 0, 0, 0, OP_RETN, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("les %Gv,%Mp", IDX_ParseModRM, IDX_UseModRM, 0, OP_LES, OP_PARM_Gv, OP_PARM_Mp, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("lds %Gv,%Mp", IDX_ParseModRM, IDX_UseModRM, 0, OP_LDS, OP_PARM_Gv, OP_PARM_Mp, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64 | DISOPTYPE_RRM_DANGEROUS),
+ /** @todo these two are actually group11 */
+ OP("mov %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("enter %Iw,%Ib", IDX_ParseImmUshort, IDX_ParseImmByte, 0, OP_ENTER, OP_PARM_Iw, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("leave", 0, 0, 0, OP_LEAVE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("retf %Iw", IDX_ParseImmUshort, 0, 0, OP_RETF, OP_PARM_Iw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+ OP("retf", 0, 0, 0, OP_RETF, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+ OP("int 3", 0, 0, 0, OP_INT3, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT),
+ OP("int %Ib", IDX_ParseImmByte, 0, 0, OP_INT, OP_PARM_Ib, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT),
+ OP("into", 0, 0, 0, OP_INTO, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT | DISOPTYPE_INVALID_64),
+ OP("iret", 0, 0, 0, OP_IRET, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+
+ /* D */
+ OP("Shift Grp2 %Eb,1", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Eb, OP_PARM_1, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Ev,1", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Ev, OP_PARM_1, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Eb,CL", IDX_ParseShiftGrp2, IDX_ParseFixedReg, 0, OP_SHIFT_GRP2, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Ev,CL", IDX_ParseShiftGrp2, IDX_ParseFixedReg, 0, OP_SHIFT_GRP2, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aam %Ib", IDX_ParseImmByte, 0, 0, OP_AAM, OP_PARM_Ib, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("aad %Ib", IDX_ParseImmByte, 0, 0, OP_AAD, OP_PARM_Ib, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ OP("salc", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_SALC, OP_PARM_REG_AL, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_INVALID_64),
+ /** @todo xlat has AL as both source and destination and DS:xBX as
+ * translation table pointer. */
+ OP("xlat", 0, 0, 0, OP_XLAT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf0", IDX_ParseEscFP, 0, 0, OP_ESCF0, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf1", IDX_ParseEscFP, 0, 0, OP_ESCF1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf2", IDX_ParseEscFP, 0, 0, OP_ESCF2, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf3", IDX_ParseEscFP, 0, 0, OP_ESCF3, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf4", IDX_ParseEscFP, 0, 0, OP_ESCF4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf5", IDX_ParseEscFP, 0, 0, OP_ESCF5, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf6", IDX_ParseEscFP, 0, 0, OP_ESCF6, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf7", IDX_ParseEscFP, 0, 0, OP_ESCF7, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* E */
+ OP("loopne %Jb", IDX_ParseImmBRel, 0, 0, OP_LOOPNE, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("loope %Jb", IDX_ParseImmBRel, 0, 0, OP_LOOPE, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("loop %Jb", IDX_ParseImmBRel, 0, 0, OP_LOOP, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("j(e)cxz %Jb", IDX_ParseImmBRel, 0, 0, OP_JECXZ, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE | DISOPTYPE_RELATIVE_CONTROLFLOW),
+ OP("in AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_IN, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("in %eAX,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_IN, OP_PARM_REG_EAX, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("out %Ib,AL", IDX_ParseImmByte, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_Ib, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("out %Ib,%eAX", IDX_ParseImmByte, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_Ib, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("call %Jv", IDX_ParseImmVRel, 0, 0, OP_CALL, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jmp %Jv", IDX_ParseImmVRel, 0, 0, OP_JMP, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jmp %Ap", IDX_ParseImmAddrF, 0, 0, OP_JMP, OP_PARM_Ap, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_INVALID_64),
+ OP("jmp %Jb", IDX_ParseImmBRel, 0, 0, OP_JMP, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("in AL,DX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_IN, OP_PARM_REG_AL, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("in %eAX,DX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_IN, OP_PARM_REG_EAX, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("out DX,AL", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_REG_DX, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("out DX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_REG_DX, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+
+
+ /* F */
+ OP("lock", 0, 0, 0, OP_LOCK, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("icebp", 0, 0, 0, OP_INT1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT),
+ OP("repne", 0, 0, 0, OP_REPNE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rep(e)", 0, 0, 0, OP_REPE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("hlt", 0, 0, 0, OP_HLT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_PRIVILEGED),
+ OP("cmc", 0, 0, 0, OP_CMC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Unary Grp3 %Eb", IDX_ParseGrp3, 0, 0, OP_UNARY_GRP3, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Unary Grp3 %Ev", IDX_ParseGrp3, 0, 0, OP_UNARY_GRP3, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("clc", 0, 0, 0, OP_CLC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stc", 0, 0, 0, OP_STC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cli", 0, 0, 0, OP_CLI, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("sti", 0, 0, 0, OP_STI, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED | DISOPTYPE_INHIBIT_IRQS),
+ OP("cld", 0, 0, 0, OP_CLD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("std", 0, 0, 0, OP_STD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc/dec Grp4", IDX_ParseGrp4, 0, 0, OP_INC_GRP4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Indirect Grp5", IDX_ParseGrp5, 0, 0, OP_IND_GRP5, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+const DISOPCODE g_aTwoByteMapX86[256] =
+{
+ /* 0 */
+ OP("Grp6", IDX_ParseGrp6, 0, 0, OP_GRP6, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Grp7", IDX_ParseGrp7, 0, 0, OP_GRP7, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lar %Gv,%Ew", IDX_ParseModRM, IDX_UseModRM, 0, OP_LAR, OP_PARM_Gv, OP_PARM_Ew, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ OP("lsl %Gv,%Ew", IDX_ParseModRM, IDX_UseModRM, 0, OP_LSL, OP_PARM_Gv, OP_PARM_Ew, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ INVALID_OPCODE,
+ OP("syscall", 0, 0, 0, OP_SYSCALL, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_ONLY_64),
+ OP("clts", 0, 0, 0, OP_CLTS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ OP("sysret", 0, 0, 0, OP_SYSRET, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_ONLY_64),
+ OP("invd", 0, 0, 0, OP_INVD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ OP("wbinvd", 0, 0, 0, OP_WBINVD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ INVALID_OPCODE,
+ OP("Two Byte Illegal Opcodes UD2", 0, 0, 0, OP_ILLUD2, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_ILLEGAL),
+ INVALID_OPCODE,
+ /* NOP Ev or prefetch (Intel vs AMD) */
+ OP("nop %Ev/prefetch", IDX_ParseModRM, 0, 0, OP_NOP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("femms", 0, 0, 0, OP_FEMMS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("3DNow! Esc", IDX_Parse3DNow, 0, 0, OP_3DNOW, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 1 */
+ OP("movups %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVUPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movups %Wps,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVUPS, OP_PARM_Wps, OP_PARM_Vps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* Next instruction has the following format:
+ * &name1/name2,
+ * where name1 is used when one of the operands
+ * is a location in memory, name2 otherwise. */
+ OP("&movlps/movhlps %Vq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVLPS, OP_PARM_Vq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movlps %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVLPS, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("unpcklps %Vps,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_UNPCKLPS, OP_PARM_Vps, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("unpckhps %Vps,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_UNPCKHPS, OP_PARM_Vps, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* can also be movlhps when reg->reg */
+ OP("&movhps/movlhps %Vq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVHPS, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movhps %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVHPS, OP_PARM_Vq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("prefetch Grp16", IDX_ParseGrp16, 0, 0, OP_PREFETCH_GRP16, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("nop %Ev", IDX_ParseModRM, 0, 0, OP_NOP, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 2 */
+ OP("mov %Rd,%Cd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV_CR, OP_PARM_Rd, OP_PARM_Cd, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED | DISOPTYPE_MOD_FIXED_11 | DISOPTYPE_FORCED_32_OP_SIZE_X86),
+ OP("mov %Rd,%Dd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV_DR, OP_PARM_Rd, OP_PARM_Dd, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED | DISOPTYPE_MOD_FIXED_11 | DISOPTYPE_FORCED_32_OP_SIZE_X86),
+ OP("mov %Cd,%Rd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV_CR, OP_PARM_Cd, OP_PARM_Rd, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED | DISOPTYPE_MOD_FIXED_11 | DISOPTYPE_FORCED_32_OP_SIZE_X86),
+ OP("mov %Dd,%Rd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV_DR, OP_PARM_Dd, OP_PARM_Rd, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED | DISOPTYPE_MOD_FIXED_11 | DISOPTYPE_FORCED_32_OP_SIZE_X86),
+ /* only valid for Pentium Pro & Pentium II */
+ OP("mov %Rd,%Td", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV_TR, OP_PARM_Rd, OP_PARM_Td, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ INVALID_OPCODE,
+ /* only valid for Pentium Pro & Pentium II */
+ OP("mov %Td,%Rd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV_TR, OP_PARM_Td, OP_PARM_Rd, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ INVALID_OPCODE,
+
+ OP("movaps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVAPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movaps %Wps,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVAPS, OP_PARM_Wps, OP_PARM_Vps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtpi2ps %Vps,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPI2PS,OP_PARM_Vps, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movntps %Wps,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVNTPS, OP_PARM_Wps, OP_PARM_Vps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvttps2pi %Qq,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTTPS2PI,OP_PARM_Qq, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtps2pi %Qq,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPS2PI,OP_PARM_Qq, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ucomiss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_UCOMISS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("comiss %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_COMISS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 3 */
+ OP("wrmsr", 0, 0, 0, OP_WRMSR, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("rdtsc", 0, 0, 0, OP_RDTSC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("rdmsr", 0, 0, 0, OP_RDMSR, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ OP("rdpmc", 0, 0, 0, OP_RDPMC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_PRIVILEGED),
+ OP("sysenter", 0, 0, 0, OP_SYSENTER,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW),
+ OP("sysexit", 0, 0, 0, OP_SYSEXIT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+ INVALID_OPCODE,
+ OP("getsec", 0, 0, 0, OP_GETSEC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("3 byte escape A4", IDX_ParseThreeByteEsc4, 0, 0, OP_3B_ESC4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("3 byte escape A5", IDX_ParseThreeByteEsc5, 0, 0, OP_3B_ESC5, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ /* SSE2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 4 */
+ OP("cmovo %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVO, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovno %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNO, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovc %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVC, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovnc %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNC, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovz %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVZ, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovnz %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNZ, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovbe %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVBE, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovnbe %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNBE, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovs %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVS, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovns %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNS, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovp %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVP, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovnp %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNP, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovl %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovnl %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovle %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVLE, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmovnle %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMOVNLE, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 5 */
+ OP("movmskps %Ed,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVMSKPS,OP_PARM_Ed, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sqrtps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_SQRTPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rsqrtps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_RSQRTPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcpps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_RCPPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("andps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_ANDPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("andnps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_ANDNPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("orps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_ORPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xorps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_XORPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("addps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADDPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mulps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MULPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtps2pd %Vpd,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPS2PD,OP_PARM_Vpd, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtdq2ps %Vps,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTDQ2PS,OP_PARM_Vps, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("subps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUBPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("minps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MINPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("divps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_DIVPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("maxps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_MAXPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 */
+ OP("punpcklbw %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLBW, OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpcklwd %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLWD, OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckldq %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLDQ, OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packsswb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKSSWB,OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpgtb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpgtw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpgtd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packuswb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKUSWB,OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhbw %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHBW, OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhwd %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHWD, OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhdq %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHDQ, OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packssdw %Pq,%Qd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKSSDW,OP_PARM_Pq, OP_PARM_Qd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE, /** @todo 0x0f 0x6c punpcklqdq Vdq,Wdq */
+ INVALID_OPCODE, /** @todo 0x0f 0x6d punpckhqdq Vdq,Wdq */
+ OP("movd %Pd,%Ed", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVD, OP_PARM_Pd, OP_PARM_Ed, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 7 */
+ OP("pshufw %Pq,%Qq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PSHUFW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("Grp12", IDX_ParseGrp12, 0, 0, OP_GRP12, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Grp13", IDX_ParseGrp13, 0, 0, OP_GRP13, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Grp14", IDX_ParseGrp14, 0, 0, OP_GRP14, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpeqb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpeqw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpeqd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("emms", 0, 0, 0, OP_EMMS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("vmread %Ey,%Gy", IDX_ParseModRM, IDX_UseModRM, 0, OP_VMREAD, OP_PARM_Ey, OP_PARM_Gy, OP_PARM_NONE, DISOPTYPE_HARMLESS|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("vmwrite %Gy,%Ey", IDX_ParseModRM, IDX_UseModRM, 0, OP_VMWRITE, OP_PARM_Gy, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("MMX UD 0x7A", 0, 0, 0, OP_MMX_UD7A,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("MMX UD 0x7B", 0, 0, 0, OP_MMX_UD7B,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("MMX UD 0x7C", 0, 0, 0, OP_MMX_UD7C,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS), /** @todo 0x0f 0x7c haddpd/haddps */
+ OP("MMX UD 0x7D", 0, 0, 0, OP_MMX_UD7D,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS), /** @todo 0x0f 0x7d hsubpd/hsubps */
+ OP("movd %Ed,%Pd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVD, OP_PARM_Ed, OP_PARM_Pd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movq %Qq,%Pq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVQ, OP_PARM_Qq, OP_PARM_Pq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 8 */
+ OP("jo %Jv", IDX_ParseImmVRel, 0, 0, OP_JO, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jno %Jv", IDX_ParseImmVRel, 0, 0, OP_JNO, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jc %Jv", IDX_ParseImmVRel, 0, 0, OP_JC, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnc %Jv", IDX_ParseImmVRel, 0, 0, OP_JNC, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("je %Jv", IDX_ParseImmVRel, 0, 0, OP_JE, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jne %Jv", IDX_ParseImmVRel, 0, 0, OP_JNE, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jbe %Jv", IDX_ParseImmVRel, 0, 0, OP_JBE, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnbe %Jv", IDX_ParseImmVRel, 0, 0, OP_JNBE, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("js %Jv", IDX_ParseImmVRel, 0, 0, OP_JS, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jns %Jv", IDX_ParseImmVRel, 0, 0, OP_JNS, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jp %Jv", IDX_ParseImmVRel, 0, 0, OP_JP, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnp %Jv", IDX_ParseImmVRel, 0, 0, OP_JNP, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jl %Jv", IDX_ParseImmVRel, 0, 0, OP_JL, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnl %Jv", IDX_ParseImmVRel, 0, 0, OP_JNL, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jle %Jv", IDX_ParseImmVRel, 0, 0, OP_JLE, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnle %Jv", IDX_ParseImmVRel, 0, 0, OP_JNLE, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW|DISOPTYPE_FORCED_64_OP_SIZE),
+
+ /* 9 */
+ OP("seto %Eb", IDX_ParseModRM, 0, 0, OP_SETO, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setno %Eb", IDX_ParseModRM, 0, 0, OP_SETNO, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setc %Eb", IDX_ParseModRM, 0, 0, OP_SETC, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setnc %Eb", IDX_ParseModRM, 0, 0, OP_SETNC, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sete %Eb", IDX_ParseModRM, 0, 0, OP_SETE, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setne %Eb", IDX_ParseModRM, 0, 0, OP_SETNE, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setbe %Eb", IDX_ParseModRM, 0, 0, OP_SETBE, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setnbe %Eb", IDX_ParseModRM, 0, 0, OP_SETNBE, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sets %Eb", IDX_ParseModRM, 0, 0, OP_SETS, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setns %Eb", IDX_ParseModRM, 0, 0, OP_SETNS, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setp %Eb", IDX_ParseModRM, 0, 0, OP_SETP, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setnp %Eb", IDX_ParseModRM, 0, 0, OP_SETNP, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setl %Eb", IDX_ParseModRM, 0, 0, OP_SETL, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setnl %Eb", IDX_ParseModRM, 0, 0, OP_SETNL, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setle %Eb", IDX_ParseModRM, 0, 0, OP_SETLE, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("setnle %Eb", IDX_ParseModRM, 0, 0, OP_SETNLE, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* a */
+ OP("push fs", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_FS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("pop fs", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_FS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("cpuid", 0, 0, 0, OP_CPUID, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("bt %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_BT, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shld %Ev,%Gv,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_SHLD, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("shld %Ev,%Gv,CL", IDX_ParseModRM, IDX_UseModRM, 0, OP_SHLD, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("push gs", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_GS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("pop gs", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_GS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("rsm", 0, 0, 0, OP_RSM, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("bts %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_BTS, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shrd %Ev,%Gv,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_SHRD, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("shrd %Ev,%Gv,CL", IDX_ParseModRM, IDX_UseModRM, IDX_ParseFixedReg,OP_SHRD, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_REG_CL, DISOPTYPE_HARMLESS),
+ OP("Grp15", IDX_ParseGrp15, 0, 0, OP_GRP15, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("imul %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_IMUL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* b */
+ OP("cmpxchg %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMPXCHG, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmpxchg %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMPXCHG, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lss %Gv,%Mp", IDX_ParseModRM, IDX_UseModRM, 0, OP_LSS, OP_PARM_Gv, OP_PARM_Mp, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_RRM_DANGEROUS),
+ OP("btr %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_BTR, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lfs %Gv,%Mp", IDX_ParseModRM, IDX_UseModRM, 0, OP_LFS, OP_PARM_Gv, OP_PARM_Mp, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lgs %Gv,%Mp", IDX_ParseModRM, IDX_UseModRM, 0, OP_LGS, OP_PARM_Gv, OP_PARM_Mp, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movzx %Gv,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVZX, OP_PARM_Gv, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movzx %Gv,%Ew", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVZX, OP_PARM_Gv, OP_PARM_Ew, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE, /** @todo 0x0f 0xb8 popcnt Gv,Ev / jmpe */
+ OP("Grp10 Invalid Op", IDX_ParseGrp10, 0, 0, OP_GRP10_INV,OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Grp8", IDX_ParseGrp8, 0, 0, OP_GRP8, OP_PARM_Ev, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("btc %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_BTC, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("bsf %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_BSF, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("bsr %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_BSR, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsx %Gv,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSX, OP_PARM_Gv, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsx %Gv,%Ew", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSX, OP_PARM_Gv, OP_PARM_Ew, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* c */
+ OP("xadd %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XADD, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xadd %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_XADD, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmpps %Vps,%Wps,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_CMPPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ /* SSE2 */
+ OP("movnti %Ed,%Gd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVNTI, OP_PARM_Ed, OP_PARM_Gd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pinsrw %Pq,%Ed,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PINSRW, OP_PARM_Pq, OP_PARM_Ed, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pextrw %Gd,%Pq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PEXTRW, OP_PARM_Gd, OP_PARM_Pq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("shufps %Vps,%Wps,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_SHUFPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("Grp9", IDX_ParseGrp9, 0, 0, OP_GRP9, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("bswap EAX", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap ECX", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap EDX", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap EBX", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap ESP", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap EBP", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap ESI", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("bswap EDI", IDX_ParseFixedReg, 0, 0, OP_BSWAP, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+
+ /* d */
+ INVALID_OPCODE, /** @todo 0x0f 0xd0 addsubpd/addsubps */
+ OP("psrlw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrld %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrlq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmullw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULLW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("pmovmskb %Gd,%Pq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVMSKB,OP_PARM_Gd, OP_PARM_Pq, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("psubusb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBUSB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubusw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBUSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminub %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINUB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pand %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAND, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddusb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDUSB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddusw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDUSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxub %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXUB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pandn %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PANDN, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* e */
+ OP("pavgb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAVGB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psraw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRAW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrad %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRAD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pavgw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAVGW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhuw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULHUW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULHW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("movntq %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVNTQ, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubsb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBSB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("por %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_POR, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddsb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDSB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pxor %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PXOR, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ INVALID_OPCODE,
+ OP("psllw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSLLW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pslld %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSLLD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psllq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSSQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmuludq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULUDQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaddwd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMADDWD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psadbw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSADBW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("maskmovq %Ppi,%Qpi", IDX_ParseModRM, IDX_UseModRM, 0, OP_MASKMOVQ,OP_PARM_Ppi, OP_PARM_Qpi, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+};
+
+/** Two byte opcode map with prefix 0x66 */
+const DISOPCODE g_aTwoByteMapX86_PF66[256] =
+{
+ /* 0 */
+ INVALID_OPCODE_BLOCK
+
+ /* 1 */
+ OP("movupd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVUPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movupd %Wpd,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVUPD, OP_PARM_Wpd, OP_PARM_Vpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movlpd %Vq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVLPD, OP_PARM_Vq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movlpd %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVLPD, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("unpcklpd %Vpd,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_UNPCKLPD,OP_PARM_Vpd, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("unpckhpd %Vpd,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_UNPCKHPD,OP_PARM_Vpd, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movhpd %Vq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVHPD, OP_PARM_Vq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movhpd %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVHPD, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movapd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVAPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movapd %Wpd,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVAPD, OP_PARM_Wpd, OP_PARM_Vpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtpi2pd %Vpd,%Qdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPI2PD,OP_PARM_Vpd, OP_PARM_Qdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movntpd %Wpd,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVNTPD, OP_PARM_Wpd, OP_PARM_Vpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvttpd2pi %Qdq,%Wpd",IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTTPD2PI,OP_PARM_Qdq, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtpd2pi %Qdq,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPD2PI,OP_PARM_Qdq, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ucomisd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_UCOMISD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("comisd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_COMISD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 3 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("3 byte escape A4", IDX_ParseThreeByteEsc4, 0, 0, OP_3B_ESC4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("3 byte escape A5", IDX_ParseThreeByteEsc5, 0, 0, OP_3B_ESC5, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ OP("movmskpd %Ed,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVMSKPD,OP_PARM_Ed, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sqrtpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_SQRTPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("andpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_ANDPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("andnpd %Vps,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_ANDNPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("orpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_ORPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xorpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_XORPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("addpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADDPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mulpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MULPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtpd2ps %Vps,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPD2PS,OP_PARM_Vps, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtps2dq %Vdq,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPS2DQ,OP_PARM_Vdq, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("subpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUBPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("minpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MINPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("divpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_DIVPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("maxpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MAXPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 */
+ OP("punpcklbw %Vdq,%Wdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLBW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpcklwd %Vdq,%Wdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLWD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckldq %Vdq,%Wdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLDQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packsswb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKSSWB,OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpgtb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpgtw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpgtd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packuswb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKUSWB,OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhbw %Pdq,%Qdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHBW, OP_PARM_Pdq, OP_PARM_Qdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhwd %Pdq,%Qdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHWD, OP_PARM_Pdq, OP_PARM_Qdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhdq %Pdq,%Qdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHDQ, OP_PARM_Pdq, OP_PARM_Qdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packssdw %Pdq,%Qdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKSSDW,OP_PARM_Pdq, OP_PARM_Qdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpcklqdq %Vdq,%Wdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKLQDQ,OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("punpckhqdq %Vdq,%Wdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_PUNPCKHQDQ,OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movd %Vdq,%Ed", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVD, OP_PARM_Vdq, OP_PARM_Ed, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movdqa %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVDQA, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 7 */
+ OP("pshufd %Vdq,%Wdq,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PSHUFD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("pcmpeqb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQB, OP_PARM_Vdq, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpeqw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQW, OP_PARM_Vdq, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpeqd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQD, OP_PARM_Vdq, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movd %Ed,%Vdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVD, OP_PARM_Ed, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movdqa %Qq,%Pq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVDQA, OP_PARM_Wdq, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 8 */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cmppd %Vpd,%Wpd,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_CMPPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("pinsrw %Vdq,%Ed,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PINSRW, OP_PARM_Vdq, OP_PARM_Ed, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pextrw %Gd,%Vdq,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PEXTRW, OP_PARM_Gd, OP_PARM_Vdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("shufpd %Vpd,%Wpd,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_SHUFPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ INVALID_OPCODE,
+ OP("psrlw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrld %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrlq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmullw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movq %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVQ, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovmskb %Gd,%Ux", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVMSKB,OP_PARM_Gd, OP_PARM_Ux, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("psubusb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBUSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubusw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBUSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminub %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINUB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pand %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAND, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddusb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDUSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddusw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDUSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxub %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXUB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pandn %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PANDN, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* e */
+ OP("pavgb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAVGB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psraw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRAW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrad %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRAD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pavgw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAVGW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhuw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULHUW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULHW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvttpd2dq %Vdq,%Wpd",IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTTPD2DQ,OP_PARM_Vdq, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movntdq %Wdq,%Vdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVNTDQ, OP_PARM_Wdq, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubsb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("por %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_POR, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddsb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pxor %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PXOR, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ INVALID_OPCODE,
+ OP("psllw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSLLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pslld %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSLLD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psllq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSSQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmuludq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULUDQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaddwd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMADDWD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psadbw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSADBW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("maskmovdqu %Vdq,%Wdq",IDX_ParseModRM, IDX_UseModRM, 0, OP_MASKMOVDQU, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psubq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSUBD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("paddd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PADDD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+};
+
+/* Two byte opcode map with prefix 0xF2 */
+const DISOPCODE g_aTwoByteMapX86_PFF2[256] =
+{
+ /* 0 */
+ INVALID_OPCODE_BLOCK
+
+ /* 1 */
+ OP("movsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsd %Wsd,%Vsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSD, OP_PARM_Wpd, OP_PARM_Vpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movddup %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVDDUP, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cvtsi2sd %Vsd,%Ed", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTSI2SD,OP_PARM_Vsd, OP_PARM_Ed, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("cvttsd2si %Gd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTTSD2SI,OP_PARM_Gd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtsd2si %Gd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTSD2SI,OP_PARM_Gd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 3 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("3 byte escape A4", IDX_ParseThreeByteEsc4, 0, 0, OP_3B_ESC4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ INVALID_OPCODE,
+ OP("sqrtsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_SQRTSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("addsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADDSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mulsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MULSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtsd2ss %Vss,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTSD2SS,OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("subsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUBSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("minsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MINSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("divsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_DIVSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("maxsd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, OP_MAXSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 */
+ INVALID_OPCODE_BLOCK
+
+ /* 7 */
+ OP("pshuflw %Vdq,%Wdq,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PSHUFLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 8 */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cmpsd %Vsd,%Wsd,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_CMPSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movdq2q %Pq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVDQ2Q, OP_PARM_Pq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* e */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cvtpd2dq %Vdq,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTPD2DQ,OP_PARM_Vdq, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* f */
+ OP("lddqu %Vdq,%Mdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_LDDQU, OP_PARM_Vdq, OP_PARM_Mdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE
+};
+
+
+/* Two byte opcode map with prefix 0xF3 */
+const DISOPCODE g_aTwoByteMapX86_PFF3[256] =
+{
+ /* 0 */
+ INVALID_OPCODE_BLOCK
+
+ /* 1 */
+ OP("movss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movss %Wss,%Vss", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSS, OP_PARM_Wss, OP_PARM_Vss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsldup %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSLDUP,OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movshdup %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSHDUP,OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cvtsi2ss %Vss,%Ed", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTSI2SS,OP_PARM_Vss, OP_PARM_Ed, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("cvttss2si %Gd,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTTSS2SI,OP_PARM_Gd, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvtss2si %Gd,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTSS2SI,OP_PARM_Gd, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 3 */
+ INVALID_OPCODE_BLOCK
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ INVALID_OPCODE,
+ OP("sqrtss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_SQRTSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rsqrtss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_RSQRTSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcpss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_RCPSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("addss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADDSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mulss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_MULSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ //??
+ OP("cvtss2sd %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTSD2SS,OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cvttps2dq %Vdq,%Wps",IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTTPS2DQ,OP_PARM_Vdq, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("subss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUBSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("minss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_MINSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("divss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_DIVSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("maxss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, OP_MAXSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movdqu %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVDQU, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 7 */
+ OP("pshufhw %Vdq,%Wdq,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_PSHUFHW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movq %Vq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVQ, OP_PARM_Vq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movdqu %Wdq,%Vdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVDQU, OP_PARM_Wdq, OP_PARM_Vdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 8 */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("popcnt %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_POPCNT, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("tzcnt %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_TZCNT, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lzcnt %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_LZCNT, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* c */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cmpss %Vss,%Wss,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte,OP_CMPSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movq2dq %Vdq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVQ2DQ, OP_PARM_Vdq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* e */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("cvtdq2pd %Vpd,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_CVTDQ2PD,OP_PARM_Vpd, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* f */
+ INVALID_OPCODE_BLOCK
+};
+
+/** Three byte opcode map (0xF 0x38 0x0x) */
+const DISOPCODE g_aThreeByteMapX86_0F38_0[16] =
+{
+ /* 0 */
+ OP("pshufb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSHUFB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phaddw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHADDW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phaddd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHADDD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phaddsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHADDSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaddubsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMADDUBSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phsubw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHSUBW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phsubd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHSUBD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phsubsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHSUBSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psignb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSIGNB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psignw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSIGNW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psignd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSIGND, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhrsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULHRSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x0F 0x38 0x1x) */
+const DISOPCODE g_aThreeByteMapX86_0F38_1[16] =
+{
+ /* 1 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("pabsb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PABSB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pabsw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PABSW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pabsd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PABSD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x0F 0x38 0xFx) */
+const DISOPCODE g_aThreeByteMapX86_0F38_F[16] =
+{
+ /* F */
+ OP("movbe %Gy,%My", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVBEGM, OP_PARM_Gy, OP_PARM_My, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movbe %My,%Gy", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVBEMG, OP_PARM_My, OP_PARM_Gy, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** These tables are mostly sparse, so use another level of indirection to save space. */
+PCDISOPCODE const g_apThreeByteMapX86_0F38[16] =
+{
+ /* 0 */
+ &g_aThreeByteMapX86_0F38_0[0],
+ /* 1 */
+ &g_aThreeByteMapX86_0F38_1[0],
+ /* 2 */
+ NULL,
+ /* 3 */
+ NULL,
+ /* 4 */
+ NULL,
+ /* 5 */
+ NULL,
+ /* 6 */
+ NULL,
+ /* 7 */
+ NULL,
+ /* 8 */
+ NULL,
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ NULL,
+ /* e */
+ NULL,
+ /* f */
+ &g_aThreeByteMapX86_0F38_F[0],
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0x0x) */
+const DISOPCODE g_aThreeByteMapX86_660F38_0[16] =
+{
+ /* 0 */
+ OP("pshufb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSHUFB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phaddw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHADDW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phaddd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHADDD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phaddsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHADDSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaddubsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMADDUBSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phsubw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHSUBW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phsubd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHSUBD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phsubsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHSUBSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psignb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSIGNB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psignw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSIGNW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psignd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSIGND, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhrsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULHRSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0x1x) */
+const DISOPCODE g_aThreeByteMapX86_660F38_1[16] =
+{
+ /* 1 */
+ OP("pblendvb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PBLENDVB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("blendvps %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_BLENDVPS, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("blendvpd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_BLENDVPD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("ptest %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PTEST, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("pabsb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PABSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pabsw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PABSW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pabsd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PABSD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0x2x) */
+const DISOPCODE g_aThreeByteMapX86_660F38_2[16] =
+{
+ /* 2 */
+ OP("pmovsxbw %Vdq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVSXBW, OP_PARM_Vdq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovsxbd %Vdq,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVSXBD, OP_PARM_Vdq, OP_PARM_Wd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovsxbq %Vdq,%Ww", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVSXBQ, OP_PARM_Vdq, OP_PARM_Ww, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovsxwd %Vdq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVSXBW, OP_PARM_Vdq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovsxwq %Vdq,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVSXWQ, OP_PARM_Vdq, OP_PARM_Wd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovsxdq %Vdq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVSXDQ, OP_PARM_Vdq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("pmuldq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULDQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pcmpeqq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPEQQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movntdqa %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVNTDQA, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("packusdw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PACKUSDW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0x3x) */
+const DISOPCODE g_aThreeByteMapX86_660F38_3[16] =
+{
+ /* 3 */
+ OP("pmovzxbw %Vdq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVZXBW, OP_PARM_Vdq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovzxbd %Vdq,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVZXBD, OP_PARM_Vdq, OP_PARM_Wd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovzxbq %Vdq,%Ww", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVZXBQ, OP_PARM_Vdq, OP_PARM_Ww, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovzxwd %Vdq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVZXWD, OP_PARM_Vdq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovzxwq %Vdq,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVZXWQ, OP_PARM_Vdq, OP_PARM_Wd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmovzxdq %Vdq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMOVZXDQ, OP_PARM_Vdq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("pcmpgtq %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PCMPGTQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminsb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminsd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminuw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINUW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pminud %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMINUD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxsb %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXSB, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxsd %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXSD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxuw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXUW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmaxud %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMAXUD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0x4x) */
+const DISOPCODE g_aThreeByteMapX86_660F38_4[16] =
+{
+ /* 4 */
+ OP("pmulld %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PMULLD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("phminposuw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PHMINPOSUW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0x8x) */
+const DISOPCODE g_aThreeByteMapX86_660F38_8[16] =
+{
+ /* 8 */
+ OP("invept %Gy,%Mdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_INVEPT, OP_PARM_Gy, OP_PARM_Mdq, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("invvpid %Gy,%Mdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_INVVPID, OP_PARM_Gy, OP_PARM_Mdq, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("invpcid %Gy,%Mdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_INVPCID, OP_PARM_Gy, OP_PARM_Mdq, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_FORCED_64_OP_SIZE),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map (0x66 0x0F 0x38 0xDx) */
+const DISOPCODE g_aThreeByteMapX86_660F38_D[16] =
+{
+ /* D */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("aesimc %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_AESIMC, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aesenc %Vdq,%Hdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_AESENC, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aesenclast %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_AESENCLAST, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aesdec %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_AESDEC, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("aesdeclast %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_AESDECLAST, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F38_F[16] =
+{
+ /* F */
+ OP("movbe %Gw,%Mw", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVBEGM, OP_PARM_Gw, OP_PARM_Mw, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movbe %Mw,%Gw", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVBEMG, OP_PARM_Mw, OP_PARM_Gw, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("adcx %Gy,%Ey", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADCX, OP_PARM_Gy, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map with prefix 0x66 (0xF 0x38) */
+PCDISOPCODE const g_apThreeByteMapX86_660F38[16] =
+{
+ /* 0 */
+ &g_aThreeByteMapX86_660F38_0[0],
+ /* 1 */
+ &g_aThreeByteMapX86_660F38_1[0],
+ /* 2 */
+ &g_aThreeByteMapX86_660F38_2[0],
+ /* 3 */
+ &g_aThreeByteMapX86_660F38_3[0],
+ /* 4 */
+ &g_aThreeByteMapX86_660F38_4[0],
+ /* 5 */
+ NULL,
+ /* 6 */
+ NULL,
+ /* 7 */
+ NULL,
+ /* 8 */
+ &g_aThreeByteMapX86_660F38_8[0],
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ &g_aThreeByteMapX86_660F38_D[0],
+ /* e */
+ NULL,
+ /* f */
+ &g_aThreeByteMapX86_660F38_F[0],
+};
+
+const DISOPCODE g_aThreeByteMapX86_F20F38_F[16] =
+{
+ /* According to Intel opcodes map in Intel® 64 and IA-32 Architectures Software Developer’s Manual dated September 2014
+ it should be %Gd (always dword regardless of operand-size attribute), but from the description of the command
+ it is clear that REX.W prefix can change this size to 64 bit, therefore it is set to %Gy. Seems to be a mistake. */
+ /** @todo r=bird: While the destination can be a 64-bit register, it is
+ * always treated like a dword register given that the upper half is
+ * always cleared. So, it is really just a convenience for a more
+ * natural syntax when using a 64-bit source register. */
+ OP("crc32 %Gy,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CRC32, OP_PARM_Gy, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("crc32 %Gy,%Ey", IDX_ParseModRM, IDX_UseModRM, 0, OP_CRC32, OP_PARM_Gy, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+const DISOPCODE g_aThreeByteMapX86_66F20F38_F[16] =
+{
+ /* According to Intel opcodes map in Intel® 64 and IA-32 Architectures Software Developer’s Manual dated September 2014
+ it should be %Gd (always dword regardless of operand-size attribute), but from the description of the command
+ it is clear that REX.W prefix can change this size to 64 bit, therefore it is set to %Gy. Seems to be a mistake. */
+ OP("crc32 %Gy,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CRC32, OP_PARM_Gy, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("crc32 %Gy,%Ew", IDX_ParseModRM, IDX_UseModRM, 0, OP_CRC32, OP_PARM_Gy, OP_PARM_Ew, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map with prefix 0xF2 (0xF 0x38) */
+/** @todo remainder missing (too lazy now) */
+PCDISOPCODE const g_apThreeByteMapX86_F20F38[16] =
+{
+ /* 0 */
+ NULL,
+ /* 1 */
+ NULL,
+ /* 2 */
+ NULL,
+ /* 3 */
+ NULL,
+ /* 4 */
+ NULL,
+ /* 5 */
+ NULL,
+ /* 6 */
+ NULL,
+ /* 7 */
+ NULL,
+ /* 8 */
+ NULL,
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ NULL,
+ /* e */
+ NULL,
+ /* f */
+ &g_aThreeByteMapX86_F20F38_F[0],
+};
+
+/** Three byte opcode map with prefixes 0x66 0xF2 (0xF 0x38) */
+PCDISOPCODE const g_apThreeByteMapX86_66F20F38[16] =
+{
+ /* 0 */
+ NULL,
+ /* 1 */
+ NULL,
+ /* 2 */
+ NULL,
+ /* 3 */
+ NULL,
+ /* 4 */
+ NULL,
+ /* 5 */
+ NULL,
+ /* 6 */
+ NULL,
+ /* 7 */
+ NULL,
+ /* 8 */
+ NULL,
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ NULL,
+ /* e */
+ NULL,
+ /* f */
+ &g_aThreeByteMapX86_66F20F38_F[0],
+};
+
+const DISOPCODE g_aThreeByteMapX86_F30F38_F[16] =
+{
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("adox %Gy,%Ey", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADOX, OP_PARM_Gy, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+/** Three byte opcode map with prefix 0xF3 (0xF 0x38) */
+PCDISOPCODE const g_apThreeByteMapX86_F30F38[16] =
+{
+ /* 0 */
+ NULL,
+ /* 1 */
+ NULL,
+ /* 2 */
+ NULL,
+ /* 3 */
+ NULL,
+ /* 4 */
+ NULL,
+ /* 5 */
+ NULL,
+ /* 6 */
+ NULL,
+ /* 7 */
+ NULL,
+ /* 8 */
+ NULL,
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ NULL,
+ /* e */
+ NULL,
+ /* f */
+ &g_aThreeByteMapX86_F30F38_F[0],
+};
+
+const DISOPCODE g_aThreeByteMapX86_0F3A_0[16] =
+{
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("palignr %Pq,%Qq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PALIGNR, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+};
+
+PCDISOPCODE const g_apThreeByteMapX86_0F3A[16] =
+{
+ /* 0 */
+ g_aThreeByteMapX86_0F3A_0,
+ /* 1 */
+ NULL,
+ /* 2 */
+ NULL,
+ /* 3 */
+ NULL,
+ /* 4 */
+ NULL,
+ /* 5 */
+ NULL,
+ /* 6 */
+ NULL,
+ /* 7 */
+ NULL,
+ /* 8 */
+ NULL,
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ NULL,
+ /* e */
+ NULL,
+ /* f */
+ NULL,
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F3A_0[16] =
+{
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("roundps %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_ROUNDPS, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("roundpd %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_ROUNDPD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("roundss %Vss,%Wss,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_ROUNDSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("roundsd %Vsd,%Wsd,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_ROUNDSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("blendps %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_BLENDPS, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("blendpd %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_BLENDPD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pblendw %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PBLENDW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("palignr %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PALIGNR, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F3A_10[16] =
+{
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("pextrb %Eb,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PEXTRB, OP_PARM_Eb, OP_PARM_Vdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pextrw %Ew,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PEXTRW, OP_PARM_Ew, OP_PARM_Vdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pextrd %Ed,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PEXTRD, OP_PARM_Ed, OP_PARM_Vdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("extractps %Ed,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_EXTRACTPS, OP_PARM_Ed, OP_PARM_Vdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F3A_20[16] =
+{
+ // pinsrb %Vdq,%Ry/Mb,%Ib
+ OP("pinsrb %Vdq,%Ey,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PINSRB, OP_PARM_Vdq, OP_PARM_Ey, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ // insertps %Vdq,%Udq/Md,%Ib
+ OP("insertps %Vdq,%Wdq,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_INSERTPS, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pinsrd %Vdq,%Ey,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PINSRD, OP_PARM_Vdq, OP_PARM_Ey, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F3A_40[16] =
+{
+ OP("dpps %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_DPPS, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("dppd %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_DPPD, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("mpsadbw %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_MPSADBW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("pclmulqdq %Vdq,%Wdq,%Ib",IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PCLMULQDQ, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F3A_60[16] =
+{
+ OP("pcmpestrm %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PCMPESTRM, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pcmpestri %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PCMPESTRI, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pcmpistrm %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PCMPISTRM, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("pcmpistri %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_PCMPISTRI, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+const DISOPCODE g_aThreeByteMapX86_660F3A_D0[16] =
+{
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("aeskeygen %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, OP_AESKEYGEN, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+};
+
+/** Three byte opcode map with prefix 0x66 (0xF 0x3A) */
+/** @todo remainder missing (too lazy now) */
+PCDISOPCODE const g_apThreeByteMapX86_660F3A[16] =
+{
+ /* 0 */
+ g_aThreeByteMapX86_660F3A_0,
+ /* 1 */
+ g_aThreeByteMapX86_660F3A_10,
+ /* 2 */
+ g_aThreeByteMapX86_660F3A_20,
+ /* 3 */
+ NULL,
+ /* 4 */
+ g_aThreeByteMapX86_660F3A_40,
+ /* 5 */
+ NULL,
+ /* 6 */
+ g_aThreeByteMapX86_660F3A_60,
+ /* 7 */
+ NULL,
+ /* 8 */
+ NULL,
+ /* 9 */
+ NULL,
+ /* a */
+ NULL,
+ /* b */
+ NULL,
+ /* c */
+ NULL,
+ /* d */
+ g_aThreeByteMapX86_660F3A_D0,
+ /* e */
+ NULL,
+ /* f */
+ NULL,
+};
+
+/* 3DNow! map (0x0F 0x0F prefix) */
+const DISOPCODE g_aTwoByteMapX86_3DNow[256] =
+{
+ /* 0 */
+ INVALID_OPCODE_MOD_RM(0x00),
+ INVALID_OPCODE_MOD_RM(0x01),
+ INVALID_OPCODE_MOD_RM(0x02),
+ INVALID_OPCODE_MOD_RM(0x03),
+ INVALID_OPCODE_MOD_RM(0x04),
+ INVALID_OPCODE_MOD_RM(0x05),
+ INVALID_OPCODE_MOD_RM(0x06),
+ INVALID_OPCODE_MOD_RM(0x07),
+ INVALID_OPCODE_MOD_RM(0x08),
+ INVALID_OPCODE_MOD_RM(0x09),
+ INVALID_OPCODE_MOD_RM(0x0a),
+ INVALID_OPCODE_MOD_RM(0x0c),
+ OP("pi2fw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PI2FW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pi2fd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PI2FD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x0e),
+ INVALID_OPCODE_MOD_RM(0x0f),
+
+ /* 1 */
+ INVALID_OPCODE_MOD_RM(0x10),
+ INVALID_OPCODE_MOD_RM(0x11),
+ INVALID_OPCODE_MOD_RM(0x12),
+ INVALID_OPCODE_MOD_RM(0x13),
+ INVALID_OPCODE_MOD_RM(0x14),
+ INVALID_OPCODE_MOD_RM(0x15),
+ INVALID_OPCODE_MOD_RM(0x16),
+ INVALID_OPCODE_MOD_RM(0x17),
+ INVALID_OPCODE_MOD_RM(0x18),
+ INVALID_OPCODE_MOD_RM(0x19),
+ INVALID_OPCODE_MOD_RM(0x1a),
+ INVALID_OPCODE_MOD_RM(0x1b),
+ OP("pf2iw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PF2IW, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pf2id %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PF2ID, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x1e),
+ INVALID_OPCODE_MOD_RM(0x1f),
+
+ /* 2 */
+ INVALID_OPCODE_BLOCK_MOD_RM(0x2)
+
+ /* 3 */
+ INVALID_OPCODE_BLOCK_MOD_RM(0x3)
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK_MOD_RM(0x4)
+
+ /* 5 */
+ INVALID_OPCODE_BLOCK_MOD_RM(0x5)
+
+ /* 6 */
+ INVALID_OPCODE_BLOCK_MOD_RM(0x6)
+
+ /* 7 */
+ INVALID_OPCODE_BLOCK_MOD_RM(0x7)
+
+ /* 8 */
+ INVALID_OPCODE_MOD_RM(0x80),
+ INVALID_OPCODE_MOD_RM(0x81),
+ INVALID_OPCODE_MOD_RM(0x82),
+ INVALID_OPCODE_MOD_RM(0x83),
+ INVALID_OPCODE_MOD_RM(0x84),
+ INVALID_OPCODE_MOD_RM(0x85),
+ INVALID_OPCODE_MOD_RM(0x86),
+ INVALID_OPCODE_MOD_RM(0x87),
+ INVALID_OPCODE_MOD_RM(0x88),
+ INVALID_OPCODE_MOD_RM(0x89),
+ OP("pfnacc %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFNACC, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x8b),
+ INVALID_OPCODE_MOD_RM(0x8c),
+ INVALID_OPCODE_MOD_RM(0x8d),
+ OP("pfpnacc %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFPNACC, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x8f),
+
+ /* 9 */
+ OP("pfcmpge %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFCMPGE, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x91),
+ INVALID_OPCODE_MOD_RM(0x92),
+ INVALID_OPCODE_MOD_RM(0x93),
+ OP("pfmin %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFMIN, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x95),
+ OP("pfrcp %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFRCP, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pfrsqrt %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFRSQRT, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x98),
+ INVALID_OPCODE_MOD_RM(0x99),
+ OP("pfsub %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFSUB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x9b),
+ INVALID_OPCODE_MOD_RM(0x9c),
+ INVALID_OPCODE_MOD_RM(0x9d),
+ OP("pfadd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFADD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x9f),
+
+ /* a */
+ OP("pfcmpgt %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFCMPGT, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xa1),
+ INVALID_OPCODE_MOD_RM(0xa2),
+ INVALID_OPCODE_MOD_RM(0xa3),
+ OP("pfmax %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFMAX, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xa5),
+ OP("pfrcpit1 %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFRCPIT1,OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pfrsqit1 %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFRSQRTIT1, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xa8),
+ INVALID_OPCODE_MOD_RM(0xa9),
+ OP("pfsubr %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFSUBR, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xab),
+ INVALID_OPCODE_MOD_RM(0xac),
+ INVALID_OPCODE_MOD_RM(0xad),
+ OP("pfacc %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFACC, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xaf),
+
+ /* b */
+ OP("pfcmpeq %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFCMPEQ, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xb1),
+ INVALID_OPCODE_MOD_RM(0xb2),
+ INVALID_OPCODE_MOD_RM(0xb3),
+ OP("pfmul %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFMUL, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xb5),
+ OP("pfrcpit2 %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFRCPIT2,OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pmulhrw %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFMULHRW,OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xb8),
+ INVALID_OPCODE_MOD_RM(0xb9),
+ INVALID_OPCODE_MOD_RM(0xba),
+ OP("pswapd %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PFSWAPD, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xbc),
+ INVALID_OPCODE_MOD_RM(0xbd),
+ INVALID_OPCODE_MOD_RM(0xbe),
+ OP("pavgusb %Pq,%Qq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PAVGUSB, OP_PARM_Pq, OP_PARM_Qq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* c */
+ INVALID_OPCODE_BLOCK_MOD_RM(0xc)
+
+ /* d */
+ INVALID_OPCODE_BLOCK_MOD_RM(0xd)
+
+ /* e */
+ INVALID_OPCODE_BLOCK_MOD_RM(0xe)
+
+ /* f */
+ INVALID_OPCODE_BLOCK_MOD_RM(0xf)
+};
+
+
+
+/* Floating point opcode starting with escape byte 0xD8 (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF0_Low[8] =
+{
+ /* 0 */
+ OP("fadd %Md", IDX_ParseModRM, 0, 0, OP_FADD, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul %Md", IDX_ParseModRM, 0, 0, OP_FMUL, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom %Md", IDX_ParseModRM, 0, 0, OP_FCOM, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp %Md", IDX_ParseModRM, 0, 0, OP_FCOMP, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub %Md", IDX_ParseModRM, 0, 0, OP_FSUB, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr %Md", IDX_ParseModRM, 0, 0, OP_FSUBR, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv %Md", IDX_ParseModRM, 0, 0, OP_FDIV, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr %Md", IDX_ParseModRM, 0, 0, OP_FDIVR, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+/* Floating point opcode starting with escape byte 0xD8 (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF0_High[16*4] =
+{
+ /* c */
+ OP("fadd ST(0),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(1)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(2)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(3)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(4)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(5)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(6)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(0),ST(7)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(1)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(2)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(3)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(4)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(5)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(6)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(7)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* d */
+ OP("fcom ST(0),ST(0)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(1)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(2)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(3)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(4)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(5)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(6)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom ST(0),ST(7)", 0, 0, 0, OP_FCOM, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(0)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(1)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(2)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(3)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(4)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(5)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(6)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp ST(0),ST(7)", 0, 0, 0, OP_FCOMP, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* e */
+ OP("fsub ST(0),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(1)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(2)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(3)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(4)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(5)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(6)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(7)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(1)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(2)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(3)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(4)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(5)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(6)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(0),ST(7)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ OP("fdiv ST(0),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(1)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(2)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(3)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(4)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(5)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(6)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(7)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(1)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(2)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(3)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(4)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(5)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(6)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(0),ST(7)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+/* Floating point opcode starting with escape byte 0xD9 (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF1_Low[8] =
+{
+ /* 0 */
+ OP("fld %Md", IDX_ParseModRM, 0, 0, OP_FLD, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("fst %Md", IDX_ParseModRM, 0, 0, OP_FST, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp %Md", IDX_ParseModRM, 0, 0, OP_FSTP, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /// @todo ??
+ OP("fldenv %M", IDX_ParseModRM, 0, 0, OP_FLDENV, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldcw %Ew", IDX_ParseModRM, 0, 0, OP_FSUBR, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /// @todo ??
+ OP("fstenv %M", IDX_ParseModRM, 0, 0, OP_FSTENV, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstcw %Ew", IDX_ParseModRM, 0, 0, OP_FSTCW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xD9 (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF1_High[16*4] =
+{
+ /* c */
+ OP("fld ST(0),ST(0)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(1)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(2)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(3)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(4)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(5)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(6)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fld ST(0),ST(7)", 0, 0, 0, OP_FLD, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(0)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(1)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(2)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(3)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(4)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(5)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(6)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxch ST(0),ST(7)", 0, 0, 0, OP_FXCH, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* d */
+ OP("fnop", 0, 0, 0, OP_FNOP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+
+ /* e */
+ OP("fchs", 0, 0, 0, OP_FCHS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fabs", 0, 0, 0, OP_FABS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("ftst", 0, 0, 0, OP_FCHS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxam", 0, 0, 0, OP_FCHS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("fld1", 0, 0, 0, OP_FLD1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldl2t", 0, 0, 0, OP_FLDL2T, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldl2e", 0, 0, 0, OP_FLDL2E, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldpi", 0, 0, 0, OP_FLDPI, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldlg2", 0, 0, 0, OP_FLDLG2, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldln2", 0, 0, 0, OP_FLDLN2, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fldz", 0, 0, 0, OP_FLDZ, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+
+ /* f */
+ OP("f2xm1", 0, 0, 0, OP_F2XM1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fyl2x", 0, 0, 0, OP_FYL2X, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fptan", 0, 0, 0, OP_FPTAN, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fpatan", 0, 0, 0, OP_FPATAN, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxtract", 0, 0, 0, OP_FXTRACT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("frem1", 0, 0, 0, OP_FREM1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdecstp", 0, 0, 0, OP_FDECSTP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fincstp", 0, 0, 0, OP_FINCSTP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fprem", 0, 0, 0, OP_FPREM, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fyl2xp1", 0, 0, 0, OP_FYL2XP1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsqrt", 0, 0, 0, OP_FSQRT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsincos", 0, 0, 0, OP_FSINCOS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("frndint", 0, 0, 0, OP_FRNDINT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fscale", 0, 0, 0, OP_FSCALE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsin", 0, 0, 0, OP_FSIN, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcos", 0, 0, 0, OP_FCOS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDA (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF2_Low[8] =
+{
+ /* 0 */
+ OP("fiadd %Md", IDX_ParseModRM, 0, 0, OP_FIADD, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fimul %Md", IDX_ParseModRM, 0, 0, OP_FIMUL, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ficom %Md", IDX_ParseModRM, 0, 0, OP_FICOM, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ficomp %Md", IDX_ParseModRM, 0, 0, OP_FICOMP, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fisub %Md", IDX_ParseModRM, 0, 0, OP_FISUB, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fisubr %Md", IDX_ParseModRM, 0, 0, OP_FISUBR, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fidiv %Md", IDX_ParseModRM, 0, 0, OP_FIDIV, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fidivr %Md", IDX_ParseModRM, 0, 0, OP_FIDIVR, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xD9 (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF2_High[16*4] =
+{
+ /* c */
+ OP("fcmovb ST(0),ST(0)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(1)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(2)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(3)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(4)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(5)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(6)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovb ST(0),ST(7)", 0, 0, 0, OP_FCMOVB, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(0)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(1)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(2)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(3)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(4)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(5)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(6)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmove ST(0),ST(7)", 0, 0, 0, OP_FCMOVE, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* d */
+ OP("fcmovbe ST(0),ST(0)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(1)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(2)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(3)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(4)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(5)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(6)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovbe ST(0),ST(7)", 0, 0, 0, OP_FCMOVBE, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(0)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(1)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(2)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(3)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(4)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(5)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(6)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovu ST(0),ST(7)", 0, 0, 0, OP_FCMOVU, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* e */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("fucompp", 0, 0, 0, OP_FUCOMPP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* f */
+ INVALID_OPCODE_BLOCK
+};
+
+
+/* Floating point opcode starting with escape byte 0xDB (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF3_Low[8] =
+{
+ /* 0 */
+ OP("fild %Md", IDX_ParseModRM, 0, 0, OP_FILD, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("fist %Md", IDX_ParseModRM, 0, 0, OP_FIST, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fistp %Md", IDX_ParseModRM, 0, 0, OP_FISTP, OP_PARM_Md, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("fld %Mq", IDX_ParseModRM, 0, 0, OP_FLD, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("fstp %Mq", IDX_ParseModRM, 0, 0, OP_FSTP, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDB (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF3_High[16*4] =
+{
+ /* c */
+ OP("fcmovnb ST(0),ST(0)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(1)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(2)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(3)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(4)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(5)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(6)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnb ST(0),ST(7)", 0, 0, 0, OP_FCMOVNB, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(0)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(1)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(2)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(3)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(4)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(5)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(6)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovne ST(0),ST(7)", 0, 0, 0, OP_FCMOVNE, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* d */
+ OP("fcmovnbe ST(0),ST(0)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(1)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(2)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(3)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(4)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(5)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(6)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnbe ST(0),ST(7)", 0, 0, 0, OP_FCMOVNBE,OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(0)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(1)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(2)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(3)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(4)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(5)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(6)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcmovnu ST(0),ST(7)", 0, 0, 0, OP_FCMOVNU, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* e */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("fclex", 0, 0, 0, OP_FCLEX, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("finit", 0, 0, 0, OP_FINIT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("fucomi ST(0),ST(0)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(1)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(2)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(3)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(4)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(5)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(6)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomi ST(0),ST(7)", 0, 0, 0, OP_FUCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* e */
+ OP("fcomi ST(0),ST(0)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(1)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(2)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(3)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(4)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(5)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(6)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomi ST(0),ST(7)", 0, 0, 0, OP_FCOMI, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+
+/* Floating point opcode starting with escape byte 0xDC (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF4_Low[8] =
+{
+ /* 0 */
+ OP("fadd %Mq", IDX_ParseModRM, 0, 0, OP_FADD, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul %Mq", IDX_ParseModRM, 0, 0, OP_FMUL, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcom %Mq", IDX_ParseModRM, 0, 0, OP_FCOM, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomp %Mq", IDX_ParseModRM, 0, 0, OP_FCOMP, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub %Mq", IDX_ParseModRM, 0, 0, OP_FSUB, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr %Mq", IDX_ParseModRM, 0, 0, OP_FSUBR, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv %Mq", IDX_ParseModRM, 0, 0, OP_FDIV, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr %Mq", IDX_ParseModRM, 0, 0, OP_FDIVR, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDC (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF4_High[16*4] =
+{
+ /* c */
+ OP("fadd ST(0),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(1),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(2),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(3),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(4),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(5),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(6),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fadd ST(7),ST(0)", 0, 0, 0, OP_FADD, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(0),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(1),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(2),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(3),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(4),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(5),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(6),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmul ST(7),ST(0)", 0, 0, 0, OP_FMUL, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* d */
+ INVALID_OPCODE_BLOCK
+
+
+ /* e */
+ OP("fsubr ST(0),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(1),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(2),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(3),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(4),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(5),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(6),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubr ST(7),ST(0)", 0, 0, 0, OP_FSUBR, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(0),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(1),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(2),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(3),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(4),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(5),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(6),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsub ST(7),ST(0)", 0, 0, 0, OP_FSUB, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ OP("fdivr ST(0),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(1),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(2),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(3),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(4),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(5),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(6),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivr ST(7),ST(0)", 0, 0, 0, OP_FDIVR, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(0),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(1),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(2),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(3),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(4),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(5),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(6),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdiv ST(7),ST(0)", 0, 0, 0, OP_FDIV, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDD (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF5_Low[8] =
+{
+ /* 0 */
+ OP("fld %Mq", IDX_ParseModRM, 0, 0, OP_FLD, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS /* fixme: wasn't initialized! */),
+ INVALID_OPCODE,
+ OP("fst %Mq", IDX_ParseModRM, 0, 0, OP_FST, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS /* fixme: wasn't initialized! */),
+ OP("fstp %Mq", IDX_ParseModRM, 0, 0, OP_FSTP, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS /* fixme: wasn't initialized! */),
+ OP("frstor %M", IDX_ParseModRM, 0, 0, OP_FRSTOR, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS /* fixme: wasn't initialized! */),
+ INVALID_OPCODE,
+ OP("fnsave %M", IDX_ParseModRM, 0, 0, OP_FSAVE, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS /* fixme: wasn't initialized! */),
+ OP("fnstsw %Mw", IDX_ParseModRM, 0, 0, OP_FNSTSW, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS /* fixme: wasn't initialized! */),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDD (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF5_High[16*4] =
+{
+ /* c */
+ OP("ffree ST(0)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_0, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(1)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_1, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(2)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_2, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(3)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_3, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(4)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_4, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(5)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_5, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(6)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_6, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ffree ST(7)", 0, 0, 0, OP_FFREE, OP_PARM_REGFP_7, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ OP("fst ST(0)", 0, 0, 0, OP_FST, OP_PARM_REGFP_0, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(1)", 0, 0, 0, OP_FST, OP_PARM_REGFP_1, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(2)", 0, 0, 0, OP_FST, OP_PARM_REGFP_2, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(3)", 0, 0, 0, OP_FST, OP_PARM_REGFP_3, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(4)", 0, 0, 0, OP_FST, OP_PARM_REGFP_4, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(5)", 0, 0, 0, OP_FST, OP_PARM_REGFP_5, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(6)", 0, 0, 0, OP_FST, OP_PARM_REGFP_6, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fst ST(7)", 0, 0, 0, OP_FST, OP_PARM_REGFP_7, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(0)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_0, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(1)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_1, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(2)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_2, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(3)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_3, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(4)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_4, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(5)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_5, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(6)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_6, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fstp ST(7)", 0, 0, 0, OP_FSTP, OP_PARM_REGFP_7, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* e */
+ OP("fucom ST(0)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_0, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(1)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_1, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(2)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_2, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(3)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_3, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(4)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_4, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(5)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_5, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(6)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_6, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucom ST(7)", 0, 0, 0, OP_FUCOM, OP_PARM_REGFP_7, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(0)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_0, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(1)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_1, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(2)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_2, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(3)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_3, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(4)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_4, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(5)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_5, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(6)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_6, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomp ST(7)", 0, 0, 0, OP_FUCOMP, OP_PARM_REGFP_7, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ INVALID_OPCODE_BLOCK
+};
+
+
+
+/* Floating point opcode starting with escape byte 0xDE (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF6_Low[8] =
+{
+ /* 0 */
+ OP("fiadd %Mw", IDX_ParseModRM, 0, 0, OP_FIADD, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fimul %Mw", IDX_ParseModRM, 0, 0, OP_FIMUL, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ficom %Mw", IDX_ParseModRM, 0, 0, OP_FICOM, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ficomp %Mw", IDX_ParseModRM, 0, 0, OP_FICOMP, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fisub %Mw", IDX_ParseModRM, 0, 0, OP_FISUB, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fisubr %Mw", IDX_ParseModRM, 0, 0, OP_FISUBR, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fidiv %Mw", IDX_ParseModRM, 0, 0, OP_FIDIV, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fidivr %Mw", IDX_ParseModRM, 0, 0, OP_FIDIVR, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDE (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF6_High[16*4] =
+{
+ /* c */
+ OP("faddp ST(0),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(1),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(2),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(3),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(4),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(5),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(6),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("faddp ST(7),ST(0)", 0, 0, 0, OP_FADDP, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(0),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(1),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(2),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(3),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(4),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(5),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(6),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fmulp ST(7),ST(0)", 0, 0, 0, OP_FMULP, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* d */
+ INVALID_OPCODE,
+ OP("fcompp", 0, 0, 0, OP_FCOMPP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+
+ /* e */
+ OP("fsubrp ST(0),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(1),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(2),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(3),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(4),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(5),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(6),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubrp ST(7),ST(0)", 0, 0, 0, OP_FSUBRP, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(0),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(1),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(2),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(3),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(4),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(5),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(6),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fsubp ST(7),ST(0)", 0, 0, 0, OP_FSUBP, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ OP("fdivrp ST(0),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(1),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(2),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(3),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(4),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(5),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(6),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivrp ST(7),ST(0)", 0, 0, 0, OP_FDIVRP, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(0),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(1),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_1, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(2),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_2, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(3),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_3, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(4),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_4, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(5),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_5, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(6),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_6, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fdivp ST(7),ST(0)", 0, 0, 0, OP_FDIVP, OP_PARM_REGFP_7, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+/* Floating point opcode starting with escape byte 0xDF (values 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF7_Low[8] =
+{
+ /* 0 */
+ OP("fild %Mw", IDX_ParseModRM, 0, 0, OP_FILD, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("fist %Mw", IDX_ParseModRM, 0, 0, OP_FIST, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fistp %Mw", IDX_ParseModRM, 0, 0, OP_FISTP, OP_PARM_Mw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fbld %M", IDX_ParseModRM, 0, 0, OP_FBLD, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fild %Mq", IDX_ParseModRM, 0, 0, OP_FILD, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fbstp %M", IDX_ParseModRM, 0, 0, OP_FBSTP, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fistp %Mq", IDX_ParseModRM, 0, 0, OP_FISTP, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* Floating point opcode starting with escape byte 0xDF (outside 0-0xBF)*/
+const DISOPCODE g_aMapX86_EscF7_High[16*4] =
+{
+ /* c */
+ INVALID_OPCODE_BLOCK
+
+ /* d */
+ INVALID_OPCODE_BLOCK
+
+ /* e */
+ OP("fnstsw ax", IDX_ParseFixedReg, 0, 0, OP_FNSTSW, OP_PARM_REG_AX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("fucomip ST(0),ST(0)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(1)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(2)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(3)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(4)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(5)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(6)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fucomip ST(0),ST(7)", 0, 0, 0, OP_FUCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ OP("fcomip ST(0),ST(0)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_0,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(1)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_1,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(2)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_2,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(3)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_3,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(4)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_4,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(5)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_5,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(6)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_6,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fcomip ST(0),ST(7)", 0, 0, 0, OP_FCOMIP, OP_PARM_REGFP_0, OP_PARM_REGFP_7,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+
+const PCDISOPCODE g_apMapX86_FP_Low[8] =
+{
+ g_aMapX86_EscF0_Low,
+ g_aMapX86_EscF1_Low,
+ g_aMapX86_EscF2_Low,
+ g_aMapX86_EscF3_Low,
+ g_aMapX86_EscF4_Low,
+ g_aMapX86_EscF5_Low,
+ g_aMapX86_EscF6_Low,
+ g_aMapX86_EscF7_Low
+};
+
+const PCDISOPCODE g_apMapX86_FP_High[8] =
+{
+ g_aMapX86_EscF0_High,
+ g_aMapX86_EscF1_High,
+ g_aMapX86_EscF2_High,
+ g_aMapX86_EscF3_High,
+ g_aMapX86_EscF4_High,
+ g_aMapX86_EscF5_High,
+ g_aMapX86_EscF6_High,
+ g_aMapX86_EscF7_High
+};
+
+/* Opcode extensions (Group tables) */
+const DISOPCODE g_aMapX86_Group1[8*4] =
+{
+ /* 80 */
+ OP("add %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ADD, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_OR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ADC, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SBB, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_AND, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SUB, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_XOR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_CMP, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 81 */
+ OP("add %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_ADD, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_OR, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_ADC, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_SBB, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_AND, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_SUB, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_XOR, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_CMP, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 82 */
+ OP("add %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ADD, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_OR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ADC, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SBB, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_AND, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SUB, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_XOR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_CMP, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 83 */
+ OP("add %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_ADD, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_OR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_ADC, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_SBB, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_AND, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_SUB, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_XOR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByteSX, 0, OP_CMP, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+const DISOPCODE g_aMapX86_Group2[8*6] =
+{
+ /* C0 */
+ OP("rol %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ROL, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ror %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ROR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcl %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_RCL, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcr %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_RCR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SHL, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shr %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SHR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SHL, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sar %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SAR, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* C1 */
+ OP("rol %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ROL, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ror %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_ROR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcl %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_RCL, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcr %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_RCR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SHL, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shr %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SHR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SHL, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sar %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_SAR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* D0 */
+ OP("rol %Eb,1", IDX_ParseModRM, 0, 0, OP_ROL, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ror %Eb,1", IDX_ParseModRM, 0, 0, OP_ROR, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcl %Eb,1", IDX_ParseModRM, 0, 0, OP_RCL, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcr %Eb,1", IDX_ParseModRM, 0, 0, OP_RCR, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Eb,1", IDX_ParseModRM, 0, 0, OP_SHL, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shr %Eb,1", IDX_ParseModRM, 0, 0, OP_SHR, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Eb,1", IDX_ParseModRM, 0, 0, OP_SHL, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sar %Eb,1", IDX_ParseModRM, 0, 0, OP_SAR, OP_PARM_Eb, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* D1 */
+ OP("rol %Ev,1", IDX_ParseModRM, 0, 0, OP_ROL, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ror %Ev,1", IDX_ParseModRM, 0, 0, OP_ROR, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcl %Ev,1", IDX_ParseModRM, 0, 0, OP_RCL, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcr %Ev,1", IDX_ParseModRM, 0, 0, OP_RCR, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Ev,1", IDX_ParseModRM, 0, 0, OP_SHL, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shr %Ev,1", IDX_ParseModRM, 0, 0, OP_SHR, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Ev,1", IDX_ParseModRM, 0, 0, OP_SHL, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sar %Ev,1", IDX_ParseModRM, 0, 0, OP_SAR, OP_PARM_Ev, OP_PARM_1 , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* D2 */
+ OP("rol %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_ROL, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ror %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_ROR, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcl %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_RCL, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcr %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_RCR, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SHL, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shr %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SHR, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SHL, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sar %Eb,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SAR, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* D3 */
+ OP("rol %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_ROL, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ror %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_ROR, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcl %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_RCL, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rcr %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_RCR, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SHL, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shr %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SHR, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("shl/sal %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SHL, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sar %Ev,CL", IDX_ParseModRM, IDX_ParseFixedReg, 0, OP_SAR, OP_PARM_Ev, OP_PARM_REG_CL ,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+};
+
+
+const DISOPCODE g_aMapX86_Group3[8*2] =
+{
+ /* F6 */
+ OP("test %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_TEST, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ //AMD manual claims test??
+ INVALID_OPCODE_MOD_RM(0xf601),
+ OP("not %Eb", IDX_ParseModRM, 0, 0, OP_NOT, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("neg %Eb", IDX_ParseModRM, 0, 0, OP_NEG, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mul %Eb", IDX_ParseModRM, 0, 0, OP_MUL, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("imul %Eb", IDX_ParseModRM, 0, 0, OP_IMUL, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("div %Eb", IDX_ParseModRM, 0, 0, OP_DIV, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("idiv %Eb", IDX_ParseModRM, 0, 0, OP_IDIV, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* F7 */
+ OP("test %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_TEST, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ //AMD manual claims test??
+ INVALID_OPCODE_MOD_RM(0xf701),
+ OP("not %Ev", IDX_ParseModRM, 0, 0, OP_NOT, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("neg %Ev", IDX_ParseModRM, 0, 0, OP_NEG, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mul %Ev", IDX_ParseModRM, 0, 0, OP_MUL, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("imul %Ev", IDX_ParseModRM, 0, 0, OP_IMUL, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("div %Ev", IDX_ParseModRM, 0, 0, OP_DIV, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("idiv %Ev", IDX_ParseModRM, 0, 0, OP_IDIV, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+const DISOPCODE g_aMapX86_Group4[8] =
+{
+ /* FE */
+ OP("inc %Eb", IDX_ParseModRM, 0, 0, OP_INC, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %Eb", IDX_ParseModRM, 0, 0, OP_DEC, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0xfe02),
+ INVALID_OPCODE_MOD_RM(0xfe03),
+ INVALID_OPCODE_MOD_RM(0xfe04),
+ INVALID_OPCODE_MOD_RM(0xfe05),
+ INVALID_OPCODE_MOD_RM(0xfe06),
+ INVALID_OPCODE_MOD_RM(0xfe07),
+};
+
+const DISOPCODE g_aMapX86_Group5[8] =
+{
+ /* FF */
+ OP("inc %Ev", IDX_ParseModRM, 0, 0, OP_INC, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("dec %Ev", IDX_ParseModRM, 0, 0, OP_DEC, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("call %Ev", IDX_ParseModRM, 0, 0, OP_CALL, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("call %Ep", IDX_ParseModRM, 0, 0, OP_CALL, OP_PARM_Ep, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW),
+ OP("jmp %Ev", IDX_ParseModRM, 0, 0, OP_JMP, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jmp %Ep", IDX_ParseModRM, 0, 0, OP_JMP, OP_PARM_Ep, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+ OP("push %Ev", IDX_ParseModRM, 0, 0, OP_PUSH, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ INVALID_OPCODE_MOD_RM(0xff07),
+};
+
+
+const DISOPCODE g_aMapX86_Group6[8] =
+{
+ /* 0F 00 */
+ OP("sldt %Ew", IDX_ParseModRM, 0, 0, OP_SLDT, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ OP("str %Ev", IDX_ParseModRM, 0, 0, OP_STR, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ OP("lldt %Ew", IDX_ParseModRM, 0, 0, OP_LLDT, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("ltr %Ew", IDX_ParseModRM, 0, 0, OP_LTR, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("verr %Ew", IDX_ParseModRM, 0, 0, OP_VERR, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ OP("verw %Ew", IDX_ParseModRM, 0, 0, OP_VERW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ INVALID_OPCODE_MOD_RM(0x0f0006),
+ INVALID_OPCODE_MOD_RM(0x0f0007),
+};
+
+/* Note!! Group 7 is NOT using the INVALID_OPCODE_MOD_RM because of monitor and vmcall. */
+const DISOPCODE g_aMapX86_Group7_mem[8] =
+{
+ /* 0F 01 */
+ OP("sgdt %Ms", IDX_ParseModRM, 0, 0, OP_SGDT, OP_PARM_Ms, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ OP("sidt %Ms", IDX_ParseModRM, 0, 0, OP_SIDT, OP_PARM_Ms, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ OP("lgdt %Ms", IDX_ParseModRM, 0, 0, OP_LGDT, OP_PARM_Ms, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("lidt %Ms", IDX_ParseModRM, 0, 0, OP_LIDT, OP_PARM_Ms, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("smsw %Ew", IDX_ParseModRM, 0, 0, OP_SMSW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ INVALID_OPCODE,
+ OP("lmsw %Ew", IDX_ParseModRM, 0, 0, OP_LMSW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("invlpg %Mb", IDX_ParseModRM, 0, 0, OP_INVLPG, OP_PARM_Mb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+};
+
+/* Note!! Group 7 is NOT using the INVALID_OPCODE_MOD_RM because of monitor and vmcall. */
+const DISOPCODE g_aMapX86_Group7_mod11_rm000[8] =
+{
+ /* 0F 01 MOD=11b */
+ INVALID_OPCODE,
+ OP("monitor %eAX,%eCX,%eDX", IDX_ParseFixedReg, IDX_ParseFixedReg, IDX_ParseFixedReg, OP_MONITOR, OP_PARM_REG_EAX, OP_PARM_REG_ECX, OP_PARM_REG_EDX, DISOPTYPE_HARMLESS ),
+ OP("xgetbv", 0, 0, 0, OP_XGETBV, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS ), /* fixed ops: ECX & EDX:EAX like wrmsr we don't details these */
+ INVALID_OPCODE,
+ OP("smsw %Ew", IDX_ParseModRM, 0, 0, OP_SMSW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ INVALID_OPCODE,
+ OP("lmsw %Ew", IDX_ParseModRM, 0, 0, OP_LMSW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("swapgs", 0, 0, 0, OP_SWAPGS, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS )
+};
+
+/* Note!! Group 7 is NOT using the INVALID_OPCODE_MOD_RM because of monitor and vmcall. */
+const DISOPCODE g_aMapX86_Group7_mod11_rm001[8] =
+{
+ /* 0F 01 MOD=11b */
+ OP("vmcall", 0, 0, 0, OP_VMCALL, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS ),
+ OP("mwait %eAX,%eCX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_MWAIT, OP_PARM_REG_EAX, OP_PARM_REG_ECX,OP_PARM_NONE, DISOPTYPE_HARMLESS ),
+ OP("xsetbv", 0, 0, 0, OP_XSETBV, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS ), /* fixed ops: ECX & EDX:EAX like wrmsr we don't details these */
+ OP("vmmcall", 0, 0, 0, OP_VMMCALL, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS ),
+ OP("smsw %Ew", IDX_ParseModRM, 0, 0, OP_SMSW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED_NOTRAP),
+ INVALID_OPCODE,
+ OP("lmsw %Ew", IDX_ParseModRM, 0, 0, OP_LMSW, OP_PARM_Ew, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("rdtscp", 0, 0, 0, OP_RDTSCP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS ),
+};
+
+const DISOPCODE g_aMapX86_Group8[8] =
+{
+ /* 0F BA */
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("bt %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_BT, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("bts %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_BTS, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("btr %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_BTR, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("btc %Ev,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_BTC, OP_PARM_Ev, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+const DISOPCODE g_aMapX86_Group9[8] =
+{
+ /* 0F C7 */
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("cmpxchg8b %Mq", IDX_ParseModRM, 0, 0, OP_CMPXCHG8B, OP_PARM_Mq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("rdrand %Ev", IDX_ParseModRM, 0, 0, OP_RDRAND, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rdseed %Ev", IDX_ParseModRM, 0, 0, OP_RDSEED, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+const DISOPCODE g_aMapX86_Group10[8] =
+{
+ /* 0F B9 */
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+};
+
+
+const DISOPCODE g_aMapX86_Group11[8*2] =
+{
+ /* 0F C6 */
+ OP("mov %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_Eb, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ /* 0F C7 */
+ OP("mov %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+};
+
+
+/* 0xF 0x71 */
+const DISOPCODE g_aMapX86_Group12[8*2] =
+{
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrlw %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLW, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psraw %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRAW, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psllw %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLW, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+
+ /* Group 12 with prefix 0x66 */
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrlw %Pdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLW, OP_PARM_Pdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psraw %Pdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRAW, OP_PARM_Pdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psllw %Pdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLW, OP_PARM_Pdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+};
+
+/* 0xF 0x72 */
+const DISOPCODE g_aMapX86_Group13[8*2] =
+{
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrld %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLD, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrad %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRAD, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("pslld %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLD, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+
+ /* Group 13 with prefix 0x66 */
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrld %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLD, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrad %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRAD, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("pslld %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLD, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+};
+
+/* 0xF 0x73 */
+const DISOPCODE g_aMapX86_Group14[8*2] =
+{
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrlq %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLQ, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psllq %Pq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLQ, OP_PARM_Pq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+
+ /* Group 14 with prefix 0x66 */
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psrlq %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLD, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("psrldq %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSRLDQ, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ OP("psllq %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLD, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pslldq %Wdq,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_PSLLDQ, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+/* 0xF 0xAE */
+const DISOPCODE g_aMapX86_Group15_mem[8] =
+{
+ OP("fxsave %M", IDX_ParseModRM, 0, 0, OP_FXSAVE, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("fxrstor %M", IDX_ParseModRM, 0, 0, OP_FXRSTOR, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ldmxcsr %M", IDX_ParseModRM, 0, 0, OP_LDMXCSR, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stmxcsr %M", IDX_ParseModRM, 0, 0, OP_STMXCSR, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xsave %M", IDX_ParseModRM, 0, 0, OP_XSAVE, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xrstor %M", IDX_ParseModRM, 0, 0, OP_XRSTOR, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xsaveopt %M", IDX_ParseModRM, 0, 0, OP_XSAVEOPT, OP_PARM_M, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("clflush %Mb", IDX_ParseModRM, 0, 0, OP_CLFLUSH, OP_PARM_Mb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+/* 0xF 0xAE */
+const DISOPCODE g_aMapX86_Group15_mod11_rm000[8] =
+{
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ /** @todo mfence + lfence + sfence instructions do not require rm=0,
+ * they work for any RM value. See bs2-cpu-instr-1.asm for details. */
+ OP("lfence", IDX_ParseModFence, 0, 0, OP_LFENCE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mfence", IDX_ParseModFence, 0, 0, OP_MFENCE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sfence", IDX_ParseModFence, 0, 0, OP_SFENCE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+/* 0xF 0x18 */
+const DISOPCODE g_aMapX86_Group16[8] =
+{
+ OP("prefetchnta %Mb", IDX_ParseModRM, 0, 0, OP_PREFETCH,OP_PARM_Mb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("prefetcht0 %Mb", IDX_ParseModRM, 0, 0, OP_PREFETCH,OP_PARM_Mb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("prefetcht1 %Mb", IDX_ParseModRM, 0, 0, OP_PREFETCH,OP_PARM_Mb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("prefetcht2 %Mb", IDX_ParseModRM, 0, 0, OP_PREFETCH,OP_PARM_Mb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+ INVALID_OPCODE_MOD_RM(0x),
+};
+
+/* 0x90 or 0xF3 0x90 */
+const DISOPCODE g_aMapX86_NopPause[2] =
+{
+ OP("nop", 0, 0, 0, OP_NOP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pause", 0, 0, 0, OP_PAUSE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
+
+
+/* VEX Map 1 - two bytes opcodes starting with 0Fh */
+const DISOPCODE g_aDisasVexMap1[] =
+{
+ /* 1 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("vmovups %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVUPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovups %Wps,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVUPS, OP_PARM_Wps, OP_PARM_Vps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("&vmovlps/vmovhlps %Vq,%Hq,%Wq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVLPS, OP_PARM_Vq, OP_PARM_Hq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovlps %Mq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVLPS, OP_PARM_Mq, OP_PARM_Vq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vunpcklps %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VUNPCKLPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vunpckhps %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VUNPCKHPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("&vmovhps/vmovlhps %Vdq,%Hq,%Wq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVHPS, OP_PARM_Vdq, OP_PARM_Hq, OP_PARM_Wq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovhps %Mq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVHPS, OP_PARM_Mq, OP_PARM_Vq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vmovaps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVAPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovaps %Wps,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVAPS, OP_PARM_Wps, OP_PARM_Vps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vmovntps %Mps,%Vps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVNTPS, OP_PARM_Mps, OP_PARM_Vps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vucomiss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VUCOMISS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcomiss %Vss,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCOMISS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 3 */
+ INVALID_OPCODE_BLOCK
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ OPVEX("vmovmskps %Gy,%Ups", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVMSKPS, OP_PARM_Gy, OP_PARM_Ups, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vsqrtps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VSQRTPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vrsqrtps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VRSQRTPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vrcpps %Vps,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VRCPPS, OP_PARM_Vps, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vandps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VANDPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vandnps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VANDNPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vorps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VORPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vxorps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VXORPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vaddps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VADDPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmulps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMULPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtps2pd %Vpd,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTPS2PD, OP_PARM_Vpd, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtdq2ps %Vps,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTDQ2PS, OP_PARM_Vps, OP_PARM_Wdq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vsubps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VSUBPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vminps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMINPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vdivps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VDIVPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaxps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMAXPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE_BLOCK
+
+ /* 7 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ /* Next instruction has the following format:
+ * @name1/name2,
+ * where name2 is used when VEX.L bit is set,
+ * name1 otherwise. */
+ OPVEX("@vzeroupper/vzeroall", 0, 0, 0, 0, OP_VZEROALL, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 8 */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcmpss %Vps,%Hps,%Wps,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VCMPSS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vshufps %Vps,%Hps,%Wps,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VSHUFPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ /* format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+};
+const DISOPMAPDESC g_DisasVexMap1Range = { &g_aDisasVexMap1[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1) };
+
+/* Vex codes for two bytes opcodes starting with 0Fh with prefix 66H*/
+static const DISOPCODE g_aDisasVexMap1_66[] =
+{
+ /* 1 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("vmovupd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVUPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovupd %Wpd,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVUPD, OP_PARM_Wpd, OP_PARM_Vpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovlpd %Vq,%Hq,%Mq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVLPD, OP_PARM_Vq, OP_PARM_Hq, OP_PARM_Mq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovlpd %Mq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVLPD, OP_PARM_Mq, OP_PARM_Vq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vunpcklpd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VUNPCKLPD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vunpckhpd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VUNPCKHPD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovhpd %Vdq,%Hq,%Mq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVHPD, OP_PARM_Vdq, OP_PARM_Hq, OP_PARM_Mq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovhpd %Mq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVHPD, OP_PARM_Mq, OP_PARM_Vq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vmovapd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVAPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovapd %Wpd,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVAPD, OP_PARM_Wpd, OP_PARM_Vpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vmovntpd %Mpd,%Vpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVNTPD, OP_PARM_Mpd, OP_PARM_Vpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vucomisd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VUCOMISD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcomisd %Vsd,%Wsd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCOMISD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 3 */
+ INVALID_OPCODE_BLOCK
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ OPVEX("vmovmskpd %Gy,%Upd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVMSKPD, OP_PARM_Gy, OP_PARM_Upd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vsqrtpd %Vpd,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VSQRTPD, OP_PARM_Vpd, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vandpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VANDPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vandnpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VANDNPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vorpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VORPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vxorpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VXORPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vaddpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VADDPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmulpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMULPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtpd2ps %Vps,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTPD2PS, OP_PARM_Vps, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtps2dq %Vdq,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTPS2DQ, OP_PARM_Vdq, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vsubpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VSUBPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vminpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMINPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vdivpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VDIVPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaxpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMAXPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* 6 */
+ OPVEX("vpunpcklbw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKLBW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpcklwd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKLWD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpckldq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKLDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpacksswb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPACKSSWB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpgtb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPGTB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpgtw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPGTW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpgtd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPGTD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpackuswb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPACKUSWB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpckhbw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKHBW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpckhwd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKHWD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpckhdq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKHDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpackssdw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPACKSSDW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpcklqdq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKLQDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpunpckhqdq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPUNPCKHQDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vmovd/vmovq %Vy,%Ey", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVD, OP_PARM_Vy, OP_PARM_Ey, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovdqa %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVDQA, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 7 */
+ OPVEX("vpshufd %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPSHUFD, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vpcmpeqb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPEQB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpeqw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPEQW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpeqd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPEQD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vhaddpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VHADDPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vhsubpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VHSUBPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovd/vmovq %Ey,%Vy", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVD, OP_PARM_Ey, OP_PARM_Vy, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovdqa %Wx,%Vx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVDQA, OP_PARM_Wx, OP_PARM_Vx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 8 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcmpps %Vpd,%Hpd,%Wpd,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VCMPSS, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ // vpinsrw Vdq,Hdq,Ry/Mw,Ib
+ OPVEX("vpinsrw %Vdq,%Hdq,%Ey,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPINSRW, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Ey, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vpextrw %Gd,%Udq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPEXTRW, OP_PARM_Gd, OP_PARM_Udq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vshufpd %Vpd,%Hpd,%Wpd,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VSHUFPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ OPVEX("vaddsubpd %Vpd,%Hpd,%Wpd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VADDSUBPD, OP_PARM_Vpd, OP_PARM_Hpd, OP_PARM_Wpd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsrlw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRLW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsrld %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRLD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsrlq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRLQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmullw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULLW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovq %Wq,%Vq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVQ, OP_PARM_Wq, OP_PARM_Vq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovmskb %Gd,%Ux", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVMSKB, OP_PARM_Gd, OP_PARM_Ux, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OPVEX("vpsubusb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBUSB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubusw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBUSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpminub %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMINUB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpand %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPAND, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddusb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDUSB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddusw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDUSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaxub %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMAXUB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpandn %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPANDN, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* e */
+ OPVEX("vpavgb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPAVGB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsraw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRAW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsrad %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRAD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpavgw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPAVGW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmulhuw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULHUW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmulhw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULHW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvttpd2dq %Vx,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTTPD2DQ, OP_PARM_Vx, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovntdq %Mx,%Vx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVNTDQ, OP_PARM_Mx, OP_PARM_Vx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubsb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBSB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpminsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMINSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpor %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPOR, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddsb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDSB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaxsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMAXSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpxor %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPXOR, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* f */
+ INVALID_OPCODE,
+ OPVEX("vpsllw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSLLW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpslld %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSLLD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsllq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSLLQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmuludq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULUDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaddwd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMADDWD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsadbw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSADBW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaskmovdqu %Vdq,%Udq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMASKMOVDQU, OP_PARM_Vdq, OP_PARM_Udq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsubq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSUBQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpaddd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPADDD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+};
+const DISOPMAPDESC g_DisasVexMap1_66Range = { &g_aDisasVexMap1_66[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1_66) };
+
+static const DISOPCODE g_aDisasVexMap1F2[] =
+{
+ /* 1 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("vmovsd %Vx,%Hx,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVSD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovsd %Wsd,%Hx,%Vsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVSD, OP_PARM_Wsd, OP_PARM_Hx, OP_PARM_Vsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovddup %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVDDUP, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE_BLOCK
+
+ /* 3 */
+ INVALID_OPCODE_BLOCK
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ INVALID_OPCODE,
+ OPVEX("vsqrtsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VSQRTSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vaddsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VADDSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmulsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMULSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtsd2ss %Vss,%Hx,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VCVTSD2SS, OP_PARM_Vss, OP_PARM_Hx, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vsubsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VSUBSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vminsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMINSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vdivsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VDIVSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaxsd %Vsd,%Hsd,%Wsd", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMAXSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 */
+ INVALID_OPCODE_BLOCK
+
+ /* 7 */
+ OPVEX("vpshuflw %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPSHUFLW, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vhaddps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VHADDPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vhsubps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VHSUBPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 8 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcmpsd %Vsd,%Hsd,%Wsd,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VCMPSD, OP_PARM_Vsd, OP_PARM_Hsd, OP_PARM_Wsd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ OPVEX("vaddsubps %Vps,%Hps,%Wps", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VADDSUBPS, OP_PARM_Vps, OP_PARM_Hps, OP_PARM_Wps, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* e */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcvtpd2dq %Vx,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTPD2DQ, OP_PARM_Vx, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* f */
+ OPVEX("vlddqu %Vx,%Mx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VLDDQU, OP_PARM_Vx, OP_PARM_Mx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+};
+const DISOPMAPDESC g_DisasVexMap1F2Range = { &g_aDisasVexMap1F2[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1F2) };
+
+/* Vex codes for two bytes opcodes starting with 0Fh with prefix F3H*/
+static const DISOPCODE g_aDisasVexMap1F3[] =
+{
+ /* 1 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("vmovss %Vx,%Hx,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVSS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovss %Wss,%Hx,%Vss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMOVSS, OP_PARM_Wss, OP_PARM_Hx, OP_PARM_Vss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovsldup %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVSLDUP, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vmovshdup %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVSHDUP, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcvtsi2ss %Vss,%Hss,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VCVTSI2SS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vcvttss2si %Gy,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTTSS2SI, OP_PARM_Gy, OP_PARM_Wss, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtss2si %Gy,%Wss", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTSS2SI, OP_PARM_Gy, OP_PARM_Wss, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 3 */
+ INVALID_OPCODE_BLOCK
+
+ /* 4 */
+ INVALID_OPCODE_BLOCK
+
+ /* 5 */
+ INVALID_OPCODE,
+ OPVEX("vsqrtss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VSQRTSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vrsqrtss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VRSQRTSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vrcpss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VRCPSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vaddss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VADDSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmulss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMULSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvtss2sd %Vsd,%Hx,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VCVTSS2SD, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vcvttps2dq %Vdq,%Wps", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTTPS2DQ, OP_PARM_Vdq, OP_PARM_Wps, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vsubss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VSUBSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vminss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMINSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vdivss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VDIVSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaxss %Vss,%Hss,%Wss", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMAXSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 6 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vmovdqu %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVDQU, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 7 */
+ OPVEX("vpshufhw %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPSHUFHW, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vmovq %Vq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVQ, OP_PARM_Vq, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovdqu %Wx,%Vx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVDQU, OP_PARM_Wx, OP_PARM_Vx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 8 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcmpps %Vss,%Hss,%Wss,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VCMPSS, OP_PARM_Vss, OP_PARM_Hss, OP_PARM_Wss, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* d */
+ INVALID_OPCODE_BLOCK
+
+ /* e */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcvtdq2pd %Vx,%Wpd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VCVTDQ2PD, OP_PARM_Vx, OP_PARM_Wpd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+};
+const DISOPMAPDESC g_DisasVexMap1F3Range = { &g_aDisasVexMap1F3[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1F3) };
+
+/** Indexed by: (/r << 1) | VEX.L */
+const DISOPCODE g_aMapX86_Group17[8*2] =
+{
+ /* 0 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE_MOD_RM(0x00),
+ INVALID_OPCODE_MOD_RM(0x01),
+ OPVEX("blsr %By,%Ey", IDX_ParseVexDest, IDX_ParseModRM, 0, 0, OP_BLSR, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x03),
+ OPVEX("blsmsk %By,%Ey", IDX_ParseVexDest, IDX_ParseModRM, 0, 0, OP_BLSMSK, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x05),
+ OPVEX("blsi %By,%Ey", IDX_ParseVexDest, IDX_ParseModRM, 0, 0, OP_BLSI, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE_MOD_RM(0x07),
+ INVALID_OPCODE_MOD_RM(0x08),
+ INVALID_OPCODE_MOD_RM(0x09),
+ INVALID_OPCODE_MOD_RM(0x0a),
+ INVALID_OPCODE_MOD_RM(0x0b),
+ INVALID_OPCODE_MOD_RM(0x0c),
+ INVALID_OPCODE_MOD_RM(0x0d),
+ INVALID_OPCODE_MOD_RM(0x0e),
+ INVALID_OPCODE_MOD_RM(0x0f),
+};
+
+static const DISOPCODE g_aDisasVexMap2[] =
+{
+ /** @todo vsha1nexte at 0xc8 + ? */
+ /* 0xf2 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("andn %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_ANDN, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vgroup17", IDX_ParseGrp17, 0, 0, 0, OP_GRP17, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("bzhi %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_BZHI, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("bextr %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_BEXTR, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+const DISOPMAPDESC g_DisasVexMap2Range = { &g_aDisasVexMap2[0], 0xf2, RT_ELEMENTS(g_aDisasVexMap2) };
+
+static const DISOPCODE g_aDisasVexMap2F3[] =
+{
+ /* 0xf5 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("pext %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_PEXT, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("sarx %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_SARX, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+const DISOPMAPDESC g_DisasVexMap2F3Range = { &g_aDisasVexMap2F3[0], 0xf5, RT_ELEMENTS(g_aDisasVexMap2F3) };
+
+static const DISOPCODE g_aDisasVexMap2F2[] =
+{
+ /* 0xf5 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("pdep %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_PDEP, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("mulx %By,%Gy,%Ey", IDX_ParseVexDest, IDX_ParseModRM, IDX_UseModRM, 0, OP_MULX, OP_PARM_By, OP_PARM_Gy, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("shrx %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_SHRX, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+const DISOPMAPDESC g_DisasVexMap2F2Range = { &g_aDisasVexMap2F2[0], 0xf5, RT_ELEMENTS(g_aDisasVexMap2F2) };
+
+static const DISOPCODE g_aDisasVexMap2_66[] =
+{
+ /* 0 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("vpshufb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSHUFB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphaddw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPHADDW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphaddd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPHADDD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphaddsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPHADDSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaddubsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMADDUBSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphsubw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPHSUBW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphsubd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPHSUBD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphsubsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPHSUBSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsignb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSIGNB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsignw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSIGNW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsignd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSIGND, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmulhrsw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULHRSW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpermilps %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPERMILPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpermilpd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPERMILPD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vtestps %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VTESTPS, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vtestpd %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VTESTPD, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 1 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcvtph2ps %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VCVTPH2PS, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vpermps %Vqq,%Hqq,%Wqq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPERMPS, OP_PARM_Vqq, OP_PARM_Hqq, OP_PARM_Wqq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vptest %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPTEST, OP_PARM_Vx, OP_PARM_Wd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vbroadcastss %Vx,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VBROADCASTSS, OP_PARM_Vx, OP_PARM_Wd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vbroadcastsd %Vqq,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VBROADCASTSD, OP_PARM_Vqq, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vbroadcastf128 %Vqq,%Mdq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VBROADCASTF128, OP_PARM_Vqq, OP_PARM_Wdq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vpabsb %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPABSB, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpabsw %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPABSW, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpabsd %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPABSD, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+
+ /* 2 */
+ OPVEX("vpmovsxbw %Vx,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVSXBW, OP_PARM_Vx, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovsxbd %Vx,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVSXBD, OP_PARM_Vx, OP_PARM_Wd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovsxbq %Vx,%Ww", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVSXBQ, OP_PARM_Vx, OP_PARM_Ww, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovsxwd %Vx,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVSXWD, OP_PARM_Vx, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovsxwq %Vx,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVSXWQ, OP_PARM_Vx, OP_PARM_Wd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovsxdq %Vx,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVSXDQ, OP_PARM_Vx, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vpmuldq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULDQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpeqq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPEQQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmovntdqa %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VMOVNTDQA, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpackusdw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VVPACKUSDW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaskmovps %Vx,%Hx,%Mx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMASKMOVPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Mx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaskmovpd %Vx,%Hx,%Mx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMASKMOVPD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Mx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaskmovps %Mx,%Hx,%Vx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMASKMOVPS, OP_PARM_Mx, OP_PARM_Hx, OP_PARM_Vx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vmaskmovpd %Mx,%Hx,%Vx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VMASKMOVPD, OP_PARM_Mx, OP_PARM_Hx, OP_PARM_Vx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 3 */
+ OPVEX("vpmovzxbw %Vx,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVZXBW, OP_PARM_Vx, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovzxbd %Vx,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVZXBD, OP_PARM_Vx, OP_PARM_Wd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovzxbq %Vx,%Ww", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVZXBQ, OP_PARM_Vx, OP_PARM_Ww, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovzxwd %Vx,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVZXWD, OP_PARM_Vx, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovzxwq %Vx,%Wd", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVZXWQ, OP_PARM_Vx, OP_PARM_Wd, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmovzxdq %Vx,%Wq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPMOVZXDQ, OP_PARM_Vx, OP_PARM_Wq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpermd %Vqq,%Hqq,%Wqq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPERMD, OP_PARM_Vqq, OP_PARM_Hqq, OP_PARM_Wqq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpgtq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPCMPGTQ, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpminsb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMINSB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpminsd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMINSD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpminuw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMINUW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpminud %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMINUD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaxsb %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMAXSB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaxsd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMAXSD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaxuw %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMAXUW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpmaxud %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMAXUD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 4 */
+ OPVEX("vpmulld %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMULLD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vphminposuw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPHMINPOSUW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("#vpsrlvd/vpsrlvq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRLVD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpsravd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSRAVD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vpsllvd/vpsllvq %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPSLLVD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 5 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vpbroadcastd %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPBROADCASTD, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpbroadcastq %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPBROADCASTQ, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpbroadcasti128 %Vqq,%Mdq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPBROADCASTI128, OP_PARM_Vqq, OP_PARM_Mdq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 6 */
+ INVALID_OPCODE_BLOCK
+
+ /* 7 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vpbroadcastb %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPBROADCASTB, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpbroadcastw %Vx,%Wx", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VPBROADCASTW, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 8 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("#vpmaskmovd/vpmaskmovq %Vx,%Hx,%Mx",IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VPMASKMOVD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Mx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("#vpmaskmovd/vpmaskmovq %Mx,%Vx,%Hx",IDX_ParseModRM, IDX_UseModRM, IDX_ParseVexDest, 0, OP_VPMASKMOVD, OP_PARM_Mx, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+
+ /* 9 */
+ /* Seems incorrect format is used in the Intel opcode tables.
+ * Correct form according to Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2 (2A, 2B & 2C): Instruction Set Reference, A-Z
+ * is the following:
+ * v?gather?d/q %Vx, %Md/q, %Hx ,
+ * where d/q is defined by VEX.W bit.
+ *
+ * The instruction are in the following format:
+ * #name1/name2 format
+ * if REX.W is set name2 is used,
+ * otherwise name1.
+ */
+ OPVEX("#vpgatherdd/vpgatherdq %Vx,%My,%Hx", IDX_ParseModRM, IDX_UseModRM, IDX_ParseVexDest, 0, OP_VGATHER, OP_PARM_Vx, OP_PARM_My, OP_PARM_Hx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vpgatherqd/vpgatherqq %Vx,%My,%Hx", IDX_ParseModRM, IDX_UseModRM, IDX_ParseVexDest, 0, OP_VGATHER, OP_PARM_Vx, OP_PARM_My, OP_PARM_Hx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vgatherdps/vgatherdpd %Vx,%My,%Hx", IDX_ParseModRM, IDX_UseModRM, IDX_ParseVexDest, 0, OP_VGATHER, OP_PARM_Vx, OP_PARM_My, OP_PARM_Hx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vgatherqps/vgatherqpd %Vx,%My,%Hx", IDX_ParseModRM, IDX_UseModRM, IDX_ParseVexDest, 0, OP_VGATHER, OP_PARM_Vx, OP_PARM_My, OP_PARM_Hx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("#vfmaddsub132ps/vfmaddsub132pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADDSUB132PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsubadd132ps/vfmsubadd132pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUBADD132PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmadd132ps/vfmadd132pd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADD132PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmadd132ss/vfmadd132sd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADD132SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsub132ps/vfmsub132pd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUB132PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsub132ss/vfmsub132sd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUB132SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmadd132ps/vfnmadd132pd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMADD132PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmadd132ss/vfnmadd132sd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMADD132SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmsub132ps/vfnmsub132pd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMSUB132PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmsub132ss/vfnmsub132sd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMSUB132SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* a */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("#vfmaddsub213ps/vfmaddsub213pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADDSUB213PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsubadd213ps/vfmsubadd213pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUBADD213PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmadd213ps/vfmadd213pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADD213PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmadd213ss/vfmadd213sd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADD213SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsub213ps/vfmsub213pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUB213PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsub213ss/vfmsub213sd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUB213SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmadd213ps/vfnmadd213pd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMADD213PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmadd213ss/vfnmadd213sd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMADD213SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmsub213ps/vfnmsub213pd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMSUB213PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmsub213ss/vfnmsub213sd %Vx,%Hx,%Wx",IDX_ParseModRM,IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMSUB213SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* b */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("#vfmaddsub231ps/vfmaddsub231pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADDSUB231PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsubadd231ps/vfmsubadd231pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUBADD231PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmadd231ps/vfmadd231pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADD231PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmadd231ss/vfmadd231sd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMADD231SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsub231ps/vfmsub231pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUB231PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfmsub231ss/vfmsub231sd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFMSUB231SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmadd231ps/vfnmadd231pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMADD231PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmadd231ss/vfnmadd231sd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMADD231SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmsub231ps/vfnmsub231pd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMSUB231PS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vfnmsub231ss/vfnmsub231sd %Vx,%Hx,%Wx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VFNMSUB231SS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* c */
+ INVALID_OPCODE_BLOCK
+
+ /* d */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vaesimc %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, 0, OP_VAESIMC, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vaesenc %Vdq,%Hdq,%Wdq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VAESENC, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vaesenclast %Vdq,%Hdq,%Wdq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VAESENCLAST, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vaesdec %Vdq,%Hdq,%Wdq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VAESDEC, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vaesdeclast %Vdq,%Hdq,%Wdq", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_VAESDECLAST, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wdq, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* e */
+ INVALID_OPCODE_BLOCK
+
+ /* f */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("shlx %Gy,%By,%Ey", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, 0, OP_SHLX, OP_PARM_Gy, OP_PARM_By, OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+};
+const DISOPMAPDESC g_DisasVexMap2_66Range = { &g_aDisasVexMap2_66[0], 0x00, RT_ELEMENTS(g_aDisasVexMap2_66) };
+
+const DISOPCODE g_aDisasVexMap3[] =
+{
+ INVALID_OPCODE, /* dummy */
+};
+const DISOPMAPDESC g_DisasVexMap3Range = { &g_aDisasVexMap3[0], 0, RT_ELEMENTS(g_aDisasVexMap3) };
+
+static const DISOPCODE g_aDisasVexMap3_66[] =
+{
+ /* 0 format string, parse param #1, parse param #2, parse param #3, parse param #4, opcode, param #1, param #2, param #3, param #4, flags */
+ OPVEX("vpermq %Vqq,%Wqq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPERMQ, OP_PARM_Vqq, OP_PARM_Wqq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpermpd %Vqq,%Wqq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPERMPD, OP_PARM_Vqq, OP_PARM_Wqq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpblendd %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPBLENDD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vpermilps %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPERMILPS, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpermilpd %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPERMILPD, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vperm2f128 %Vqq,%Hqq,%Wqq,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPERM2F128, OP_PARM_Vqq, OP_PARM_Hqq, OP_PARM_Wqq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vroundps %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VROUNDPS, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vroundpd %Vx,%Wx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VROUNDPD, OP_PARM_Vx, OP_PARM_Wx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vroundss %Vss,%Wss,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VROUNDSS, OP_PARM_Vss, OP_PARM_Wss, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vroundsd %Vsd,%Wsd,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VROUNDSD, OP_PARM_Vsd, OP_PARM_Wsd, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vblendps %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VBLENDPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vblendpd %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VBLENDPD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vpblendw %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPBLENDW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vpalignr %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPALIGNR, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+
+ /* 1 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ // vpextrb %Rd/Mb,%Vdq,%Ib
+ OPVEX("vpextrb %Eb,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPEXTRB, OP_PARM_Eb, OP_PARM_Vdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ // vpextrw %Rd/Mw,%Vdq,%Ib
+ OPVEX("vpextrw %Ew,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPEXTRW, OP_PARM_Ew, OP_PARM_Vdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("#vpextrd/vpextrq %Ey,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPEXTRD, OP_PARM_Ey, OP_PARM_Vdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vextractps %Ed,%Vdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VEXTRACTPS, OP_PARM_Ed, OP_PARM_Vdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vinsertf128 %Vqq,%Hqq,%Wqq,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VINSERTF128, OP_PARM_Vqq, OP_PARM_Hqq, OP_PARM_Wqq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vextractf128 %Wdq,%Vqq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VEXTRACTF128, OP_PARM_Eb, OP_PARM_Vdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vcvtps2ph %Wx,%Vx,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VCVTPS2PH, OP_PARM_Wx, OP_PARM_Vx, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ // vpinsrb %Vdq,%Hdq,%Ry/Mb,%Ib
+ OPVEX("vpinsrb %Vdq,%Hdq,%Eb,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPINSRB, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Eb, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ // vinsertps %Vdq,%Hdq,%Udq/Md,%Ib
+ OPVEX("vinsertps %Vdq,%Hdq,%Wd,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VINSERTPS, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wd, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("#vpinsrd/vpinsrq %Vdq,%Hdq,%Ey,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPINSRD, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Ey, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 3 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vinserti128 %Vqq,%Hqq,%Wqq,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VINSERTI128, OP_PARM_Vqq, OP_PARM_Hqq, OP_PARM_Wqq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vextracti128 %Wdq,%Vqq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VEXTRACTI128, OP_PARM_Wdq, OP_PARM_Vqq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 4 */
+ OPVEX("vdpps %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VDPPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vdppd %Vdq,%Hdq,%Wdq,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VDPPD, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OPVEX("vmpsadbw %Vx,%Hx,%Wx,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VMPSADBW, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vpclmulqdq %Vdq,%Hdq,%Wdq,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPCLMULQDQ, OP_PARM_Vdq, OP_PARM_Hdq, OP_PARM_Wdq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OPVEX("vperm2i128 %Vqq,%Hqq,%Wqq,%Ib", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPERM2I128, OP_PARM_Vqq, OP_PARM_Hqq, OP_PARM_Wqq, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vblendvps %Vx,%Hx,%Wx,%Lx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VBLENDVPS, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Lx, DISOPTYPE_HARMLESS),
+ OPVEX("vblendvpd %Vx,%Hx,%Wx,%Lx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VBLENDVPD, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Lx, DISOPTYPE_HARMLESS),
+ OPVEX("vpblendvb %Vx,%Hx,%Wx,%Lx", IDX_ParseModRM, IDX_ParseVexDest, IDX_UseModRM, IDX_ParseImmByte, OP_VPBLENDVB, OP_PARM_Vx, OP_PARM_Hx, OP_PARM_Wx, OP_PARM_Lx, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 5 */
+ INVALID_OPCODE_BLOCK
+
+ /* 6 */
+ OPVEX("vpcmpestrm %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPCMPESTRM, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpestri %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPCMPESTRI, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpistrm %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPCMPISTRM, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OPVEX("vpcmpistri %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VPCMPISTRI, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 7 */
+ INVALID_OPCODE_BLOCK
+
+ /* 8 */
+ INVALID_OPCODE_BLOCK
+
+ /* 9 */
+ INVALID_OPCODE_BLOCK
+
+ /* a */
+ INVALID_OPCODE_BLOCK
+
+ /* b */
+ INVALID_OPCODE_BLOCK
+
+ /* c */
+ INVALID_OPCODE_BLOCK
+
+ /* d */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OPVEX("vaeskeygen %Vdq,%Wdq,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_VAESKEYGEN, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+const DISOPMAPDESC g_DisasVexMap3_66Range = { &g_aDisasVexMap3_66[0], 0x00, RT_ELEMENTS(g_aDisasVexMap3_66) };
+
+const DISOPCODE g_aDisasVexMap3F2[] =
+{
+ OPVEX("rorx %Gy,%Ey,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByte, 0, OP_RORX, OP_PARM_Gy, OP_PARM_Ey, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+const DISOPMAPDESC g_DisasVexMap3F2Range = { &g_aDisasVexMap3F2[0], 0xf0, RT_ELEMENTS(g_aDisasVexMap3F2) };
+
+const DISOPCODE g_aDisasVexMap3F3[] =
+{
+ INVALID_OPCODE, /* dummy */
+};
+const DISOPMAPDESC g_DisasVexMap3F3Range = { &g_aDisasVexMap3F3[0], 0, RT_ELEMENTS(g_aDisasVexMap3F3) };
+
+
+/** Invalid range for the g_aapVexOpcodesMapRanges table. */
+const DISOPMAPDESC g_DisasVexMapInvalidRange = { &g_InvalidOpcode[0], 0, 1 };
+
+
+PCDISOPMAPDESC const g_aapVexOpcodesMapRanges[4][4] =
+{
+ /* No prefix: */
+ {
+ &g_DisasVexMapInvalidRange,
+ &g_DisasVexMap1Range, // 0fh 2-byte opcodes
+ &g_DisasVexMap2Range, // 0f38h 3-byte opcodes
+ &g_DisasVexMap3Range, // 0f3ah 3-byte opcodes
+ },
+ /* 66h prefix: */
+ {
+ &g_DisasVexMapInvalidRange,
+ &g_DisasVexMap1_66Range, // 0fh 2-byte opcodes
+ &g_DisasVexMap2_66Range, // 0f38h 3-byte opcodes
+ &g_DisasVexMap3_66Range, // 0f3ah 3-byte opcodes
+ },
+ /* f3h prefix: */
+ {
+ &g_DisasVexMapInvalidRange,
+ &g_DisasVexMap1F3Range, // 0fh 2-byte opcodes
+ &g_DisasVexMap2F3Range, // 0f38h 3-byte opcodes
+ &g_DisasVexMap3F3Range, // 0f3ah 3-byte opcodes
+ },
+ /* f2h prefix: */
+ {
+ &g_DisasVexMapInvalidRange,
+ &g_DisasVexMap1F2Range, // 0fh 2-byte opcodes
+ &g_DisasVexMap2F2Range, // 0f38h 3-byte opcodes2
+ &g_DisasVexMap3F2Range, // 0f3ah 3-byte opcodes
+ }
+};
+
diff --git a/src/VBox/Disassembler/DisasmTablesX64.cpp b/src/VBox/Disassembler/DisasmTablesX64.cpp
new file mode 100644
index 00000000..05de6d0b
--- /dev/null
+++ b/src/VBox/Disassembler/DisasmTablesX64.cpp
@@ -0,0 +1,369 @@
+/* $Id: DisasmTablesX64.cpp $ */
+/** @file
+ * VBox disassembler - Tables for AMD64 (64-bit mode).
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include "DisasmInternal.h"
+
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+/// @todo Verify tables for correctness
+/// @todo opcode type (harmless, potentially dangerous, dangerous)
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+#ifndef DIS_CORE_ONLY
+static char g_szInvalidOpcode[] = "Invalid Opcode";
+#endif
+
+#define INVALID_OPCODE \
+ OP(g_szInvalidOpcode, 0, 0, 0, OP_INVALID, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INVALID)
+
+#define INVALID_OPCODE_BLOCK \
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,\
+ INVALID_OPCODE,
+
+/* Tables for the elegant Intel X64 instruction set */
+
+const DISOPCODE g_aOneByteMapX64[256] =
+{
+ /* 0 */
+ OP("add %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Eb, OP_PARM_Gb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Ev, OP_PARM_Gv , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Gb, OP_PARM_Eb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADD, OP_PARM_Gv, OP_PARM_Ev , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_ADD, OP_PARM_REG_AL, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("add %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_ADD, OP_PARM_REG_EAX, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("or %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Eb, OP_PARM_Gb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Ev, OP_PARM_Gv , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Gb, OP_PARM_Eb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_OR, OP_PARM_Gv, OP_PARM_Ev , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_OR, OP_PARM_REG_AL, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("or %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_OR, OP_PARM_REG_EAX, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("2-BYTE ESCAPE", IDX_ParseTwoByteEsc,0, 0, OP_2B_ESC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 1 */
+ OP("adc %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Eb, OP_PARM_Gb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Ev, OP_PARM_Gv , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Gb, OP_PARM_Eb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_ADC, OP_PARM_Gv, OP_PARM_Ev , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_ADC, OP_PARM_REG_AL, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("adc %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_ADC, OP_PARM_REG_EAX, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("sbb %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Eb, OP_PARM_Gb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Ev, OP_PARM_Gv , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Gb, OP_PARM_Eb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_SBB, OP_PARM_Gv, OP_PARM_Ev , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_SBB, OP_PARM_REG_AL, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sbb %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_SBB, OP_PARM_REG_EAX, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+
+ /* 2 */
+ OP("and %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Eb, OP_PARM_Gb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Ev, OP_PARM_Gv , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Gb, OP_PARM_Eb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_AND, OP_PARM_Gv, OP_PARM_Ev , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_AND, OP_PARM_REG_AL, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("and %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_AND, OP_PARM_REG_EAX, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG ES", 0, 0, 0, OP_SEG, OP_PARM_REG_ES, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("sub %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Eb, OP_PARM_Gb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Ev, OP_PARM_Gv , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Gb, OP_PARM_Eb , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_SUB, OP_PARM_Gv, OP_PARM_Ev , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_SUB, OP_PARM_REG_AL, OP_PARM_Ib , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("sub %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_SUB, OP_PARM_REG_EAX, OP_PARM_Iz , OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* Branch not taken hint prefix for branches on a Pentium 4 or Xeon CPU (or higher)! */
+ OP("SEG CS", 0, 0, 0, OP_SEG, OP_PARM_REG_CS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+
+ /* 3 */
+ OP("xor %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_XOR, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_XOR, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xor %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_XOR, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG SS", 0, 0, 0, OP_SEG, OP_PARM_REG_SS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("cmp %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_CMP, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte,0, OP_CMP, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmp %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_CMP, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /* Branch not taken hint prefix for branches on a Pentium 4 or Xeon CPU (or higher)! */
+ OP("SEG DS", 0, 0, 0, OP_SEG, OP_PARM_REG_DS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+
+ /* 4 */
+ OP("REX", 0, 0, 0, OP_REX, OP_PARM_REX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.B", 0, 0, 0, OP_REX, OP_PARM_REX_B, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.X", 0, 0, 0, OP_REX, OP_PARM_REX_X, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.XB", 0, 0, 0, OP_REX, OP_PARM_REX_XB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.R", 0, 0, 0, OP_REX, OP_PARM_REX_R, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.RB", 0, 0, 0, OP_REX, OP_PARM_REX_RB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.RX", 0, 0, 0, OP_REX, OP_PARM_REX_RX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.RXB", 0, 0, 0, OP_REX, OP_PARM_REX_RXB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.W", 0, 0, 0, OP_REX, OP_PARM_REX_W, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WB", 0, 0, 0, OP_REX, OP_PARM_REX_WB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WX", 0, 0, 0, OP_REX, OP_PARM_REX_WX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WXB", 0, 0, 0, OP_REX, OP_PARM_REX_WXB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WR", 0, 0, 0, OP_REX, OP_PARM_REX_WR, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WRB", 0, 0, 0, OP_REX, OP_PARM_REX_WRB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WRX", 0, 0, 0, OP_REX, OP_PARM_REX_WRX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("REX.WRXB", 0, 0, 0, OP_REX, OP_PARM_REX_WRXB, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 5 */
+ OP("push %eAX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eCX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eDX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eBX", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eSP", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eBP", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eSI", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("push %eDI", IDX_ParseFixedReg, 0, 0, OP_PUSH, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eAX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EAX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eCX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ECX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eDX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EDX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eBX", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EBX, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eSP", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ESP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eBP", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EBP, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eSI", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_ESI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("pop %eDI", IDX_ParseFixedReg, 0, 0, OP_POP, OP_PARM_REG_EDI, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE | DISOPTYPE_REXB_EXTENDS_OPREG),
+
+ /* 6 */
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ OP("movsxd %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOVSXD, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG FS", 0, 0, 0, OP_SEG, OP_PARM_REG_FS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("SEG GS", 0, 0, 0, OP_SEG, OP_PARM_REG_GS, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("OP SIZE", 0, 0, 0, OP_OPSIZE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("ADDR SIZE", 0, 0, 0, OP_ADDRSIZE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("push %Iz", IDX_ParseImmZ, 0, 0, OP_PUSH, OP_PARM_Iz, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("imul %Gv,%Ev,%Iz", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmZ, OP_IMUL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_Iz, DISOPTYPE_HARMLESS),
+ OP("push %Ib", IDX_ParseImmByteSX, 0, 0, OP_PUSH, OP_PARM_Ib, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("imul %Gv,%Ev,%Ib", IDX_ParseModRM, IDX_UseModRM, IDX_ParseImmByteSX, OP_IMUL, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_Ib, DISOPTYPE_HARMLESS),
+ OP("insb %Yb,DX", IDX_ParseYb, IDX_ParseFixedReg, 0, OP_INSB, OP_PARM_Yb, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("insw/d %Yv,DX", IDX_ParseYv, IDX_ParseFixedReg, 0, OP_INSWD, OP_PARM_Yv, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("outsb DX,%Xb", IDX_ParseFixedReg, IDX_ParseXb, 0, OP_OUTSB, OP_PARM_REG_DX, OP_PARM_Yb, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("outsw/d DX,%Xv", IDX_ParseFixedReg, IDX_ParseXv, 0, OP_OUTSWD, OP_PARM_REG_DX, OP_PARM_Yv, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+
+
+ /* 7 */
+ OP("jo %Jb", IDX_ParseImmBRel, 0, 0, OP_JO, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jno %Jb", IDX_ParseImmBRel, 0, 0, OP_JNO, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jc %Jb", IDX_ParseImmBRel, 0, 0, OP_JC, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnc %Jb", IDX_ParseImmBRel, 0, 0, OP_JNC, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("je %Jb", IDX_ParseImmBRel, 0, 0, OP_JE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jne %Jb", IDX_ParseImmBRel, 0, 0, OP_JNE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jbe %Jb", IDX_ParseImmBRel, 0, 0, OP_JBE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnbe %Jb", IDX_ParseImmBRel, 0, 0, OP_JNBE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("js %Jb", IDX_ParseImmBRel, 0, 0, OP_JS, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jns %Jb", IDX_ParseImmBRel, 0, 0, OP_JNS, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jp %Jb", IDX_ParseImmBRel, 0, 0, OP_JP, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnp %Jb", IDX_ParseImmBRel, 0, 0, OP_JNP, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jl %Jb", IDX_ParseImmBRel, 0, 0, OP_JL, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnl %Jb", IDX_ParseImmBRel, 0, 0, OP_JNL, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jle %Jb", IDX_ParseImmBRel, 0, 0, OP_JLE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jnle %Jb", IDX_ParseImmBRel, 0, 0, OP_JNLE, OP_PARM_Jb , OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+
+ /* 8 */
+ OP("Imm Grp1 %Eb,%Ib", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Imm Grp1 %Ev,%Iz", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Ev, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("Imm Grp1 %Ev,%Ib", IDX_ParseGrp1, 0, 0, OP_IMM_GRP1,OP_PARM_Ev, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_TEST, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_TEST, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xchg %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_XCHG, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("xchg %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_XCHG, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Eb,%Gb", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Eb, OP_PARM_Gb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ev,%Gv", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Gv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Gb,%Eb", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Gb, OP_PARM_Eb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Gv,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Gv, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ev,%Sw", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Sw, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS),
+ OP("lea %Gv,%M", IDX_ParseModRM, IDX_UseModRM, 0, OP_LEA, OP_PARM_Gv, OP_PARM_M, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Sw,%Ev", IDX_ParseModRM, IDX_UseModRM, 0, OP_MOV, OP_PARM_Sw, OP_PARM_Ev, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS | DISOPTYPE_INHIBIT_IRQS),
+ /** @todo this is grp 1a, actually */
+ OP("pop %Ev", IDX_ParseModRM, 0, 0, OP_POP, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+ /* 9 */
+ OP("nop/pause/xchg %eAX,%eAX", IDX_ParseNopPause, 0, 0, OP_NOP, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eCX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_ECX, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eDX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EDX, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eBX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EBX, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eSP,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_ESP, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eBP,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EBP, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eSI,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_ESI, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("xchg %eDI,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_XCHG, OP_PARM_REG_EDI, OP_PARM_REG_EAX, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("cbw", 0, 0, 0, OP_CBW, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cwd", 0, 0, 0, OP_CWD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ OP("wait", 0, 0, 0, OP_WAIT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("pushf %Fv", 0, 0, 0, OP_PUSHF, OP_PARM_Fv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("popf %Fv", 0, 0, 0, OP_POPF, OP_PARM_Fv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_POTENTIALLY_DANGEROUS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("sahf", 0, 0, 0, OP_SAHF, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lahf", 0, 0, 0, OP_LAHF, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* A */
+ OP("mov AL,%Ob", IDX_ParseFixedReg, IDX_ParseImmAddr, 0, OP_MOV, OP_PARM_REG_AL, OP_PARM_Ob, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %eAX,%Ov", IDX_ParseFixedReg, IDX_ParseImmAddr, 0, OP_MOV, OP_PARM_REG_EAX, OP_PARM_Ov, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ob,AL", IDX_ParseImmAddr, IDX_ParseFixedReg, 0, OP_MOV, OP_PARM_Ob, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ov,%eAX", IDX_ParseImmAddr, IDX_ParseFixedReg, 0, OP_MOV, OP_PARM_Ov, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsb %Xb,%Yb", IDX_ParseXb, IDX_ParseYb, 0, OP_MOVSB, OP_PARM_Xb, OP_PARM_Yb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("movsw/d %Xv,%Yv", IDX_ParseXv, IDX_ParseYv, 0, OP_MOVSWD, OP_PARM_Xv, OP_PARM_Yv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmpsb %Xb,%Yb", IDX_ParseXb, IDX_ParseYb, 0, OP_CMPSB, OP_PARM_Xb, OP_PARM_Yb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cmpsw/d %Xv,%Yv", IDX_ParseXv, IDX_ParseYv, 0, OP_CMPWD, OP_PARM_Xv, OP_PARM_Yv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_TEST, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("test %eAX,%Iz", IDX_ParseFixedReg, IDX_ParseImmZ, 0, OP_TEST, OP_PARM_REG_EAX, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stosb %Yb,AL", IDX_ParseYb, IDX_ParseFixedReg, 0, OP_STOSB, OP_PARM_Yb, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stosw/d %Yv,%eAX", IDX_ParseYv, IDX_ParseFixedReg, 0, OP_STOSWD, OP_PARM_Yv, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lodsb AL,%Xb", IDX_ParseFixedReg, IDX_ParseXb, 0, OP_LODSB, OP_PARM_REG_AL, OP_PARM_Xb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("lodsw/d %eAX,%Xv", IDX_ParseFixedReg, IDX_ParseXv, 0, OP_LODSWD, OP_PARM_REG_EAX, OP_PARM_Xv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("scasb AL,%Xb", IDX_ParseFixedReg, IDX_ParseXb, 0, OP_SCASB, OP_PARM_REG_AL, OP_PARM_Xb, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("scasw/d %eAX,%Xv", IDX_ParseFixedReg, IDX_ParseXv, 0, OP_SCASWD, OP_PARM_REG_EAX, OP_PARM_Xv, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* B */
+ OP("mov %eAL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eCL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_CL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eDL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_DL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eBL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_BL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eAH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_AH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eCH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_CH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eDH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_DH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eBH,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_REG_BH, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eAX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EAX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eCX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_ECX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eDX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EDX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eBX,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EBX, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eSP,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_ESP, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eBP,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EBP, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eSI,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_ESI, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+ OP("mov %eDI,%Iv", IDX_ParseFixedReg, IDX_ParseImmV, 0, OP_MOV, OP_PARM_REG_EDI, OP_PARM_Iv, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_REXB_EXTENDS_OPREG),
+
+ /* C */
+ OP("Shift Grp2 %Eb,%Ib", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Ev,%Ib", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Ev, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("retn %Iw", IDX_ParseImmUshort, 0, 0, OP_RETN, OP_PARM_Iw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("retn", 0, 0, 0, OP_RETN, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("VEX 3-byte", IDX_ParseVex3b, 0, 0, OP_VEX3B, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("VEX 2-byte", IDX_ParseVex2b, 0, 0, OP_VEX2B, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ /** @todo these two are actually group11 */
+ OP("mov %Eb,%Ib", IDX_ParseModRM, IDX_ParseImmByte, 0, OP_MOV, OP_PARM_Eb, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("mov %Ev,%Iz", IDX_ParseModRM, IDX_ParseImmZ, 0, OP_MOV, OP_PARM_Ev, OP_PARM_Iz, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("enter %Iw,%Ib", IDX_ParseImmUshort, IDX_ParseImmByte, 0, OP_ENTER, OP_PARM_Iw, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("leave", 0, 0, 0, OP_LEAVE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_DEFAULT_64_OP_SIZE),
+ OP("retf %Iw", IDX_ParseImmUshort, 0, 0, OP_RETF, OP_PARM_Iw, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+ OP("retf", 0, 0, 0, OP_RETF, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+ OP("int 3", 0, 0, 0, OP_INT3, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT),
+ OP("int %Ib", IDX_ParseImmByte, 0, 0, OP_INT, OP_PARM_Ib, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT),
+ INVALID_OPCODE,
+ OP("iret", 0, 0, 0, OP_IRET, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW),
+
+ /* D */
+ OP("Shift Grp2 %Eb,1", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Eb, OP_PARM_1, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Ev,1", IDX_ParseShiftGrp2, 0, 0, OP_SHIFT_GRP2, OP_PARM_Ev, OP_PARM_1, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Eb,CL", IDX_ParseShiftGrp2, IDX_ParseFixedReg, 0, OP_SHIFT_GRP2, OP_PARM_Eb, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Shift Grp2 %Ev,CL", IDX_ParseShiftGrp2, IDX_ParseFixedReg, 0, OP_SHIFT_GRP2, OP_PARM_Ev, OP_PARM_REG_CL, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ INVALID_OPCODE,
+ INVALID_OPCODE,
+ /* setalc?? */
+ INVALID_OPCODE,
+ OP("xlat", 0, 0, 0, OP_XLAT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf0", IDX_ParseEscFP, 0, 0, OP_ESCF0, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf1", IDX_ParseEscFP, 0, 0, OP_ESCF1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf2", IDX_ParseEscFP, 0, 0, OP_ESCF2, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf3", IDX_ParseEscFP, 0, 0, OP_ESCF3, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf4", IDX_ParseEscFP, 0, 0, OP_ESCF4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf5", IDX_ParseEscFP, 0, 0, OP_ESCF5, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf6", IDX_ParseEscFP, 0, 0, OP_ESCF6, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("esc 0xf7", IDX_ParseEscFP, 0, 0, OP_ESCF7, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+
+
+ /* E */
+ OP("loopne %Jb", IDX_ParseImmBRel, 0, 0, OP_LOOPNE, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("loope %Jb", IDX_ParseImmBRel, 0, 0, OP_LOOPE, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("loop %Jb", IDX_ParseImmBRel, 0, 0, OP_LOOP, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("j(e)cxz %Jb", IDX_ParseImmBRel, 0, 0, OP_JECXZ, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW|DISOPTYPE_RELATIVE_CONTROLFLOW|DISOPTYPE_COND_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("in AL,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_IN, OP_PARM_REG_AL, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("in %eAX,%Ib", IDX_ParseFixedReg, IDX_ParseImmByte, 0, OP_IN, OP_PARM_REG_EAX, OP_PARM_Ib, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("out %Ib,AL", IDX_ParseImmByte, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_Ib, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("out %Ib,%eAX", IDX_ParseImmByte, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_Ib, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("call %Jv", IDX_ParseImmVRel, 0, 0, OP_CALL, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("jmp %Jv", IDX_ParseImmVRel, 0, 0, OP_JMP, OP_PARM_Jv, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ INVALID_OPCODE,
+ OP("jmp %Jb", IDX_ParseImmBRel, 0, 0, OP_JMP, OP_PARM_Jb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_RELATIVE_CONTROLFLOW | DISOPTYPE_FORCED_64_OP_SIZE),
+ OP("in AL,DX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_IN, OP_PARM_REG_AL, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("in %eAX,DX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_IN, OP_PARM_REG_EAX, OP_PARM_REG_DX, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_READ),
+ OP("out DX,AL", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_REG_DX, OP_PARM_REG_AL, OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+ OP("out DX,%eAX", IDX_ParseFixedReg, IDX_ParseFixedReg, 0, OP_OUT, OP_PARM_REG_DX, OP_PARM_REG_EAX,OP_PARM_NONE, DISOPTYPE_PORTIO | DISOPTYPE_PRIVILEGED | DISOPTYPE_PORTIO_WRITE),
+
+
+ /* F */
+ OP("lock", 0, 0, 0, OP_LOCK, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("icebp", 0, 0, 0, OP_INT1, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_INTERRUPT),
+ OP("repne", 0, 0, 0, OP_REPNE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("rep(e)", 0, 0, 0, OP_REPE, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("hlt", 0, 0, 0, OP_HLT, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS | DISOPTYPE_PRIVILEGED),
+ OP("cmc", 0, 0, 0, OP_CMC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Unary Grp3 %Eb", IDX_ParseGrp3, 0, 0, OP_UNARY_GRP3, OP_PARM_Eb, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Unary Grp3 %Ev", IDX_ParseGrp3, 0, 0, OP_UNARY_GRP3, OP_PARM_Ev, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("clc", 0, 0, 0, OP_CLC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("stc", 0, 0, 0, OP_STC, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("cli", 0, 0, 0, OP_CLI, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED),
+ OP("sti", 0, 0, 0, OP_STI, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_DANGEROUS | DISOPTYPE_PRIVILEGED | DISOPTYPE_INHIBIT_IRQS),
+ OP("cld", 0, 0, 0, OP_CLD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("std", 0, 0, 0, OP_STD, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("inc/dec Grp4", IDX_ParseGrp4, 0, 0, OP_INC_GRP4, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+ OP("Indirect Grp5", IDX_ParseGrp5, 0, 0, OP_IND_GRP5, OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
+};
+
diff --git a/src/VBox/Disassembler/Makefile.kmk b/src/VBox/Disassembler/Makefile.kmk
new file mode 100644
index 00000000..cdc72106
--- /dev/null
+++ b/src/VBox/Disassembler/Makefile.kmk
@@ -0,0 +1,91 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the VBox Disassembler.
+#
+
+#
+# Copyright (C) 2006-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+# include the sub-makefile first.
+if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_VALIDATIONKIT)
+ include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk
+endif
+
+
+LIBRARIES += DisasmR3
+DisasmR3_TEMPLATE = VBoxR3Dll
+DisasmR3_DEFS = IN_DIS
+DisasmR3_SOURCES = \
+ Disasm.cpp \
+ DisasmCore.cpp \
+ DisasmTables.cpp \
+ DisasmTablesX64.cpp \
+ DisasmMisc.cpp \
+ DisasmFormatBytes.cpp \
+ DisasmFormatYasm.cpp
+
+LIBRARIES += DisasmR3Static
+DisasmR3Static_TEMPLATE = VBoxR3Static
+DisasmR3Static_EXTENDS = DisasmR3
+
+ifndef VBOX_ONLY_VALIDATIONKIT
+
+ LIBRARIES += DisasmBldProg
+ DisasmBldProg_TEMPLATE = VBoxAdvBldProg
+ DisasmBldProg_EXTENDS = DisasmR3
+
+ LIBRARIES += DisasmCoreR3
+ DisasmCoreR3_TEMPLATE = VBoxR3Dll
+ DisasmCoreR3_DEFS = IN_DIS DIS_CORE_ONLY
+ DisasmCoreR3_SOURCES = \
+ DisasmCore.cpp \
+ DisasmTables.cpp \
+ DisasmTablesX64.cpp \
+ DisasmMisc.cpp
+
+ ifdef VBOX_WITH_RAW_MODE
+ LIBRARIES += DisasmRC
+ DisasmRC_TEMPLATE = VBoxRc
+ DisasmRC_DEFS = IN_DIS IN_RT_RC DIS_CORE_ONLY
+ DisasmRC_SOURCES = \
+ DisasmCore.cpp \
+ DisasmTables.cpp \
+ DisasmTablesX64.cpp \
+ DisasmMisc.cpp
+ endif # VBOX_WITH_RAW_MODE
+
+ LIBRARIES += DisasmR0
+ DisasmR0_TEMPLATE = VBoxR0
+ DisasmR0_DEFS = IN_DIS IN_RT_R0 DIS_CORE_ONLY
+ DisasmR0_SOURCES = \
+ DisasmCore.cpp \
+ DisasmTables.cpp \
+ DisasmTablesX64.cpp \
+ DisasmMisc.cpp
+
+endif # !VBOX_ONLY_VALIDATIONKIT
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Disassembler/testcase/Makefile.kmk b/src/VBox/Disassembler/testcase/Makefile.kmk
new file mode 100644
index 00000000..1f993247
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/Makefile.kmk
@@ -0,0 +1,271 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the VBox Disassembler.
+#
+
+#
+# Copyright (C) 2006-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+ifdef VBOX_WITH_TESTCASES
+
+
+ if1of ($(KBUILD_TARGET_ARCH), amd64 x86)
+ PROGRAMS += tstDisasm-1
+ tstDisasm-1_TEMPLATE = VBoxR3TstExe
+ tstDisasm-1_DEFS = IN_DIS
+ tstDisasm-1_SOURCES = \
+ tstDisasm-1.cpp \
+ tstDisasm-1A.asm
+ tstDisasm-1_LIBS = \
+ $(PATH_STAGE_LIB)/DisasmR3$(VBOX_SUFF_LIB) \
+ $(LIB_RUNTIME)
+
+ PROGRAMS += tstDisasmCore-1
+ tstDisasmCore-1_EXTENDS = tstDisasm-1
+ tstDisasmCore-1_DEFS = IN_DIS DIS_CORE_ONLY
+ tstDisasmCore-1_LIBS = \
+ $(PATH_STAGE_LIB)/DisasmCoreR3$(VBOX_SUFF_LIB) \
+ $(LIB_RUNTIME)
+ endif
+
+
+ PROGRAMS += tstDisasm-2
+ tstDisasm-2_TEMPLATE = VBoxR3TstExe
+ tstDisasm-2_DEFS = IN_DIS
+ tstDisasm-2_SOURCES = \
+ tstDisasm-2.cpp
+ tstDisasm-2_LIBS = \
+ $(PATH_STAGE_LIB)/DisasmR3$(VBOX_SUFF_LIB) \
+ $(LIB_RUNTIME)
+
+ # Tests that will be build, disassembled and re-build from disassembly.
+ VBOX_DISAS_TESTS_BUILD = \
+ tstAsmFnstsw-1.asm \
+ tstAsmLock-1.asm \
+ tstAsmMovFixedReg-1.asm \
+ tstAsmMovSeg-1.asm \
+ tstAsmMovzx-1.asm \
+ tstAsmPop-1.asm \
+ tstAsmPush-1.asm \
+ tstAsmSignExtend-1.asm \
+ tstAsmRegs-1.asm \
+ tstAsm3DNow-1.asm
+
+ # Tests that only contains invalid/undefined instructions.
+ VBOX_DISAS_TESTS_INVALID = \
+ tstAsmLock-2.asm \
+ tstAsmLock-3.asm
+
+ # Tests that will be disassembled and re-build from disassembly (list of binaries).
+ ## @todo tstBinMovzx-1.bin: does C7 imply 32-bit reg in 16-bit mode, or what exactly does it do?
+ VBOX_DISAS_TESTS_BINARIES := \
+ tstBinMovzx-1.bin \
+ tstBinFnstsw-1.bin
+ ifeq ($(USER)x,bird)
+ VBOX_DISAS_TESTS_BINARIES += \
+ tstBin-1.bin \
+ tstBin-2.bin \
+ tstBin-3.bin \
+ tstBin-4.bin \
+ tstBin-5.bin \
+ tstBin-6.bin
+ # $(PATH_STAGE_BIN)/testcase/tstDisasm-2$(SUFF_EXEC)
+ endif
+ VBOX_DISAS_TESTS_BINARIES_NOT_16BIT := \
+ tstBinFnstsw-1.bin
+ VBOX_DISAS_TESTS_BINARIES_NOT_32BIT :=
+ VBOX_DISAS_TESTS_BINARIES_NOT_64BIT :=
+
+
+ #
+ # The gory bits...
+ #
+
+ # Where we put the output files from the testcases.
+ VBOX_DISAS_TEST_OUT_DIR := $(PATH_TARGET)/Disassembler/testcase
+ BLDDIRS += $(VBOX_DISAS_TEST_OUT_DIR)
+
+ # Generate the rules for creating the .bin files.
+ VBOX_DISAS_TESTS_BIN = $(VBOX_DISAS_TESTS_BUILD) $(VBOX_DISAS_TESTS_INVALID)
+ VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, \
+ $(VBOX_DISAS_TESTS_BIN:.asm=-16.bin) \
+ $(VBOX_DISAS_TESTS_BIN:.asm=-32.bin) \
+ $(VBOX_DISAS_TESTS_BIN:.asm=-64.bin))
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BIN:.asm=-16.bin)): $(PATH_SUB_CURRENT)/$$(patsubst %-16.bin,%.asm,$$(notdir $$(@))) | $$(dir $$@)
+ @$(ECHO) "Assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=16 -o $@ $<
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BIN:.asm=-32.bin)): $(PATH_SUB_CURRENT)/$$(patsubst %-32.bin,%.asm,$$(notdir $$(@))) | $$(dir $$@)
+ @$(ECHO) "Assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=32 -o $@ $<
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BIN:.asm=-64.bin)): $(PATH_SUB_CURRENT)/$$(patsubst %-64.bin,%.asm,$$(notdir $$(@))) | $$(dir $$@)
+ @$(ECHO) "Assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=64 -o $@ $<
+
+
+ # Generate the rules for the 'build' tests.
+ VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.asm) \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.asm) \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.asm))
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.asm)): $$(subst -disas.asm,.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "Generating: $(@F) from $(<F)"
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -o $@ -- $(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=16 $<
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.asm)): $$(subst -disas.asm,.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "Generating: $(@F) from $(<F)"
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -o $@ -- $(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=32 $<
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.asm)): $$(subst -disas.asm,.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "Generating: $(@F) from $(<F)"
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -o $@ -- $(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=64 $<
+
+
+ VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.bin) \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.bin) \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.bin))
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-16-disas.bin)): $$(subst .bin,.asm,$$@) | $$(dir $$@)
+ @$(ECHO) "Re-assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=16 -o $@ $<
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-32-disas.bin)): $$(subst .bin,.asm,$$@) | $$(dir $$@)
+ @$(ECHO) "Re-assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=32 -o $@ $<
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_BUILD:.asm=-64-disas.bin)): $$(subst .bin,.asm,$$@) | $$(dir $$@)
+ @$(ECHO) "Re-assembling: $(<F) into $(@F)"
+ $(TOOL_YASM_AS) -f bin -a x86 --force-strict -DTEST_BITS=64 -o $@ $<
+
+
+ VBOX_DISAS_TESTS += $(foreach test, $(VBOX_DISAS_TESTS_BUILD:.asm=), $(test)-16.tst $(test)-32.tst $(test)-64.tst)
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-16.tst) \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-32.tst) \
+ $(VBOX_DISAS_TESTS_BUILD:.asm=-64.tst) ): $$(subst .tst,-disas.bin,$$@) | $$(dir $$@)
+ @$(ECHO) "Verifying build: $(<F) and $(@F:.tst=.bin)"
+ @$(RM) -f $@
+ $(CMP) $(@:.tst=.bin) $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(<F) [re-assembled]"
+
+
+
+ # Generate the rules for the 'invalid' tests.
+ VBOX_DISAS_TESTS += $(foreach test, $(VBOX_DISAS_TESTS_INVALID:.asm=), $(test)-16.tst $(test)-32.tst $(test)-64.tst)
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_INVALID:.asm=-16.tst)): $$(patsubst %.tst,%.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "TESTING: $(@F) [--undef-op=all]"
+ @$(RM) -f $@
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -- $(tstDisasm-2_1_STAGE_TARGET) --undef-op=all --cpumode=16 $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(@F) [--undef-op=all]"
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_INVALID:.asm=-32.tst)): $$(patsubst %.tst,%.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "TESTING: $(@F) [--undef-op=all]"
+ @$(RM) -f $@
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -- $(tstDisasm-2_1_STAGE_TARGET) --undef-op=all --cpumode=32 $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(@F) [--undef-op=all]"
+
+ $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS_INVALID:.asm=-64.tst)): $$(patsubst %.tst,%.bin,$$@) $$(tstDisasm-2_1_STAGE_TARGET) | $$(dir $$@)
+ @$(ECHO) "TESTING: $(@F) [--undef-op=all]"
+ @$(RM) -f $@
+ $(REDIRECT) -E VBOX_LOG_DEST=nofile -- $(tstDisasm-2_1_STAGE_TARGET) --undef-op=all --cpumode=64 $<
+ @$(APPEND) $@ "done"
+ @$(ECHO) " PASSED: $(@F) [--undef-op=all]"
+
+
+ # Generate the rules for the binary tests.
+ define def_vbox_disas_binary_rules
+ $(outbase).asm: $(full_binary) $$$$(tstDisasm-2_1_STAGE_TARGET) | $(VBOX_DISAS_TEST_OUT_DIR)/
+ @$$(ECHO) "Generating: $$(@F) from $$(<F)"
+ $$(REDIRECT) -E VBOX_LOG_DEST=nofile -o $$@ -- $$(tstDisasm-2_1_STAGE_TARGET) --style=yasm --cpumode=$(bits) --undef-op=db $$<
+
+ $(outbase).bin + $(outbase).lst: $(outbase).asm
+ @$$(ECHO) "Re-assembling: $$(<F) into $$(@F)"
+ $$(TOOL_YASM_AS) -f bin -a x86 --force-strict -l $(outbase).lst -o $$@ $$<
+
+ $(outbase).tst: $(outbase).bin
+ @$$(ECHO) "Verifying build: $$(<F) against $(not-dir $(full_binary))"
+ @$$(RM) -f $$@
+ $$(CMP) -l $(full_binary) $$<
+ @$$(APPEND) $$@ "done"
+ @$$(ECHO) " PASSED: $$(<F) [binary]"
+
+ $(name).tst:: $(outbase).tst
+ VBOX_DISAS_TEST_CLEAN += $(outbase).tst $(outbase).bin $(outbase).asm
+ VBOX_DISAS_TESTS += $(name)-rebuild-$(bits).tst
+ endef # def_vbox_disas_binary_rules
+
+ define def_vbox_disas_binary
+ local name := $(notdir $(basename $(binary)))
+ local full_binary := $(abspathex $(binary),$(PATH_SUB_CURRENT))
+ local outbase := $(VBOX_DISAS_TEST_OUT_DIR)/$(name)-rebuild-$(bits)
+ $(eval $(def_vbox_disas_binary_rules))
+ endef # def_vbox_disas_binary
+
+ ## @todo 64-bit is problematic because of bugs like POP RDI ending up as POP EDI (incorrect default opmode).
+ #$(foreach bits, 64, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary)))
+ $(foreach bits, 32 16, $(foreach binary, $(filter-out $(VBOX_DISAS_TESTS_BINARIES_NOT_$(bits)BIT), $(VBOX_DISAS_TESTS_BINARIES)) \
+ , $(evalvalctx def_vbox_disas_binary)))
+
+
+ # Add the .tst to the clean up.
+ VBOX_DISAS_TEST_CLEAN += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/, $(VBOX_DISAS_TESTS))
+ OTHER_CLEAN += $(VBOX_DISAS_TEST_CLEAN)
+
+
+ #
+ # Add the tests to the target list for the testing pass.
+ # (kBuild r1646)
+ #
+ TESTING += $(addprefix $(VBOX_DISAS_TEST_OUT_DIR)/,$(VBOX_DISAS_TESTS))
+
+
+ #
+ # The test aliases
+ #
+ # To run the tstAsmLock-3.asm test: kmk tstAsmLock-3.tst
+ # To run the 64-bit tstAsmLock-3.asm test: kmk tstAsmLock-3-64.tst
+ #
+ define def_vbox_test_aliases
+ local test_base := $(basename $(test))
+ local test_root := $(patsubst %-16,%,$(patsubst %-32,%,$(patsubst %-64,%,$(test_base))))
+ $(test_base).tst:: $(VBOX_DISAS_TEST_OUT_DIR)/$(test)
+ $(test_root).tst:: $(test_base).tst
+ $(test_base).o:: $(test_base).tst
+ $(test_base).obj:: $(test_base).tst
+ $(test_root).o:: $(test_root).tst
+ $(test_root).obj:: $(test_root).tst
+ endef
+ $(foreach test,$(VBOX_DISAS_TESTS),$(evalvalctx def_vbox_test_aliases))
+
+endif # VBOX_WITH_TESTCASES
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Disassembler/testcase/tstAsm.mac b/src/VBox/Disassembler/testcase/tstAsm.mac
new file mode 100644
index 00000000..32491bc1
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsm.mac
@@ -0,0 +1,68 @@
+; $Id: tstAsm.mac $
+;; @file
+; Disassembly testcase - Common header for the xREG macros.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%if TEST_BITS == 64
+ %define xCB 8
+ %define xSP rsp
+ %define xBP rbp
+ %define xAX rax
+ %define xBX rbx
+ %define xCX rcx
+ %define xDX rdx
+ %define xDI rdi
+ %define xSI rsi
+%endif
+%if TEST_BITS == 32
+ %define xCB 4
+ %define xSP esp
+ %define xBP ebp
+ %define xAX eax
+ %define xBX ebx
+ %define xCX ecx
+ %define xDX edx
+ %define xDI edi
+ %define xSI esi
+%endif
+%if TEST_BITS == 16
+ %define xCB 2
+ %define xSP sp
+ %define xBP bp
+ %define xAX ax
+ %define xBX bx
+ %define xCX cx
+ %define xDX dx
+ %define xDI di
+ %define xSI si
+%endif
+%ifndef xCB
+ %error "TEST_BITS is missing or wrong."
+%endif
+
+%if __YASM_VERSION_ID__ >= 001020001h ; v1.2.0.1 and greater, make sure to exclude v1.2.0.0.
+ %define pmulhrwa pmulhrw
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm b/src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm
new file mode 100644
index 00000000..bd188e41
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsm3DNow-1.asm
@@ -0,0 +1,91 @@
+; $Id: tstAsm3DNow-1.asm $
+;; @file
+; Disassembly testcase - 3DNow!
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+
+ BITS TEST_BITS
+
+ pavgusb mm1, mm0
+ pf2id mm5, mm4
+ pf2iw mm6, mm3
+ pfacc mm7, mm2
+ pfadd mm5, mm4
+ pfcmpeq mm6, mm3
+ pfcmpge mm2, mm7
+ pfcmpgt mm4, mm5
+ pfmax mm3, mm6
+ pfmin mm1, mm0
+ pfmul mm5, mm4
+ pmulhrwa mm3, mm6
+ pfnacc mm4, mm5
+ pfpnacc mm3, mm6
+ pfrcp mm0, mm1
+ pfrcpit1 mm2, mm7
+ pfrcpit2 mm4, mm5
+ pfrsqrt mm7, mm2
+ pfrsqit1 mm1, mm0
+ pfsub mm6, mm3
+ pfsubr mm0, mm1
+ pi2fd mm7, mm2
+ pi2fw mm0, mm1
+ pswapd mm2, mm7
+
+%if TEST_BITS == 16
+ %define SIB(extra)
+ %define SIB(extra)
+%else
+ %define SIB(extra) extra
+%endif
+ pf2id mm5, qword [ds:xSI SIB(+000101010h)]
+ pf2iw mm6, qword [fs:xSI SIB(+000101010h)]
+ pfacc mm7, qword [gs:xSI SIB(+000101010h)]
+ pfadd mm5, qword [ xSI SIB(+000101010h)]
+ pfcmpeq mm6, qword [ xDI SIB(*8+000101010h)]
+ pfcmpge mm2, qword [es:xSI SIB(+000100010h)]
+ pfcmpgt mm4, qword [es:xSI SIB(+000101010h)]
+ pfmax mm3, qword [es:xSI SIB(+000101010h)]
+ pfmin mm1, qword [es:xSI SIB(+000101010h)]
+ pfmul mm5, qword [es:xSI SIB(+000101000h)]
+ pfrcpit1 mm2, qword [es:xBP SIB(+000101510h)]
+%if TEST_BITS != 16
+ pavgusb mm1, qword [es:xAX SIB(+000000010h)]
+ pfpnacc mm3, qword [es:xDX SIB(+000102900h)]
+ pfrcp mm0, qword [es:xCX SIB(+000101020h)]
+ pmulhrwa mm3, qword [es:xAX SIB(+0ffffffffh)]
+ pfrcpit2 mm4, qword [es:xSP SIB(+000101310h)]
+%endif
+ pfnacc mm4, qword [es:xBX SIB(+000101010h)]
+ pfrsqrt mm7, qword [es:xSI SIB(+0f0106010h)]
+ pfrsqit1 mm1, qword [es:xDI SIB(+0001f1010h)]
+ pfsub mm6, qword [es:xSI SIB(*2)]
+ pfsubr mm0, qword [es:xSI SIB(*3)]
+ pi2fd mm7, qword [es:xSI SIB(*4)]
+ pi2fw mm0, qword [es:xSI SIB(*5)]
+ pswapd mm2, qword [es:xSI SIB(*8)]
+
+ pmulhrwa mm0, qword [ds:xBP SIB(+xDI*8+00f000001h)]
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm b/src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm
new file mode 100644
index 00000000..d9899823
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmFnstsw-1.asm
@@ -0,0 +1,41 @@
+; $Id: tstAsmFnstsw-1.asm $
+;; @file
+; Disassembly testcase - Valid fnstsw* instructitons.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+ BITS TEST_BITS
+
+ fstsw ax
+ fnstsw ax
+ fstsw [xBX]
+ fnstsw [xBX]
+ fstsw [xBX+xDI]
+ fnstsw [xBX+xDI]
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmLock-1.asm b/src/VBox/Disassembler/testcase/tstAsmLock-1.asm
new file mode 100644
index 00000000..f9a0b618
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmLock-1.asm
@@ -0,0 +1,685 @@
+; $Id: tstAsmLock-1.asm $
+;; @file
+; Disassembly testcase - Valid lock sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+%if TEST_BITS == 64
+
+; The disassembler doesn't do imm32 right for 64-bit stuff, so disable it for now.
+; %define WITH_64_BIT_TESTS_IMM32
+
+; The cmpxchg16b/8b stuff isn't handled correctly in 64-bit mode. In the 8b case
+; it could be both yasm and the vbox disassembler. Have to check docs/gas/nasm.
+; %define WITH_64_BIT_TESTS_CMPXCHG16B
+
+; Seems there are some issues with the byte, word and dword variants of r8-15.
+; Again, this could be yasm issues too...
+; %define WITH_64_BIT_TESTS_BORKED_REGS
+
+ %define WITH_64_BIT_TESTS
+%endif
+
+ BITS TEST_BITS
+
+ ;
+ ; ADC
+ ;
+ ; 80 /2 ib ADC reg/mem8, imm8 - sans reg dst
+ lock adc byte [1000h], byte 8
+ lock adc byte [xBX], byte 8
+ lock adc byte [xDI], byte 8
+ ; 81 /2 i[wd] ADC reg/memX, immX - sans reg dst
+ lock adc word [1000h], word 090cch
+ lock adc word [xBX], word 090cch
+ lock adc word [xDI], word 090cch
+ lock adc dword [1000h], dword 0cc90cc90h
+ lock adc dword [xBX], dword 0cc90cc90h
+ lock adc dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc qword [1000h], dword 0cc90cc90h
+ lock adc qword [rbx], dword 0cc90cc90h
+ lock adc qword [rdi], dword 0cc90cc90h
+ lock adc qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /2 ib ADC reg/memX, imm8 - sans reg dst
+ lock adc word [1000h], byte 07fh
+ lock adc word [xBX], byte 07fh
+ lock adc word [xDI], byte 07fh
+ lock adc dword [1000h], byte 07fh
+ lock adc dword [xBX], byte 07fh
+ lock adc dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock adc qword [1000h], byte 07fh
+ lock adc qword [rbx], byte 07fh
+ lock adc qword [rdi], byte 07fh
+ lock adc qword [r10], byte 07fh
+%endif
+
+ ; 10 /r ADC reg/mem8, reg8 - sans reg dst
+ lock adc byte [1000h], bl
+ lock adc byte [xBX], bl
+ lock adc byte [xSI], bl
+ ; 11 /r ADC reg/memX, regX - sans reg dst
+ lock adc word [1000h], bx
+ lock adc word [xBX], bx
+ lock adc word [xSI], bx
+ lock adc dword [1000h], ebx
+ lock adc dword [xBX], ebx
+ lock adc dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock adc qword [1000h], rbx
+ lock adc qword [rbx], rbx
+ lock adc qword [rsi], rbx
+ lock adc qword [r11], rbx
+%endif
+
+ ;
+ ; ADD
+ ;
+ ; 80 /0 ib ADD reg/mem8, imm8 - sans reg dst
+ lock add byte [1000h], byte 8
+ lock add byte [xBX], byte 8
+ lock add byte [xDI], byte 8
+ ; 81 /0 i[wd] ADD reg/memX, immX - sans reg dst
+ lock add word [1000h], word 090cch
+ lock add word [xBX], word 090cch
+ lock add word [xDI], word 090cch
+ lock add dword [1000h], dword 0cc90cc90h
+ lock add dword [xBX], dword 0cc90cc90h
+ lock add dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock add qword [1000h], dword 0cc90cc90h
+ lock add qword [rbx], dword 0cc90cc90h
+ lock add qword [rdi], dword 0cc90cc90h
+ lock add qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /0 ib ADD reg/memX, imm8 - sans reg dst
+ lock add word [1000h], byte 07fh
+ lock add word [xBX], byte 07fh
+ lock add word [xDI], byte 07fh
+ lock add dword [1000h], byte 07fh
+ lock add dword [xBX], byte 07fh
+ lock add dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock add qword [1000h], byte 07fh
+ lock add qword [rbx], byte 07fh
+ lock add qword [rdi], byte 07fh
+ lock add qword [r10], byte 07fh
+%endif
+
+ ; 00 /r ADD reg/mem8, reg8 - sans reg dst
+ lock add byte [1000h], bl
+ lock add byte [xBX], bl
+ lock add byte [xSI], bl
+ ; 01 /r ADD reg/memX, regX - sans reg dst
+ lock add word [1000h], bx
+ lock add word [xBX], bx
+ lock add word [xSI], bx
+ lock add dword [1000h], ebx
+ lock add dword [xBX], ebx
+ lock add dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock add qword [1000h], rbx
+ lock add qword [rbx], rbx
+ lock add qword [rsi], rbx
+ lock add qword [r11], rbx
+%endif
+
+ ;
+ ; AND
+ ;
+ ; 80 /4 ib AND reg/mem8, imm8 - sans reg dst
+ lock and byte [1000h], byte 8
+ lock and byte [xBX], byte 8
+ lock and byte [xDI], byte 8
+ ; 81 /4 i[wd] AND reg/memX, immX - sans reg dst
+ lock and word [1000h], word 090cch
+ lock and word [xBX], word 090cch
+ lock and word [xDI], word 090cch
+ lock and dword [1000h], dword 0cc90cc90h
+ lock and dword [xBX], dword 0cc90cc90h
+ lock and dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock and qword [1000h], dword 0cc90cc90h
+ lock and qword [rbx], dword 0cc90cc90h
+ lock and qword [rdi], dword 0cc90cc90h
+ lock and qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /4 ib AND reg/memX, imm8 - sans reg dst
+ lock and word [1000h], byte 07fh
+ lock and word [xBX], byte 07fh
+ lock and word [xDI], byte 07fh
+ lock and dword [1000h], byte 07fh
+ lock and dword [xBX], byte 07fh
+ lock and dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock and qword [1000h], byte 07fh
+ lock and qword [rbx], byte 07fh
+ lock and qword [rdi], byte 07fh
+ lock and qword [r10], byte 07fh
+%endif
+
+ ; 20 /r AND reg/mem8, reg8 - sans reg dst
+ lock and byte [1000h], bl
+ lock and byte [xBX], bl
+ lock and byte [xSI], bl
+ ; 21 /r AND reg/memX, regX - sans reg dst
+ lock and word [1000h], bx
+ lock and word [xBX], bx
+ lock and word [xSI], bx
+ lock and dword [1000h], ebx
+ lock and dword [xBX], ebx
+ lock and dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock and qword [1000h], rbx
+ lock and qword [rbx], rbx
+ lock and qword [rsi], rbx
+ lock and qword [r11], rbx
+%endif
+
+ ;
+ ; BTC
+ ;
+ ; 0f bb /r BTC reg/memX, regX (X != 8) - sans reg dst
+ lock btc word [20cch], bx
+ lock btc word [xBX], bx
+ lock btc word [xDI], bx
+ lock btc dword [20cch], ebx
+ lock btc dword [xBX], ebx
+ lock btc dword [xDI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btc qword [20cch], rbx
+ lock btc qword [rdx], rbx
+ lock btc qword [rdi], r10
+ lock btc qword [r8], r12
+%endif
+ ; 0f ba /7 ib BTC reg/memX, imm8 (X != 8) - sans reg dst
+ lock btc word [20cch], 15
+ lock btc word [xBX], 15
+ lock btc word [xDI], 15
+ lock btc dword [20cch], 30
+ lock btc dword [xBX], 30
+ lock btc dword [xDI], 30
+%ifdef WITH_64_BIT_TESTS
+ lock btc qword [20cch], 60
+ lock btc qword [rdx], 60
+ lock btc qword [rdi], 60
+ lock btc qword [r9], 60
+ lock btc qword [r12], 60
+%endif
+
+ ;
+ ; BTR
+ ;
+ ; 0f b3 /r BTR reg/memX, regX (X != 8) - sans reg dst
+ lock btr word [20cch], bx
+ lock btr word [xBX], bx
+ lock btr word [xDI], bx
+ lock btr dword [20cch], ebx
+ lock btr dword [xBX], ebx
+ lock btr dword [xDI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btr qword [20cch], rbx
+ lock btr qword [rdx], rbx
+ lock btr qword [rdi], r10
+ lock btr qword [r8], r12
+%endif
+ ; 0f ba /6 ib BTR reg/memX, imm8 (X != 8) - sans reg dst
+ lock btr word [20cch], 15
+ lock btr word [xBX], 15
+ lock btr word [xDI], 15
+ lock btr dword [20cch], 30
+ lock btr dword [xBX], 30
+ lock btr dword [xDI], 30
+%ifdef WITH_64_BIT_TESTS
+ lock btr qword [20cch], 60
+ lock btr qword [rdx], 60
+ lock btr qword [rdi], 60
+ lock btr qword [r9], 60
+ lock btr qword [r12], 60
+%endif
+
+ ;
+ ; BTS
+ ;
+ ; 0f ab /r BTS reg/memX, regX (X != 8) - sans reg dst
+ lock bts word [20cch], bx
+ lock bts word [xBX], bx
+ lock bts word [xDI], bx
+ lock bts dword [20cch], ebx
+ lock bts dword [xBX], ebx
+ lock bts dword [xDI], ebx
+%if TEST_BITS == 64
+ lock bts qword [20cch], rbx
+ lock bts qword [rdx], rbx
+ lock bts qword [rdi], r10
+ lock bts qword [r8], r12
+%endif
+ ; 0f ba /5 ib BTS reg/memX, imm8 (X != 8) - sans reg dst
+ lock bts word [20cch], 15
+ lock bts word [xBX], 15
+ lock bts word [xDI], 15
+ lock bts dword [20cch], 30
+ lock bts dword [xBX], 30
+ lock bts dword [xDI], 30
+%if TEST_BITS == 64
+ lock bts qword [20cch], 60
+ lock bts qword [rdx], 60
+ lock bts qword [rdi], 60
+ lock bts qword [r9], 60
+ lock bts qword [r12], 60
+%endif
+
+ ;
+ ; CMPXCHG
+ ;
+ ; 0f b0 /r CMPXCHG reg8/mem8, regX - with reg dst
+ lock cmpxchg byte [30cch], cl
+ lock cmpxchg byte [xBX], cl
+ lock cmpxchg byte [xSI], cl
+ ; 0f b1 /r CMPXCHG regX/memX, regX - with reg dst
+ lock cmpxchg word [30cch], cx
+ lock cmpxchg word [xBX], cx
+ lock cmpxchg word [xSI], cx
+ lock cmpxchg dword [30cch], ecx
+ lock cmpxchg dword [xBX], ecx
+ lock cmpxchg dword [xSI], ecx
+%ifdef WITH_64_BIT_TESTS
+ lock cmpxchg qword [30cch], rcx
+ lock cmpxchg qword [xBX], rcx
+ lock cmpxchg qword [xSI], rcx
+ lock cmpxchg qword [rdi], r8
+ lock cmpxchg qword [r12], r9
+%endif
+
+ ;
+ ; CMPXCHG8B
+ ; CMPXCHG16B
+ ;
+ ;; @todo get back to cmpxchg8b and cmpxchg16b.
+ lock cmpxchg8b qword [1000h]
+ lock cmpxchg8b qword [xDI]
+ lock cmpxchg8b qword [xDI+xBX]
+%ifdef WITH_64_BIT_TESTS_CMPXCHG16B
+ lock cmpxchg16b [1000h]
+ lock cmpxchg16b [xDI]
+ lock cmpxchg16b [xDI+xBX]
+%endif
+
+ ;
+ ; DEC
+ ;
+ ; fe /1 DEC reg8/mem8 - sans reg dst
+ lock dec byte [40cch]
+ lock dec byte [xBX]
+ lock dec byte [xSI]
+ ; ff /1 DEC regX/memX - sans reg dst
+ lock dec word [40cch]
+ lock dec word [xBX]
+ lock dec word [xSI]
+ lock dec dword [40cch]
+ lock dec dword [xBX]
+ lock dec dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock dec qword [40cch]
+ lock dec qword [xBX]
+ lock dec qword [xSI]
+ lock dec qword [r8]
+ lock dec qword [r12]
+%endif
+
+ ;
+ ; INC
+ ;
+ ; fe /0 INC reg8/mem8 - sans reg dst
+ lock inc byte [40cch]
+ lock inc byte [xBX]
+ lock inc byte [xSI]
+ ; ff /0 INC regX/memX - sans reg dst
+ lock inc word [40cch]
+ lock inc word [xBX]
+ lock inc word [xSI]
+ lock inc dword [40cch]
+ lock inc dword [xBX]
+ lock inc dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock inc qword [40cch]
+ lock inc qword [xBX]
+ lock inc qword [xSI]
+ lock inc qword [r8]
+ lock inc qword [r12]
+%endif
+
+ ;
+ ; NEG
+ ;
+ ; f6 /3 NEG reg8/mem8 - sans reg dst
+ lock neg byte [40cch]
+ lock neg byte [xBX]
+ lock neg byte [xSI]
+ ; f7 /3 NEG regX/memX - sans reg dst
+ lock neg word [40cch]
+ lock neg word [xBX]
+ lock neg word [xSI]
+ lock neg dword [40cch]
+ lock neg dword [xBX]
+ lock neg dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock neg qword [40cch]
+ lock neg qword [xBX]
+ lock neg qword [xSI]
+ lock neg qword [r8]
+ lock neg qword [r12]
+%endif
+
+ ;
+ ; NOT
+ ;
+ ; f6 /2 NOT reg8/mem8 - sans reg dst
+ lock not byte [40cch]
+ lock not byte [xBX]
+ lock not byte [xSI]
+ ; f7 /2 NOT regX/memX - sans reg dst
+ lock not word [40cch]
+ lock not word [xBX]
+ lock not word [xSI]
+ lock not dword [40cch]
+ lock not dword [xBX]
+ lock not dword [xSI]
+%ifdef WITH_64_BIT_TESTS
+ lock not qword [40cch]
+ lock not qword [xBX]
+ lock not qword [xSI]
+ lock not qword [r8]
+ lock not qword [r12]
+%endif
+
+ ;
+ ; OR
+ ;
+ ; 80 /1 ib OR reg/mem8, imm8 - sans reg dst
+ lock or byte [1000h], byte 8
+ lock or byte [xBX], byte 8
+ lock or byte [xDI], byte 8
+ ; 81 /1 i[wd] OR reg/memX, immX - sans reg dst
+ lock or word [1000h], word 090cch
+ lock or word [xBX], word 090cch
+ lock or word [xDI], word 090cch
+ lock or dword [1000h], dword 0cc90cc90h
+ lock or dword [xBX], dword 0cc90cc90h
+ lock or dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or qword [1000h], dword 0cc90cc90h
+ lock or qword [rbx], dword 0cc90cc90h
+ lock or qword [rdi], dword 0cc90cc90h
+ lock or qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /1 ib OR reg/memX, imm8 - sans reg dst
+ lock or word [1000h], byte 07fh
+ lock or word [xBX], byte 07fh
+ lock or word [xDI], byte 07fh
+ lock or dword [1000h], byte 07fh
+ lock or dword [xBX], byte 07fh
+ lock or dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock or qword [1000h], byte 07fh
+ lock or qword [rbx], byte 07fh
+ lock or qword [rdi], byte 07fh
+ lock or qword [r10], byte 07fh
+%endif
+
+ ; 08 /r OR reg/mem8, reg8 - sans reg dst
+ lock or byte [1000h], bl
+ lock or byte [xBX], bl
+ lock or byte [xSI], bl
+ ; 09 /r OR reg/memX, regX - sans reg dst
+ lock or word [1000h], bx
+ lock or word [xBX], bx
+ lock or word [xSI], bx
+ lock or dword [1000h], ebx
+ lock or dword [xBX], ebx
+ lock or dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock or qword [1000h], rbx
+ lock or qword [rbx], rbx
+ lock or qword [rsi], rbx
+ lock or qword [r11], rbx
+%endif
+
+ ;
+ ; SBB
+ ;
+ ; 80 /3 ib SBB reg/mem8, imm8 - sans reg dst
+ lock sbb byte [1000h], byte 8
+ lock sbb byte [xBX], byte 8
+ lock sbb byte [xDI], byte 8
+ ; 81 /3 i[wd] SBB reg/memX, immX - sans reg dst
+ lock sbb word [1000h], word 090cch
+ lock sbb word [xBX], word 090cch
+ lock sbb word [xDI], word 090cch
+ lock sbb dword [1000h], dword 0cc90cc90h
+ lock sbb dword [xBX], dword 0cc90cc90h
+ lock sbb dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb qword [1000h], dword 0cc90cc90h
+ lock sbb qword [rbx], dword 0cc90cc90h
+ lock sbb qword [rdi], dword 0cc90cc90h
+ lock sbb qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /3 ib SBB reg/memX, imm8 - sans reg dst
+ lock sbb word [1000h], byte 07fh
+ lock sbb word [xBX], byte 07fh
+ lock sbb word [xDI], byte 07fh
+ lock sbb dword [1000h], byte 07fh
+ lock sbb dword [xBX], byte 07fh
+ lock sbb dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock sbb qword [1000h], byte 07fh
+ lock sbb qword [rbx], byte 07fh
+ lock sbb qword [rdi], byte 07fh
+ lock sbb qword [r10], byte 07fh
+%endif
+
+ ; 18 /r SBB reg/mem8, reg8 - sans reg dst
+ lock sbb byte [1000h], bl
+ lock sbb byte [xBX], bl
+ lock sbb byte [xSI], bl
+ ; 19 /r SBB reg/memX, regX - sans reg dst
+ lock sbb word [1000h], bx
+ lock sbb word [xBX], bx
+ lock sbb word [xSI], bx
+ lock sbb dword [1000h], ebx
+ lock sbb dword [xBX], ebx
+ lock sbb dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sbb qword [1000h], rbx
+ lock sbb qword [rbx], rbx
+ lock sbb qword [rsi], rbx
+ lock sbb qword [r11], rbx
+%endif
+
+ ;
+ ; SUB
+ ;
+ ; 80 /5 ib SUB reg/mem8, imm8 - sans reg dst
+ lock sub byte [1000h], byte 8
+ lock sub byte [xBX], byte 8
+ lock sub byte [xDI], byte 8
+ ; 81 /5 i[wd] SUB reg/memX, immX - sans reg dst
+ lock sub word [1000h], word 090cch
+ lock sub word [xBX], word 090cch
+ lock sub word [xDI], word 090cch
+ lock sub dword [1000h], dword 0cc90cc90h
+ lock sub dword [xBX], dword 0cc90cc90h
+ lock sub dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub qword [1000h], dword 0cc90cc90h
+ lock sub qword [rbx], dword 0cc90cc90h
+ lock sub qword [rdi], dword 0cc90cc90h
+ lock sub qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /5 ib SUB reg/memX, imm8 - sans reg dst
+ lock sub word [1000h], byte 07fh
+ lock sub word [xBX], byte 07fh
+ lock sub word [xDI], byte 07fh
+ lock sub dword [1000h], byte 07fh
+ lock sub dword [xBX], byte 07fh
+ lock sub dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock sub qword [1000h], byte 07fh
+ lock sub qword [rbx], byte 07fh
+ lock sub qword [rdi], byte 07fh
+ lock sub qword [r10], byte 07fh
+%endif
+
+ ; 28 /r SUB reg/mem8, reg8 - sans reg dst
+ lock sub byte [1000h], bl
+ lock sub byte [xBX], bl
+ lock sub byte [xSI], bl
+ ; 29 /r SUB reg/memX, regX - sans reg dst
+ lock sub word [1000h], bx
+ lock sub word [xBX], bx
+ lock sub word [xSI], bx
+ lock sub dword [1000h], ebx
+ lock sub dword [xBX], ebx
+ lock sub dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sub qword [1000h], rbx
+ lock sub qword [rbx], rbx
+ lock sub qword [rsi], rbx
+ lock sub qword [r11], rbx
+%endif
+
+ ;
+ ; XADD
+ ;
+ ; 0f c0 /r XADD reg/mem8, reg8 - sans reg dst
+ lock xadd byte [1000h], bl
+ lock xadd byte [xBX], bl
+ lock xadd byte [xDI], bl
+ ; 0f c1 /r XADD reg/memX, immX - sans reg dst
+ lock xadd word [1000h], cx
+ lock xadd word [xBX], cx
+ lock xadd word [xDI], cx
+ lock xadd dword [1000h], edx
+ lock xadd dword [xBX], edx
+ lock xadd dword [xDI], edx
+%ifdef WITH_64_BIT_TESTS
+ lock xadd qword [1000h], rbx
+ lock xadd qword [xBX], rbx
+ lock xadd qword [xDI], rbx
+ lock xadd qword [r8], rbx
+ lock xadd qword [r12], r8
+%endif
+
+ ;
+ ; XCHG
+ ;
+ ; Note: The operands can be switched around but the
+ ; encoding is the same.
+ ;
+ ; 86 /r XCHG reg/mem8, imm8 - sans reg dst
+ lock xchg byte [80cch], bl
+ lock xchg byte [xBX], bl
+ lock xchg byte [xSI], bl
+%ifdef WITH_64_BIT_TESTS_BORKED_REGS
+ lock xchg byte [rsi], r15b ; turns into r15l which yasm doesn't grok
+ lock xchg byte [r8], r15b ; ditto
+%endif
+ ; 87 /r XCHG reg/memX, immX - sans reg dst
+ lock xchg word [80cch], bx
+ lock xchg word [xBX], bx
+ lock xchg word [xSI], bx
+ lock xchg dword [80cch], ebx
+ lock xchg dword [xBX], ebx
+ lock xchg dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xchg qword [80cch], rbx
+ lock xchg qword [xBX], rbx
+ lock xchg qword [xSI], rbx
+ lock xchg qword [xSI], r15
+ %ifdef WITH_64_BIT_TESTS_BORKED_REGS
+ lock xchg dword [xSI], r15d ; turns into rdi
+ lock xchg word [xSI], r15w ; turns into rdi
+ %endif
+%endif
+
+ ;
+ ; XOR
+ ;
+ ; 80 /6 ib XOR reg/mem8, imm8 - sans reg dst
+ lock xor byte [1000h], byte 8
+ lock xor byte [xBX], byte 8
+ lock xor byte [xDI], byte 8
+ ; 81 /6 i[wd] XOR reg/memX, immX - sans reg dst
+ lock xor word [1000h], word 090cch
+ lock xor word [xBX], word 090cch
+ lock xor word [xDI], word 090cch
+ lock xor dword [1000h], dword 0cc90cc90h
+ lock xor dword [xBX], dword 0cc90cc90h
+ lock xor dword [xDI], dword 0cc90cc90h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor qword [1000h], dword 0cc90cc90h
+ lock xor qword [rbx], dword 0cc90cc90h
+ lock xor qword [rdi], dword 0cc90cc90h
+ lock xor qword [r9], dword 0cc90cc90h
+%endif
+ ; 83 /6 ib XOR reg/memX, imm8 - sans reg dst
+ lock xor word [1000h], byte 07fh
+ lock xor word [xBX], byte 07fh
+ lock xor word [xDI], byte 07fh
+ lock xor dword [1000h], byte 07fh
+ lock xor dword [xBX], byte 07fh
+ lock xor dword [xDI], byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock xor qword [1000h], byte 07fh
+ lock xor qword [rbx], byte 07fh
+ lock xor qword [rdi], byte 07fh
+ lock xor qword [r10], byte 07fh
+%endif
+
+ ; 30 /r XOR reg/mem8, reg8 - sans reg dst
+ lock xor byte [1000h], bl
+ lock xor byte [xBX], bl
+ lock xor byte [xSI], bl
+ ; 31 /r XOR reg/memX, regX - sans reg dst
+ lock xor word [1000h], bx
+ lock xor word [xBX], bx
+ lock xor word [xSI], bx
+ lock xor dword [1000h], ebx
+ lock xor dword [xBX], ebx
+ lock xor dword [xSI], ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xor qword [1000h], rbx
+ lock xor qword [rbx], rbx
+ lock xor qword [rsi], rbx
+ lock xor qword [r11], rbx
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmLock-2.asm b/src/VBox/Disassembler/testcase/tstAsmLock-2.asm
new file mode 100644
index 00000000..f1e38b3a
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmLock-2.asm
@@ -0,0 +1,547 @@
+; $Id: tstAsmLock-2.asm $
+;; @file
+; Disassembly testcase - Invalid invariants.
+;
+; The intention is to check in a binary using the --all-invalid mode
+; of tstDisasm-2.
+;
+; There are some regX, reg/memX variations that aren't tested as
+; they would require db'ing out the instructions (12 /r and 13 /r
+; for instance).
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+%if TEST_BITS == 64
+; The disassembler doesn't do imm32 right for 64-bit stuff, so disable it for now.
+; %define WITH_64_BIT_TESTS_IMM32
+ %define WITH_64_BIT_TESTS
+%endif
+
+ BITS TEST_BITS
+
+ ;
+ ; ADC
+ ;
+ ; 14 ib ADC AL, imm8
+ lock adc al, byte 8
+ ; 15 i[wd] ADC [ER]AX, immX
+ lock adc ax, word 16
+ lock adc eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc rax, dword 256
+ lock adc rax, dword 0cc90cc90h
+%endif
+ ; 80 /2 ib ADC reg/mem8, imm8 - with reg dst
+ lock adc cl, byte 8
+ ; 81 /2 i[wd] ADC reg/memX, immX - with reg dst
+ lock adc cx, word 1000h
+ lock adc ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc rcx, dword 100000h
+%endif
+ ; 83 /2 ib ADC reg/memX, imm8 - with reg dst
+ lock adc cx, byte 07fh
+ lock adc ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock adc rcx, byte 07fh
+%endif
+
+ ; 10 /r ADC reg/mem8, reg8 - with reg dst
+ lock adc cl, bl
+ ; 11 /r ADC reg/memX, regX - with reg dst
+ lock adc cx, bx
+ lock adc ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock adc rcx, rbx
+%endif
+ ; 12 /r ADC reg8, reg/mem8
+ lock adc cl, [0badh]
+ ; 13 /r ADC regX, reg/memX
+ lock adc cx, [0badh]
+ lock adc ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock adc rcx, [0badh]
+%endif
+
+ ;
+ ; ADD
+ ;
+ ; 04 ib ADD AL, imm8
+ lock add al, byte 8
+ ; 05 i[wd] ADD [ER]AX, immX
+ lock add ax, word 16
+ lock add eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock add rax, dword 256
+ lock add rax, dword 0cc90cc90h
+%endif
+ ; 80 /0 ib ADD reg/mem8, imm8 - with reg dst
+ lock add cl, byte 8
+ ; 81 /0 i[wd] ADD reg/memX, immX - with reg dst
+ lock add cx, word 1000h
+ lock add ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock add rcx, dword 100000h
+%endif
+ ; 83 /0 ib ADD reg/memX, imm8 - with reg dst
+ lock add cx, byte 07fh
+ lock add ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock add rcx, byte 07fh
+%endif
+
+ ; 00 /r ADD reg/mem8, reg8 - with reg dst
+ lock add cl, bl
+ ; 01 /r ADD reg/memX, regX - with reg dst
+ lock add cx, bx
+ lock add ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock add rcx, rbx
+%endif
+ ; 02 /r ADD reg8, reg/mem8
+ lock add cl, [0badh]
+ ; 03 /r ADD regX, reg/memX
+ lock add cx, [0badh]
+ lock add ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock add rcx, [0badh]
+%endif
+
+ ;
+ ; AND
+ ;
+ ; 24 ib AND AL, imm8
+ lock and al, byte 8
+ ; 25 i[wd] AND [ER]AX, immX
+ lock and ax, word 16
+ lock and eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock and rax, dword 256
+ lock and rax, dword 0cc90cc90h
+%endif
+ ; 80 /4 ib AND reg/mem8, imm8 - with reg dst
+ lock and cl, byte 8
+ ; 81 /4 i[wd] AND reg/memX, immX - with reg dst
+ lock and cx, word 1000h
+ lock and ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock and rcx, dword 100000h
+%endif
+ ; 83 /4 ib AND reg/memX, imm8 - with reg dst
+ lock and cx, byte 07fh
+ lock and ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS
+ lock and rcx, byte 07fh
+%endif
+
+ ; 20 /r AND reg/mem8, reg8 - with reg dst
+ lock and cl, bl
+ ; 21 /r AND reg/memX, regX - with reg dst
+ lock and cx, bx
+ lock and ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock and rcx, rbx
+%endif
+ ; 22 /r AND reg8, reg/mem8
+ lock and cl, [0badh]
+ ; 23 /r AND regX, reg/memX
+ lock and cx, [0badh]
+ lock and ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock and rcx, [0badh]
+%endif
+
+ ;
+ ; BTC
+ ;
+ ; 0f bb /r BTC reg/memX, regX (X != 8) - with reg dst
+ lock btc cx, bx
+ lock btc ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btc rcx, rbx
+ lock btc r8, rbx
+ lock btc r10, r8
+%endif
+ ; 0f ba /7 ib BTC reg/memX, imm8 (X != 8) - with reg dst
+ lock btc cx, 15
+ lock btc ecx, 30
+%ifdef WITH_64_BIT_TESTS
+ lock btc rcx, 60
+ lock btc r8, 61
+ lock btc r10, 3
+%endif
+
+ ;
+ ; BTR
+ ;
+ ; 0f b3 /r BTR reg/memX, regX (X != 8) - with reg dst
+ lock btr cx, bx
+ lock btr ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock btr rcx, rbx
+ lock btr r8, rbx
+ lock btr r10, r8
+%endif
+ ; 0f ba /6 ib BTR reg/memX, imm8 (X != 8) - with reg dst
+ lock btr cx, 15
+ lock btr ecx, 30
+%ifdef WITH_64_BIT_TESTS
+ lock btr rcx, 60
+ lock btr r8, 61
+ lock btr r10, 3
+%endif
+
+ ;
+ ; BTS
+ ;
+ ; 0f ab /r BTS reg/memX, regX (X != 8) - with reg dst
+ lock bts cx, bx
+ lock bts ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock bts rcx, rbx
+ lock bts r8, rbx
+ lock bts r10, r8
+%endif
+ ; 0f ba /5 ib BTS reg/memX, imm8 (X != 8) - with reg dst
+ lock bts cx, 15
+ lock bts ecx, 30
+%ifdef WITH_64_BIT_TESTS
+ lock bts rcx, 60
+ lock bts r8, 61
+ lock bts r10, 3
+%endif
+
+ ;
+ ; CMPXCHG
+ ;
+ ; 0f b0 /r CMPXCHG reg8/mem8, regX - with reg dst
+ lock cmpxchg bl, cl
+ ; 0f b1 /r CMPXCHG regX/memX, regX - with reg dst
+ lock cmpxchg bx, cx
+ lock cmpxchg ebx, ecx
+%ifdef WITH_64_BIT_TESTS
+ lock cmpxchg rbx, rcx
+%endif
+
+ ;
+ ; CMPXCHG8B
+ ; CMPXCHG16B
+ ;
+ ; all valid.
+
+ ;
+ ; DEC
+ ;
+ ; fe /1 DEC reg8/mem8 - with reg dst
+ lock dec bl
+ ; ff /1 DEC regX/memX - with reg dst
+
+%if TEST_BITS != 64 ; cannot force these two in 32 and 16 bit mode.
+ db 066h, 0f0h, 0ffh, 0cbh
+ db 0f0h, 0ffh, 0cbh
+%else
+ lock dec bx
+ lock dec ebx
+ %ifdef WITH_64_BIT_TESTS
+ lock dec rbx
+ lock dec r8
+ lock dec r14
+ %endif
+%endif
+%if TEST_BITS != 64
+ ; 48 +rw DEC reg16
+ lock dec dx
+ ; 48 +rd DEC reg32
+ lock dec edx
+%endif
+
+ ;
+ ; INC
+ ;
+ ; fe /1 INC reg8/mem8 - with reg dst
+ lock inc bl
+ ; ff /1 INC regX/memX - with reg dst
+
+%if TEST_BITS != 64 ; cannot force these two in 32 and 16 bit mode.
+ db 066h, 0f0h, 0ffh, 0c3h
+ db 0f0h, 0ffh, 0c3h
+%else
+ lock inc bx
+ lock inc ebx
+ %ifdef WITH_64_BIT_TESTS
+ lock inc rbx
+ lock inc r8
+ lock inc r14
+ %endif
+%endif
+%if TEST_BITS != 64
+ ; 48 +rw INC reg16
+ lock inc dx
+ ; 48 +rd INC reg32
+ lock inc edx
+%endif
+
+ ;
+ ; NEG
+ ;
+ ; f6 /3 NEG reg8/mem8 - with reg dst
+ lock neg bl
+ ; f7 /3 NEG regX/memX - with reg dst
+ lock neg bx
+ lock neg ebx
+%ifdef WITH_64_BIT_TESTS
+ lock neg rbx
+ lock neg r8
+ lock neg r14
+%endif
+
+ ;
+ ; NOT
+ ;
+ ; f6 /2 NOT reg8/mem8 - with reg dst
+ lock not bl
+ ; f7 /2 NOT regX/memX - with reg dst
+ lock not bx
+ lock not ebx
+%ifdef WITH_64_BIT_TESTS
+ lock not rbx
+ lock not r8
+ lock not r14
+%endif
+
+ ;
+ ; OR
+ ;
+ ; 0C ib OR AL, imm8
+ lock or al, byte 8
+ ; 0D i[wd] OR [ER]AX, immX
+ lock or ax, word 16
+ lock or eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or rax, dword 256
+ lock or rax, dword 0cc90cc90h
+%endif
+ ; 80 /1 ib OR reg/mem8, imm8 - with reg dst
+ lock or cl, byte 8
+ ; 81 /1 i[wd] OR reg/memX, immX - with reg dst
+ lock or cx, word 1000h
+ lock or ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or rcx, dword 100000h
+%endif
+ ; 83 /1 ib OR reg/memX, imm8 - with reg dst
+ lock or cx, byte 07fh
+ lock or ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock or rcx, byte 07fh
+%endif
+ ; 08 /r OR reg/mem8, reg8 - with reg dst
+ lock or cl, bl
+ ; 09 /r OR reg/memX, regX - with reg dst
+ lock or cx, bx
+ lock or ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock or rcx, rbx
+%endif
+ ; 0A /r OR reg8, reg/mem8
+ lock or cl, [0badh]
+ ; 0B /r OR regX, reg/memX
+ lock or cx, [0badh]
+ lock or ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock or rcx, [0badh]
+%endif
+
+ ;
+ ; SBB
+ ;
+ ; 1C ib SBB AL, imm8
+ lock sbb al, byte 8
+ ; 1D i[wd] SBB [ER]AX, immX
+ lock sbb ax, word 16
+ lock sbb eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb rax, dword 256
+ lock sbb rax, dword 0cc90cc90h
+%endif
+ ; 80 /3 ib SBB reg/mem8, imm8 - with reg dst
+ lock sbb cl, byte 8
+ ; 81 /3 i[wd] SBB reg/memX, immX - with reg dst
+ lock sbb cx, word 1000h
+ lock sbb ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb rcx, dword 100000h
+%endif
+ ; 83 /3 ib SBB reg/memX, imm8 - with reg dst
+ lock sbb cx, byte 07fh
+ lock sbb ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sbb rcx, byte 07fh
+%endif
+ ; 18 /r SBB reg/mem8, reg8 - with reg dst
+ lock sbb cl, bl
+ ; 19 /r SBB reg/memX, regX - with reg dst
+ lock sbb cx, bx
+ lock sbb ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sbb rcx, rbx
+%endif
+ ; 1A /r SBB reg8, reg/mem8
+ lock sbb cl, [0badh]
+ ; 1B /r SBB regX, reg/memX
+ lock sbb cx, [0badh]
+ lock sbb ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock sbb rcx, [0badh]
+%endif
+
+ ;
+ ; SUB
+ ;
+ ; 2C ib SUB AL, imm8
+ lock sub al, byte 8
+ ; 2D i[wd] SUB [ER]AX, immX
+ lock sub ax, word 16
+ lock sub eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub rax, dword 256
+ lock sub rax, dword 0cc90cc90h
+%endif
+ ; 80 /5 ib SUB reg/mem8, imm8 - with reg dst
+ lock sub cl, byte 8
+ ; 81 /5 i[wd] SUB reg/memX, immX - with reg dst
+ lock sub cx, word 1000h
+ lock sub ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub rcx, dword 100000h
+%endif
+ ; 83 /5 ib SUB reg/memX, imm8 - with reg dst
+ lock sub cx, byte 07fh
+ lock sub ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock sub rcx, byte 07fh
+%endif
+ ; 28 /r SUB reg/mem8, reg8 - with reg dst
+ lock sub cl, bl
+ ; 29 /r SUB reg/memX, regX - with reg dst
+ lock sub cx, bx
+ lock sub ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock sub rcx, rbx
+%endif
+ ; 2A /r SUB reg8, reg/mem8
+ lock sub cl, [0badh]
+ ; 2B /r SUB regX, reg/memX
+ lock sub cx, [0badh]
+ lock sub ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock sub rcx, [0badh]
+%endif
+
+ ;
+ ; XADD
+ ;
+ ; 0f c0 /r XADD reg/mem8, reg8 - with reg dst
+ lock xadd al, bl
+ ; 0f c1 /r XADD reg/memX, immX - with reg dst
+ lock xadd cx, bx
+ lock xadd ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xadd rcx, rbx
+ lock xadd r8, rbx
+ lock xadd r10, r8
+%endif
+
+ ;
+ ; XCHG
+ ;
+ ; Note: The operands can be switched around but the
+ ; encoding is the same.
+ ;
+ ; 90 +r[wdq] XCHG [RE]ax, regX
+ lock xchg ax, bx
+ lock xchg eax, ecx
+%ifdef WITH_64_BIT_TESTS
+ lock xchg rax, rcx
+ lock xchg rax, r10
+%endif
+ ; 86 /r XCHG reg/mem8, imm8 - with reg dst
+ lock xchg al, bl
+%ifdef WITH_64_BIT_TESTS
+ lock xchg r10b, cl
+ lock xchg r10b, r15b
+%endif
+ ; 87 /r XCHG reg/memX, immX - with reg dst
+ lock xchg ax, bx
+ lock xchg eax, ebx
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xchg rax, rbx
+ lock xchg r12, rbx
+ lock xchg r14, r8
+%endif
+
+ ;
+ ; XOR
+ ;
+ ; 34 ib XOR AL, imm8
+ lock xor al, byte 8
+ ; 35 i[wd] XOR [ER]AX, immX
+ lock xor ax, word 16
+ lock xor eax, dword 128
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor rax, dword 256
+ lock xor rax, dword 0cc90cc90h
+%endif
+ ; 80 /6 ib XOR reg/mem8, imm8 - with reg dst
+ lock xor cl, byte 8
+ ; 81 /6 i[wd] XOR reg/memX, immX - with reg dst
+ lock xor cx, word 1000h
+ lock xor ecx, dword 100000h
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor rcx, dword 100000h
+%endif
+ ; 83 /6 ib XOR reg/memX, imm8 - with reg dst
+ lock xor cx, byte 07fh
+ lock xor ecx, byte 07fh
+%ifdef WITH_64_BIT_TESTS_IMM32
+ lock xor rcx, byte 07fh
+%endif
+ ; 30 /r XOR reg/mem8, reg8 - with reg dst
+ lock xor cl, bl
+ ; 31 /r XOR reg/memX, regX - with reg dst
+ lock xor cx, bx
+ lock xor ecx, ebx
+%ifdef WITH_64_BIT_TESTS
+ lock xor rcx, rbx
+%endif
+ ; 32 /r XOR reg8, reg/mem8
+ lock xor cl, [0badh]
+ ; 33 /r XOR regX, reg/memX
+ lock xor cx, [0badh]
+ lock xor ecx, [0badh]
+%ifdef WITH_64_BIT_TESTS
+ lock xor rcx, [0badh]
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmLock-3.asm b/src/VBox/Disassembler/testcase/tstAsmLock-3.asm
new file mode 100644
index 00000000..508be5e8
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmLock-3.asm
@@ -0,0 +1,56 @@
+; $Id: tstAsmLock-3.asm $
+;; @file
+; Disassembly testcase - Invalid lock sequences for non-locking instructions.
+;
+; The intention is to check in a binary using the --all-invalid mode
+; of tstDisasm-2.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+
+ BITS TEST_BITS
+
+ lock mov ebp, esp
+ lock mov byte [0], 0
+ lock mov word [0], 0
+ lock mov dword [0], 0
+ lock mov word [0], 01234h
+ lock mov dword [0], 012348765h
+ lock mov byte [ebx], 0
+ lock mov [ebx], eax
+ lock mov [ebx], ax
+ lock mov [ebx], al
+ lock mov [ebx], edx
+ lock mov [ebx], dx
+ lock mov [ebx], dl
+ lock ret
+%if TEST_BITS != 64
+ lock pop ebp
+ lock push esp
+%else
+ lock pop rbp
+ lock push rsp
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm b/src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm
new file mode 100644
index 00000000..571994a4
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmMovFixedReg-1.asm
@@ -0,0 +1,113 @@
+; $Id: tstAsmMovFixedReg-1.asm $
+;; @file
+; Disassembly testcase - Valid mov immediate to fixed registers.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2013-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+ BITS TEST_BITS
+
+ mov al, 01h
+ mov cl, 02h
+ mov dl, 03h
+ mov bl, 04h
+ mov ah, 05h
+ mov ch, 06h
+ mov dh, 07h
+ mov bh, 08h
+%if TEST_BITS == 64
+ mov spl, 09h
+ mov bpl, 0ah
+ mov sil, 0bh
+ mov dil, 0ch
+ mov r8b, 0dh
+ mov r9b, 0eh
+ mov r10b, 0fh
+ mov r11b, 010h
+ mov r12b, 011h
+ mov r13b, 012h
+ mov r14b, 013h
+ mov r15b, 014h
+%endif
+
+ mov ax, 0f701h
+ mov cx, 0f702h
+ mov dx, 0f703h
+ mov bx, 0f704h
+ mov sp, 0f705h
+ mov bp, 0f706h
+ mov si, 0f707h
+ mov di, 0f708h
+%if TEST_BITS == 64
+ mov r8w, 0f709h
+ mov r9w, 0f70ah
+ mov r10w, 0f70bh
+ mov r11w, 0f70ch
+ mov r12w, 0f70dh
+ mov r13w, 0f70eh
+ mov r14w, 0f70fh
+ mov r15w, 0f710h
+%endif
+
+ mov eax, 0beeff701h
+ mov ecx, 0beeff702h
+ mov edx, 0beeff703h
+ mov ebx, 0beeff704h
+ mov esp, 0beeff705h
+ mov ebp, 0beeff706h
+ mov esi, 0beeff707h
+ mov edi, 0beeff708h
+%if TEST_BITS == 64
+ mov r8d, 0beeff709h
+ mov r9d, 0beeff70ah
+ mov r10d, 0beeff70bh
+ mov r11d, 0beeff70ch
+ mov r12d, 0beeff70dh
+ mov r13d, 0beeff70eh
+ mov r14d, 0beeff70fh
+ mov r15d, 0beeff710h
+%endif
+
+%if TEST_BITS == 64
+ mov rax, 0feedbabef00df701h
+ mov rcx, 0feedbabef00df702h
+ mov rdx, 0feedbabef00df703h
+ mov rbx, 0feedbabef00df704h
+ mov rsp, 0feedbabef00df705h
+ mov rbp, 0feedbabef00df706h
+ mov rsi, 0feedbabef00df707h
+ mov rdi, 0feedbabef00df708h
+ mov r8, 0feedbabef00df709h
+ mov r9, 0feedbabef00df70ah
+ mov r10, 0feedbabef00df70bh
+ mov r11, 0feedbabef00df70ch
+ mov r12, 0feedbabef00df70dh
+ mov r13, 0feedbabef00df70eh
+ mov r14, 0feedbabef00df70fh
+ mov r15, 0feedbabef00df710h
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm b/src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm
new file mode 100644
index 00000000..f4df41cf
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmMovSeg-1.asm
@@ -0,0 +1,58 @@
+; $Id: tstAsmMovSeg-1.asm $
+;; @file
+; Disassembly testcase - Valid mov from/to segment instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+ BITS TEST_BITS
+
+ mov fs, eax
+ mov fs, ax
+%if TEST_BITS == 64
+ mov fs, rax
+%endif
+
+ mov fs, [ebx]
+%if TEST_BITS != 64
+ mov fs, [bx]
+%else
+ mov fs, [rbx]
+%endif
+
+ mov ax, fs
+ mov eax, fs
+%if TEST_BITS == 64
+ mov rax, fs
+%endif
+
+ mov [ebx], fs
+%if TEST_BITS != 64
+ mov [bx], fs
+%else
+ mov [rbx], fs
+%endif
diff --git a/src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm b/src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm
new file mode 100644
index 00000000..910c8900
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmMovzx-1.asm
@@ -0,0 +1,49 @@
+; $Id: tstAsmMovzx-1.asm $
+;; @file
+; Disassembly testcase - Valid movzx sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+ BITS TEST_BITS
+
+ movzx ax, al
+ movzx eax, al
+ movzx ax, [ebx]
+ movzx eax, byte [ebx]
+ movzx eax, word [ebx]
+%if TEST_BITS != 64
+ movzx ax, [bx+si+8]
+ movzx eax, byte [bx+si+8]
+ movzx eax, word [bx+si+8]
+%else
+ movzx rax, al
+ movzx rax, ax
+ movzx rax, byte [rsi]
+ movzx rax, word [rsi]
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmPop-1.asm b/src/VBox/Disassembler/testcase/tstAsmPop-1.asm
new file mode 100644
index 00000000..7cc44fa2
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmPop-1.asm
@@ -0,0 +1,46 @@
+; $Id: tstAsmPop-1.asm $
+;; @file
+; Disassembly testcase - Valid pop sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+ BITS TEST_BITS
+%if TEST_BITS != 64
+ pop bp
+ pop ebp
+ pop word [bp]
+ pop dword [bp]
+ pop word [ebp]
+ pop dword [ebp]
+%else
+ %if 0 ; doesn't work yet
+ pop rbp
+ pop qword [rbp]
+ %endif
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmPush-1.asm b/src/VBox/Disassembler/testcase/tstAsmPush-1.asm
new file mode 100644
index 00000000..a87e86c8
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmPush-1.asm
@@ -0,0 +1,46 @@
+; $Id: tstAsmPush-1.asm $
+;; @file
+; Disassembly testcase - Valid push sequences and related instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+ BITS TEST_BITS
+%if TEST_BITS != 64
+ push bp
+ push ebp
+ push word [bp]
+ push dword [bp]
+ push word [ebp]
+ push dword [ebp]
+%else
+ %if 0 ; doesn't work yet - default operand size is wrong?
+ push rbp
+ push qword [rbp]
+ %endif
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmRegs-1.asm b/src/VBox/Disassembler/testcase/tstAsmRegs-1.asm
new file mode 100644
index 00000000..eecfd879
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmRegs-1.asm
@@ -0,0 +1,119 @@
+; $Id: tstAsmRegs-1.asm $
+;; @file
+; Disassembly testcase - Accessing all the registers
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+
+ BITS TEST_BITS
+
+ ;; @todo
+ ; Missing a bunch of permutations and encoding variants
+ ;
+
+ mov al, al
+ mov al, ah
+ mov al, bl
+ mov al, bh
+ mov al, cl
+ mov al, ch
+ mov al, dl
+ mov al, dh
+%if TEST_BITS == 64
+ mov al, dil
+ mov al, sil
+ mov al, bpl
+ mov al, spl
+ mov al, r8b
+ mov al, r9b
+ mov al, r10b
+ mov al, r11b
+ mov al, r12b
+ mov al, r13b
+ mov al, r14b
+ mov al, r15b
+%endif
+
+ mov ax, ax
+ mov ax, bx
+ mov ax, cx
+ mov ax, dx
+ mov ax, si
+ mov ax, di
+ mov ax, bp
+ mov ax, sp
+%if TEST_BITS == 64
+ mov ax, r8w
+ mov ax, r9w
+ mov ax, r10w
+ mov ax, r11w
+ mov ax, r12w
+ mov ax, r13w
+ mov ax, r14w
+ mov ax, r15w
+%endif
+
+ mov eax, eax
+ mov eax, ebx
+ mov eax, ecx
+ mov eax, edx
+ mov eax, esi
+ mov eax, edi
+ mov eax, ebp
+ mov eax, esp
+%if TEST_BITS == 64
+ mov eax, r8d
+ mov eax, r9d
+ mov eax, r10d
+ mov eax, r11d
+ mov eax, r12d
+ mov eax, r13d
+ mov eax, r14d
+ mov eax, r15d
+%endif
+
+%if TEST_BITS == 64
+ mov rax, rax
+ mov rax, rbx
+ mov rax, rcx
+ mov rax, rdx
+ mov rax, rsi
+ mov rax, rdi
+ mov rax, rbp
+ mov rax, rsp
+ mov rax, r8
+ mov rax, r9
+ mov rax, r10
+ mov rax, r11
+ mov rax, r12
+ mov rax, r13
+ mov rax, r14
+ mov rax, r15
+%endif
+
diff --git a/src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm b/src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm
new file mode 100644
index 00000000..0b3228ca
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstAsmSignExtend-1.asm
@@ -0,0 +1,63 @@
+; $Id: tstAsmSignExtend-1.asm $
+;; @file
+; Disassembly testcase - Valid sign extension instructions.
+;
+; This is a build test, that means it will be assembled, disassembled,
+; then the disassembly output will be assembled and the new binary will
+; compared with the original.
+;
+
+;
+; Copyright (C) 2008-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+%include "tstAsm.mac"
+ BITS TEST_BITS
+
+ movsx ax, al
+ movsx eax, al
+ movsx eax, ax
+
+ ;
+ ; ParseImmByteSX
+ ;
+
+ ; 83 /x
+ add eax, strict byte 8
+ add eax, strict byte -1
+ cmp ebx, strict byte -1
+
+ add ax, strict byte 8
+ add ax, strict byte -1
+ cmp bx, strict byte -1
+
+%if TEST_BITS == 64 ; check that these come out with qword values and not words or dwords.
+ add rax, strict byte 8
+ add rax, strict byte -1
+ cmp rbx, strict byte -1
+%endif
+
+ ; push %Ib
+ push strict byte -1
+ push strict byte -128
+ push strict byte 127
+
+ ;; @todo imul
diff --git a/src/VBox/Disassembler/testcase/tstBinFnstsw-1.bin b/src/VBox/Disassembler/testcase/tstBinFnstsw-1.bin
new file mode 100644
index 00000000..b23f6031
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstBinFnstsw-1.bin
Binary files differ
diff --git a/src/VBox/Disassembler/testcase/tstBinMovzx-1.bin b/src/VBox/Disassembler/testcase/tstBinMovzx-1.bin
new file mode 100644
index 00000000..e6db7adf
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstBinMovzx-1.bin
@@ -0,0 +1 @@
+·@ \ No newline at end of file
diff --git a/src/VBox/Disassembler/testcase/tstDisasm-1.cpp b/src/VBox/Disassembler/testcase/tstDisasm-1.cpp
new file mode 100644
index 00000000..015fdf58
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstDisasm-1.cpp
@@ -0,0 +1,214 @@
+/* $Id: tstDisasm-1.cpp $ */
+/** @file
+ * VBox disassembler - Test application
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include <iprt/test.h>
+#include <iprt/ctype.h>
+#include <iprt/string.h>
+#include <iprt/errcore.h>
+#include <iprt/time.h>
+
+
+DECLASM(int) TestProc32(void);
+DECLASM(int) TestProc32_EndProc(void);
+#ifndef RT_OS_OS2
+DECLASM(int) TestProc64(void);
+DECLASM(int) TestProc64_EndProc(void);
+#endif
+//uint8_t aCode16[] = { 0x66, 0x67, 0x89, 0x07 };
+
+static void testDisas(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
+{
+ RTTestISub(pszSub);
+ size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
+ for (size_t off = 0; off < cbInstrs;)
+ {
+ DISSTATE Dis;
+ uint32_t cb = 1;
+#ifndef DIS_CORE_ONLY
+ uint32_t const cErrBefore = RTTestIErrorCount();
+ char szOutput[256] = {0};
+ int rc = DISInstrToStr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb, szOutput, sizeof(szOutput));
+
+ RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+ RTTESTI_CHECK(cb == Dis.cbInstr);
+ RTTESTI_CHECK(cb > 0);
+ RTTESTI_CHECK(cb <= 16);
+ RTStrStripR(szOutput);
+ RTTESTI_CHECK(szOutput[0]);
+ if (szOutput[0])
+ {
+ char *pszBytes = strchr(szOutput, '[');
+ RTTESTI_CHECK(pszBytes);
+ if (pszBytes)
+ {
+ RTTESTI_CHECK(pszBytes[-1] == ' ');
+ RTTESTI_CHECK(RT_C_IS_XDIGIT(pszBytes[1]));
+ RTTESTI_CHECK(pszBytes[cb * 3] == ']');
+ RTTESTI_CHECK(pszBytes[cb * 3 + 1] == ' ');
+
+ size_t cch = strlen(szOutput);
+ RTTESTI_CHECK(szOutput[cch - 1] != ',');
+ }
+ }
+ if (cErrBefore != RTTestIErrorCount())
+ RTTestIFailureDetails("rc=%Rrc, off=%#x (%u) cbInstr=%u enmDisCpuMode=%d\n",
+ rc, off, off, Dis.cbInstr, enmDisCpuMode);
+ RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput);
+
+ /* Check with size-only. */
+ uint32_t cbOnly = 1;
+ DISSTATE DisOnly;
+ rc = DISInstrWithPrefetchedBytes((uintptr_t)&pabInstrs[off], enmDisCpuMode, 0 /*fFilter - none */,
+ Dis.abInstr, Dis.cbCachedInstr, NULL, NULL, &DisOnly, &cbOnly);
+
+ RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+ RTTESTI_CHECK(cbOnly == DisOnly.cbInstr);
+ RTTESTI_CHECK_MSG(cbOnly == cb, ("%#x vs %#x\n", cbOnly, cb));
+
+#else /* DIS_CORE_ONLY */
+ int rc = DISInstr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb);
+ RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+ RTTESTI_CHECK(cb == Dis.cbInstr);
+#endif /* DIS_CORE_ONLY */
+
+ off += cb;
+ }
+}
+
+
+static DECLCALLBACK(int) testReadBytes(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
+{
+ RT_NOREF1(cbMinRead);
+ memcpy(&pDis->abInstr[offInstr], (void *)((uintptr_t)pDis->uInstrAddr + offInstr), cbMaxRead);
+ pDis->cbCachedInstr = offInstr + cbMaxRead;
+ return VINF_SUCCESS;
+}
+
+
+static void testPerformance(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
+{
+ RTTestISubF("Performance - %s", pszSub);
+
+ size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
+ uint64_t cInstrs = 0;
+ uint64_t nsStart = RTTimeNanoTS();
+ for (uint32_t i = 0; i < _512K; i++) /* the samples are way to small. :-) */
+ {
+ for (size_t off = 0; off < cbInstrs; cInstrs++)
+ {
+ uint32_t cb = 1;
+ DISSTATE Dis;
+ DISInstrWithReader((uintptr_t)&pabInstrs[off], enmDisCpuMode, testReadBytes, NULL, &Dis, &cb);
+ off += cb;
+ }
+ }
+ uint64_t cNsElapsed = RTTimeNanoTS() - nsStart;
+
+ RTTestIValueF(cNsElapsed, RTTESTUNIT_NS, "%s-Total", pszSub);
+ RTTestIValueF(cNsElapsed / cInstrs, RTTESTUNIT_NS_PER_CALL, "%s-per-instruction", pszSub);
+}
+
+void testTwo(void)
+{
+ static const struct
+ {
+ DISCPUMODE enmMode;
+ uint8_t abInstr[24];
+ uint8_t cbParam1;
+ uint8_t cbParam2;
+ uint8_t cbParam3;
+ } s_gInstrs[] =
+ {
+ { DISCPUMODE_64BIT, { 0x48, 0xc7, 0x03, 0x00, 0x00, 0x00, 0x00, }, 8, 8, 0, },
+ };
+ for (unsigned i = 0; i < RT_ELEMENTS(s_gInstrs); i++)
+ {
+ uint32_t cb = 1;
+ DISSTATE Dis;
+ int rc;
+ RTTESTI_CHECK_RC(rc = DISInstr(s_gInstrs[i].abInstr, s_gInstrs[i].enmMode, &Dis, &cb), VINF_SUCCESS);
+ if (rc == VINF_SUCCESS)
+ {
+ uint32_t cb2;
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param1)) == s_gInstrs[i].cbParam1,
+ ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam1));
+#ifndef DIS_CORE_ONLY
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param2)) == s_gInstrs[i].cbParam2,
+ ("%u: %#x vs %#x (%s)\n", i , cb2, s_gInstrs[i].cbParam2, Dis.pCurInstr->pszOpcode));
+#else
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param2)) == s_gInstrs[i].cbParam2,
+ ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam2));
+#endif
+ RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param3)) == s_gInstrs[i].cbParam3,
+ ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam3));
+ }
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ RT_NOREF2(argc, argv);
+ RTTEST hTest;
+ RTEXITCODE rcExit = RTTestInitAndCreate("tstDisasm", &hTest);
+ if (rcExit)
+ return rcExit;
+ RTTestBanner(hTest);
+
+ static const struct
+ {
+ const char *pszDesc;
+ uint8_t const *pbStart;
+ uintptr_t uEndPtr;
+ DISCPUMODE enmCpuMode;
+ } aSnippets[] =
+ {
+ { "32-bit", (uint8_t const *)(uintptr_t)TestProc32, (uintptr_t)&TestProc32_EndProc, DISCPUMODE_32BIT },
+#ifndef RT_OS_OS2
+ { "64-bit", (uint8_t const *)(uintptr_t)TestProc64, (uintptr_t)&TestProc64_EndProc, DISCPUMODE_64BIT },
+#endif
+ };
+
+ for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
+ testDisas(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
+
+ testTwo();
+
+ if (RTTestIErrorCount() == 0)
+ {
+ for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
+ testPerformance(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
+ }
+
+ return RTTestSummaryAndDestroy(hTest);
+}
+
diff --git a/src/VBox/Disassembler/testcase/tstDisasm-1A.asm b/src/VBox/Disassembler/testcase/tstDisasm-1A.asm
new file mode 100644
index 00000000..112f7037
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstDisasm-1A.asm
@@ -0,0 +1,474 @@
+; $Id: tstDisasm-1A.asm $
+;; @file
+; VBox disassembler: Assembler test routines
+;
+
+;
+; Copyright (C) 2006-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+;*******************************************************************************
+;* Header Files *
+;*******************************************************************************
+%include "iprt/asmdefs.mac"
+;%include "VBox/vmm/vm.mac"
+;%include "VBox/err.mac"
+;%include "VBox/vmm/stam.mac"
+;%include "iprt/x86.mac"
+
+BITS 32
+
+%ifndef __YASM_VERSION_ID__
+ %define __YASM_VERSION_ID__ 001010000h ; v1.2.0.0 for OS/2
+%endif
+%if __YASM_VERSION_ID__ >= 001020001h ; v1.2.0.1 and greater, make sure to exclude v1.2.0.0.
+ %define pmulhrwa pmulhrw
+%endif
+
+
+BEGINCODE
+
+align 16
+BEGINPROC TestProc32
+ xor eax, eax
+ mov al, 4
+ lea edx, [4]
+ mov edx, 4
+ mov eax, 4
+ shl eax, 4
+ shl edx, 4
+ shr edx, 4
+ mov eax, edx
+ mov eax, ecx
+ mov edx, eax
+ mov ecx, eax
+ DB 0xF0, 0x0F, 0x22, 0xC0
+ DB 0xF0, 0x0F, 0x20, 0xC0
+ smsw word [edx+16]
+ ; invept eax, dqword [ecx]
+ DB 0x66, 0x0F, 0x38, 0x80, 0x1
+ ; invept eax, dqword [ecx]
+ DB 0x66, 0x0F, 0x38, 0x81, 0x1
+ mov eax, dword [ecx]
+ mov word [edi], 0123ah
+ movzx eax,byte [edx]
+ movzx eax,word [edx]
+ mov dword [es:ebx + 1234h], 0789h
+ mov word [fs:ebx + ecx], 0654h
+ mov byte [esi + eax*4], 054h
+ mov bl, byte [ds:ebp + 1234h]
+ mov al, [cs:1234h + ecx*8]
+ mov al, [cs:1234h]
+ mov ax, [cs:1234h]
+ mov eax, [cs:1234h]
+ lock cmpxchg [ecx], eax
+ lock cmpxchg [ecx], ax
+ lock cmpxchg [ecx], dl
+ movzx ESI,word [EAX]
+ in al, dx
+ in ax, dx
+ in eax, dx
+ mov ebx, [ecx + eax*4 + 17]
+ mov ebx, [ebp + eax*4 + 4]
+ mov ebx, [ebp + eax*4]
+ int 80h
+ in al, 60h
+ in ax, dx
+ out 64h, eax
+
+ movss xmm0, xmm1
+ movss xmm3, [eax]
+ movss [eax], xmm4
+ movsd xmm6, xmm1
+
+ pause
+ nop
+
+ ; 3Dnow!
+ pavgusb mm1, mm0
+ pf2id mm5, mm4
+ pf2iw mm6, mm3
+ pfacc mm7, mm2
+ pfadd mm5, mm4
+ pfcmpeq mm6, mm3
+ pfcmpge mm2, mm7
+ pfcmpgt mm4, mm5
+ pfmax mm3, mm6
+ pfmin mm1, mm0
+ pfmul mm5, mm4
+ pmulhrwa mm3, mm6
+ pfnacc mm4, mm5
+ pfpnacc mm3, mm6
+ pfrcp mm0, mm1
+ pfrcpit1 mm2, mm7
+ pfrcpit2 mm4, mm5
+ pfrsqrt mm7, mm2
+ pfrsqit1 mm1, mm0
+ pfsub mm6, mm3
+ pfsubr mm0, mm1
+ pi2fd mm7, mm2
+ pi2fw mm0, mm1
+ pswapd mm2, mm7
+
+ pavgusb mm1, qword [es:eax+000000010h]
+ pf2id mm5, qword [ds:esi+000101010h]
+ pf2iw mm6, qword [fs:esi+000101010h]
+ pfacc mm7, qword [gs:esi+000101010h]
+ pfadd mm5, qword [ esi+000101010h]
+ pfcmpeq mm6, qword [ edi*8+000101010h]
+ pfcmpge mm2, qword [es:esi+000100010h]
+ pfcmpgt mm4, qword [es:esi+000101010h]
+ pfmax mm3, qword [es:esi+000101010h]
+ pfmin mm1, qword [es:esi+000101010h]
+ pfmul mm5, qword [es:esi+000101000h]
+%ifndef RT_OS_OS2 ; nasm objects to this
+ pmulhrwa mm3, qword [es:eax+0ffffffffh]
+%endif
+ pfnacc mm4, qword [es:ebx+000101010h]
+ pfpnacc mm3, qword [es:edx+000102900h]
+ pfrcp mm0, qword [es:ecx+000101020h]
+ pfrcpit1 mm2, qword [es:ebp+000101510h]
+ pfrcpit2 mm4, qword [es:esp+000101310h]
+ pfrsqrt mm7, qword [es:esi+0f0106010h]
+ pfrsqit1 mm1, qword [es:edi+0001f1010h]
+ pfsub mm6, qword [es:esi*2]
+ pfsubr mm0, qword [es:esi*3]
+ pi2fd mm7, qword [es:esi*4]
+ pi2fw mm0, qword [es:esi*5]
+ pswapd mm2, qword [es:esi*8]
+
+ pmulhrwa mm0, qword [ds:ebp+edi*8+00f000001h]
+
+ ; MMX
+ psubusb mm1, mm3
+ cvtpi2pd xmm0, mm3
+ paddd mm1, mm3
+ paddd xmm1, xmm3
+
+%if __YASM_VERSION_ID__ >= 001030000h ; Old yasm doesn't support the instructions below
+ adcx eax, ebx
+ adcx eax, [edi]
+
+ adox eax, ebx
+ adox eax, [edi]
+ adox eax, [edi + 1000h]
+
+ tzcnt ax, bx
+ tzcnt eax, ebx
+ tzcnt ax, [edi]
+ tzcnt eax, [edi]
+ tzcnt eax, [edi + 1000h]
+ vpmovsxbw ymm0, xmm1
+ vpmovzxbq ymm1, [100h]
+ vgatherqps xmm0,dword [eax+xmm0*2],xmm0
+ vgatherqpd xmm0,qword [eax+xmm0*2],xmm0
+%endif
+
+ movbe eax, [edi]
+ movbe ebx, [edi + 1000h]
+ movbe ax, [edi]
+ movbe [edi], eax
+
+ crc32 eax, bl
+ crc32 eax, bx
+ crc32 eax, ebx
+ crc32 eax, byte [edi]
+ crc32 eax, word [edi]
+ crc32 eax, dword [edi]
+
+ popcnt ax, bx
+ popcnt eax, ebx
+ popcnt ax, [edi]
+ popcnt eax, [edi]
+ popcnt eax, [edi + 1000h]
+
+ lzcnt ax, bx
+ lzcnt eax, ebx
+ lzcnt ax, [edi]
+ lzcnt eax, [edi]
+ lzcnt eax, [edi + 1000h]
+
+ vmread eax, ebx
+ vmwrite eax, ebx
+
+ movd mm0, [edi]
+ movq mm0, [edi]
+ movq mm0, mm1
+
+ vmovups xmm0, xmm1
+ vmovaps ymm0, ymm1
+ vunpcklps xmm0, xmm1, xmm2
+ vunpcklps ymm0, ymm1, ymm2
+
+ lddqu xmm1, [ds:ebp+edi*8+00f000001h]
+ vlddqu xmm1, [ds:ebp+edi*8+00f000001h]
+ vlddqu ymm1, [ds:ebp+edi*8+00f000001h]
+
+ vpmovsxbw xmm0,qword [0x100]
+ vbroadcastf128 ymm0,oword [0x100]
+
+ palignr mm0, mm1, 1
+ vpinsrb xmm0, xmm1, eax, 1
+ vpinsrb xmm0, xmm1, [100h], 1
+ vinsertps xmm0, xmm1, xmm2, 1
+ vinsertps xmm0, xmm1, [100h], 1
+
+ vblendvps xmm0, xmm1, xmm2, xmm3
+ vblendvps ymm0, ymm1, ymm2, ymm3
+
+ aesimc xmm0, xmm1
+
+ pmovzxbq xmm0, xmm1
+ pmovzxbq xmm1, [100h]
+
+ vfmaddsub132pd ymm1, ymm2, ymm3
+
+%ifndef RT_OS_OS2
+ blsr eax, ebx
+ blsi eax, [ebx]
+%endif
+ db 0c4h, 0e2h, 0f8h, 0f3h, 01bh ; blsi rax, dword [ebx] - but VEX.W=1 is ignored, so same as previous
+%ifndef RT_OS_OS2
+ blsmsk eax, [ebx+edi*2]
+ shlx eax, ebx, ecx
+%endif
+
+ pmovmskb eax, mm2
+ pmovmskb eax, xmm3
+ vpmovmskb eax, xmm3
+%ifndef RT_OS_OS2
+ vpmovmskb eax, ymm3
+%endif
+
+ENDPROC TestProc32
+
+
+%ifndef RT_OS_OS2
+BITS 64
+align 16
+BEGINPROC TestProc64
+ mov cr8, rax
+ mov cr8, rbx
+ mov [0xfffe0080], rax
+ mov [0xfffe0080], rbx
+ mov rax, cr8
+ mov rbx, cr8
+ mov rax, [0xfffe0080]
+ mov rbx, [0xfffe0080]
+ divsd xmm1, xmm0
+ ; invept rdi, dqword [rsi]
+ DB 0x66, 0x0F, 0x38, 0x80, 0x3E
+ ; invept rcx, dqword [rdx]
+ DB 0x66, 0x0F, 0x38, 0x80, 0xA
+ ;invvpid rdi, dqword [rsi]
+ DB 0x66, 0x0F, 0x38, 0x81, 0x3E
+ ; invvpid rcx, dqword [rdx]
+ DB 0x66, 0x0F, 0x38, 0x81, 0xA
+ mov rdi, [rsi]
+ mov rcx, [rdx]
+ db 48h
+ db 0c7h
+ db 42h
+ db 18h
+ db 20h
+ db 3eh
+ db 23h
+ db 80h
+ call qword [r8+10h]
+ ; test
+ db 48h
+ db 8bh
+ db 44h
+ db 0ah
+ db 0f8h
+ ;incorrectly assembled by yasm; REX.W should not be added!
+ ;test rax, dword 0cc90cc90h
+ db 8bh
+ db 04h
+ db 8dh
+ db 00h
+ db 00h
+ db 0feh
+ db 0ffh
+ mov qword [rcx+rdx], 0
+ mov dword [rcx+rdx], 0
+ and [r15], rax
+ movzx rcx, sil
+ and sil, 3
+ movzx ecx, ah
+ and ah, 3
+
+ sub rcx, 1234h
+ mov rax, qword [0cc90cc90h]
+ mov rax, qword [00c90cc90h]
+ mov rax, dword 0cc90cc90h
+ mov rax, qword 0ffffcc90cc90h
+
+ movzx rax,byte [edx]
+ movzx rax,word [edx]
+ movzx rax,byte [rdx]
+ lock cmpxchg [rcx], rax
+ lock cmpxchg [rcx], ax
+ lock cmpxchg [r15], dl
+ movzx RSI, word [R8]
+ in al, dx
+ in ax, dx
+ in eax, dx
+ mov rbx, [rcx + rax*4 + 17]
+ mov rbx, [rbp + rax*4 + 4]
+ mov rbx, [rbp + rax*4]
+ mov rbx, [ebp + eax*4]
+ int 80h
+ in al, 60h
+ in ax, dx
+ out 64h, eax
+
+ movss xmm0, xmm14
+ movsd xmm6, xmm1
+
+ movbe eax, [rdi]
+ movbe ax, [rdi]
+ movbe rax, [rdi]
+
+ crc32 eax, bl
+ crc32 eax, bx
+ crc32 eax, ebx
+ crc32 eax, byte [edi]
+ crc32 eax, word [edi]
+ crc32 eax, dword [edi]
+
+ crc32 rax, bl
+ crc32 rax, byte [rdi]
+ crc32 rax, qword [rdi]
+
+%if __YASM_VERSION_ID__ >= 001030000h ; Old yasm doesn't support the instructions below
+
+ adcx eax, ebx
+ adcx rax, rbx
+ adcx r8, r11
+ adcx r8d, edx
+
+ adox eax, ebx
+ adox eax, [edi]
+ adox eax, [edi + 1000h]
+
+ adox rax, rbx
+ adox rax, [rdi]
+ adox rax, [rdi + 1000h]
+ adox rax, [edi + 1000h]
+
+ tzcnt ax, bx
+ tzcnt eax, ebx
+ tzcnt rax, rbx
+ tzcnt ax, [edi]
+ tzcnt eax, [edi]
+ tzcnt eax, [edi + 1000h]
+
+ vpunpcklbw ymm1, ymm2, ymm3
+ vpmovsxbw ymm4,[0x100]
+ vgatherqpd xmm0,qword [rbx+xmm11*2],xmm2
+%endif
+
+ popcnt ax, bx
+ popcnt eax, ebx
+ popcnt rax, rbx
+ popcnt ax, [edi]
+ popcnt eax, [edi]
+ popcnt eax, [edi + 1000h]
+ popcnt rax, [rdi + 1000h]
+
+ lzcnt ax, bx
+ lzcnt eax, ebx
+ lzcnt rax, rbx
+ lzcnt ax, [edi]
+ lzcnt eax, [edi]
+ lzcnt eax, [edi + 1000h]
+ lzcnt eax, [rdi]
+ lzcnt ax, [rdi]
+ lzcnt rax, [rdi]
+ lzcnt r8d, [rdi]
+
+ vmread rax, rbx
+ vmwrite rax, rbx
+
+ getsec
+
+ movd mm0, [rdi]
+ movq mm0, [edi]
+ movq mm0, mm1
+
+ vmovups xmm0, xmm1
+ vmovaps ymm0, ymm1
+ vunpcklps xmm0, xmm1, xmm2
+ vunpcklps ymm0, ymm1, ymm2
+ vunpcklps ymm0, ymm10, ymm2
+
+ vmovups xmm5, xmm9
+
+ vcmpps xmm1, xmm2, xmm3, 12
+
+ lddqu xmm1, [ebp+edi*8+00f000001h]
+ vlddqu xmm1, [rbp+rdi*8+00f000001h]
+ vlddqu ymm1, [rbp+rdi*8+00f000001h]
+
+ vbroadcastf128 ymm0,oword [0x100]
+ vmovlps xmm0, xmm1, [100h]
+ vmovlps xmm0, xmm1, [eax + ebx]
+ vmovlps xmm0, xmm1, [rax + rbx]
+ vmovlps xmm10, xmm1, [rax]
+
+ vblendvpd xmm0, xmm1, [100h], xmm3
+
+ dpps xmm0, xmm1, 1
+
+ extractps eax, xmm2, 3
+ vzeroupper
+ vzeroall
+
+ movlps xmm0, [100h]
+ movlps xmm0, [eax + ebx]
+ movlps xmm10, [rax + rbx]
+ movhlps xmm0, xmm1
+
+ blsr eax, ebx
+ blsr rax, rbx
+ blsi eax, [rbx]
+ blsi rax, [rbx]
+ db 0c4h, 0e2h, 0f8h | 4, 0f3h, 01bh ; blsi rax, [rbx] with VEX.L=1 - should be invalid
+ blsmsk eax, [rbx+rdi*2]
+ blsmsk rax, [rbx+rdi*2]
+ blsmsk r8, [rbx+rdi*2]
+
+ shlx eax, ebx, ecx
+ shlx r8, rax, r15
+
+ pmovmskb eax, mm2
+ pmovmskb r9, mm2
+ pmovmskb eax, xmm3
+ pmovmskb r10, xmm3
+ vpmovmskb eax, xmm3
+ vpmovmskb rax, xmm3
+ vpmovmskb r11, ymm9
+
+ ret
+ENDPROC TestProc64
+%endif ; !OS2
+
diff --git a/src/VBox/Disassembler/testcase/tstDisasm-2.cpp b/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
new file mode 100644
index 00000000..27ffc33b
--- /dev/null
+++ b/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
@@ -0,0 +1,693 @@
+/* $Id: tstDisasm-2.cpp $ */
+/** @file
+ * Testcase - Generic Disassembler Tool.
+ */
+
+/*
+ * Copyright (C) 2008-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/dis.h>
+#include <VBox/err.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/initterm.h>
+#include <iprt/getopt.h>
+#include <iprt/file.h>
+#include <iprt/path.h>
+#include <iprt/stream.h>
+#include <iprt/string.h>
+#include <iprt/ctype.h>
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+typedef enum { kAsmStyle_Default, kAsmStyle_yasm, kAsmStyle_masm, kAsmStyle_gas, kAsmStyle_invalid } ASMSTYLE;
+typedef enum { kUndefOp_Fail, kUndefOp_All, kUndefOp_DefineByte, kUndefOp_End } UNDEFOPHANDLING;
+
+typedef struct MYDISSTATE
+{
+ DISSTATE Dis;
+ uint64_t uAddress; /**< The current instruction address. */
+ uint8_t *pbInstr; /**< The current instruction (pointer). */
+ uint32_t cbInstr; /**< The size of the current instruction. */
+ bool fUndefOp; /**< Whether the current instruction is really an undefined opcode.*/
+ UNDEFOPHANDLING enmUndefOp; /**< How to treat undefined opcodes. */
+ int rc; /**< Set if we hit EOF. */
+ size_t cbLeft; /**< The number of bytes left. (read) */
+ uint8_t *pbNext; /**< The next byte. (read) */
+ uint64_t uNextAddr; /**< The address of the next byte. (read) */
+ char szLine[256]; /**< The disassembler text output. */
+} MYDISSTATE;
+typedef MYDISSTATE *PMYDISSTATE;
+
+
+
+/**
+ * Default style.
+ *
+ * @param pState The disassembler state.
+ */
+static void MyDisasDefaultFormatter(PMYDISSTATE pState)
+{
+ RTPrintf("%s", pState->szLine);
+}
+
+
+/**
+ * Yasm style.
+ *
+ * @param pState The disassembler state.
+ */
+static void MyDisasYasmFormatter(PMYDISSTATE pState)
+{
+ char szTmp[256];
+#if 0
+ /* a very quick hack. */
+ strcpy(szTmp, RTStrStripL(strchr(pState->szLine, ':') + 1));
+
+ char *psz = strrchr(szTmp, '[');
+ *psz = '\0';
+ RTStrStripR(szTmp);
+
+ psz = strstr(szTmp, " ptr ");
+ if (psz)
+ memset(psz, ' ', 5);
+
+ char *pszEnd = strchr(szTmp, '\0');
+ while (pszEnd - &szTmp[0] < 71)
+ *pszEnd++ = ' ';
+ *pszEnd = '\0';
+
+#else
+ size_t cch = DISFormatYasmEx(&pState->Dis, szTmp, sizeof(szTmp),
+ DIS_FMT_FLAGS_STRICT | DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_COMMENT
+ | DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_SPACED,
+ NULL, NULL);
+ Assert(cch < sizeof(szTmp));
+ while (cch < 71)
+ szTmp[cch++] = ' ';
+ szTmp[cch] = '\0';
+#endif
+
+ RTPrintf(" %s ; %s", szTmp, pState->szLine);
+}
+
+
+/**
+ * Masm style.
+ *
+ * @param pState The disassembler state.
+ */
+static void MyDisasMasmFormatter(PMYDISSTATE pState)
+{
+ RTPrintf("masm not implemented: %s", pState->szLine);
+}
+
+
+/**
+ * This is a temporary workaround for catching a few illegal opcodes
+ * that the disassembler is currently letting thru, just enough to make
+ * the assemblers happy.
+ *
+ * We're too close to a release to dare mess with these things now as
+ * they may consequences for performance and let alone introduce bugs.
+ *
+ * @returns true if it's valid. false if it isn't.
+ *
+ * @param pDis The disassembler output.
+ */
+static bool MyDisasIsValidInstruction(DISSTATE const *pDis)
+{
+ switch (pDis->pCurInstr->uOpcode)
+ {
+ /* These doesn't take memory operands. */
+ case OP_MOV_CR:
+ case OP_MOV_DR:
+ case OP_MOV_TR:
+ if (pDis->ModRM.Bits.Mod != 3)
+ return false;
+ break;
+
+ /* The 0x8f /0 variant of this instruction doesn't get its /r value verified. */
+ case OP_POP:
+ if ( pDis->bOpCode == 0x8f
+ && pDis->ModRM.Bits.Reg != 0)
+ return false;
+ break;
+
+ /* The 0xc6 /0 and 0xc7 /0 variants of this instruction don't get their /r values verified. */
+ case OP_MOV:
+ if ( ( pDis->bOpCode == 0xc6
+ || pDis->bOpCode == 0xc7)
+ && pDis->ModRM.Bits.Reg != 0)
+ return false;
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+
+/**
+ * @interface_method_impl{FNDISREADBYTES}
+ */
+static DECLCALLBACK(int) MyDisasInstrRead(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
+{
+ RT_NOREF1(cbMaxRead);
+ PMYDISSTATE pState = (PMYDISSTATE)pDis;
+ RTUINTPTR uSrcAddr = pState->Dis.uInstrAddr + offInstr;
+ if (RT_LIKELY( pState->uNextAddr == uSrcAddr
+ && pState->cbLeft >= cbMinRead))
+ {
+ /*
+ * Straight forward reading.
+ */
+ //size_t cbToRead = cbMaxRead;
+ size_t cbToRead = cbMinRead;
+ memcpy(&pState->Dis.abInstr[offInstr], pState->pbNext, cbToRead);
+ pState->Dis.cbCachedInstr = offInstr + (uint8_t)cbToRead;
+ pState->pbNext += cbToRead;
+ pState->cbLeft -= cbToRead;
+ pState->uNextAddr += cbToRead;
+ return VINF_SUCCESS;
+ }
+
+ if (pState->uNextAddr == uSrcAddr)
+ {
+ /*
+ * Reading too much.
+ */
+ if (pState->cbLeft > 0)
+ {
+ memcpy(&pState->Dis.abInstr[offInstr], pState->pbNext, pState->cbLeft);
+ offInstr += (uint8_t)pState->cbLeft;
+ cbMinRead -= (uint8_t)pState->cbLeft;
+ pState->pbNext += pState->cbLeft;
+ pState->uNextAddr += pState->cbLeft;
+ pState->cbLeft = 0;
+ }
+ memset(&pState->Dis.abInstr[offInstr], 0xcc, cbMinRead);
+ pState->rc = VERR_EOF;
+ }
+ else
+ {
+ /*
+ * Non-sequential read, that's an error.
+ */
+ RTStrmPrintf(g_pStdErr, "Reading before current instruction!\n");
+ memset(&pState->Dis.abInstr[offInstr], 0x90, cbMinRead);
+ pState->rc = VERR_INTERNAL_ERROR;
+ }
+ pState->Dis.cbCachedInstr = offInstr + cbMinRead;
+ return pState->rc;
+}
+
+
+/**
+ * Disassembles a block of memory.
+ *
+ * @returns VBox status code.
+ * @param argv0 Program name (for errors and warnings).
+ * @param enmCpuMode The cpu mode to disassemble in.
+ * @param uAddress The address we're starting to disassemble at.
+ * @param uHighlightAddr The address of the instruction that should be
+ * highlighted. Pass UINT64_MAX to keep quiet.
+ * @param pbFile Where to start disassemble.
+ * @param cbFile How much to disassemble.
+ * @param enmStyle The assembly output style.
+ * @param fListing Whether to print in a listing like mode.
+ * @param enmUndefOp How to deal with undefined opcodes.
+ */
+static int MyDisasmBlock(const char *argv0, DISCPUMODE enmCpuMode, uint64_t uAddress,
+ uint64_t uHighlightAddr, uint8_t *pbFile, size_t cbFile,
+ ASMSTYLE enmStyle, bool fListing, UNDEFOPHANDLING enmUndefOp)
+{
+ RT_NOREF1(fListing);
+
+ /*
+ * Initialize the CPU context.
+ */
+ MYDISSTATE State;
+ State.uAddress = uAddress;
+ State.pbInstr = pbFile;
+ State.cbInstr = 0;
+ State.enmUndefOp = enmUndefOp;
+ State.rc = VINF_SUCCESS;
+ State.cbLeft = cbFile;
+ State.pbNext = pbFile;
+ State.uNextAddr = uAddress;
+
+ void (*pfnFormatter)(PMYDISSTATE pState);
+ switch (enmStyle)
+ {
+ case kAsmStyle_Default:
+ pfnFormatter = MyDisasDefaultFormatter;
+ break;
+
+ case kAsmStyle_yasm:
+ RTPrintf(" BITS %d\n", enmCpuMode == DISCPUMODE_16BIT ? 16 : enmCpuMode == DISCPUMODE_32BIT ? 32 : 64);
+ pfnFormatter = MyDisasYasmFormatter;
+ break;
+
+ case kAsmStyle_masm:
+ pfnFormatter = MyDisasMasmFormatter;
+ break;
+
+ default:
+ AssertFailedReturn(VERR_INTERNAL_ERROR);
+ }
+
+ /*
+ * The loop.
+ */
+ int rcRet = VINF_SUCCESS;
+ while (State.cbLeft > 0)
+ {
+ /*
+ * Disassemble it.
+ */
+ State.cbInstr = 0;
+ State.cbLeft += State.pbNext - State.pbInstr;
+ State.uNextAddr = State.uAddress;
+ State.pbNext = State.pbInstr;
+
+ int rc = DISInstrToStrWithReader(State.uAddress, enmCpuMode, MyDisasInstrRead, &State,
+ &State.Dis, &State.cbInstr, State.szLine, sizeof(State.szLine));
+ if ( RT_SUCCESS(rc)
+ || ( ( rc == VERR_DIS_INVALID_OPCODE
+ || rc == VERR_DIS_GEN_FAILURE)
+ && State.enmUndefOp == kUndefOp_DefineByte))
+ {
+ State.fUndefOp = rc == VERR_DIS_INVALID_OPCODE
+ || rc == VERR_DIS_GEN_FAILURE
+ || State.Dis.pCurInstr->uOpcode == OP_INVALID
+ || State.Dis.pCurInstr->uOpcode == OP_ILLUD2
+ || ( State.enmUndefOp == kUndefOp_DefineByte
+ && !MyDisasIsValidInstruction(&State.Dis));
+ if (State.fUndefOp && State.enmUndefOp == kUndefOp_DefineByte)
+ {
+ if (!State.cbInstr)
+ {
+ State.Dis.abInstr[0] = 0;
+ State.Dis.pfnReadBytes(&State.Dis, 0, 1, 1);
+ State.cbInstr = 1;
+ }
+ RTPrintf(" db");
+ for (unsigned off = 0; off < State.cbInstr; off++)
+ RTPrintf(off ? ", %03xh" : " %03xh", State.Dis.abInstr[off]);
+ RTPrintf(" ; %s\n", State.szLine);
+ }
+ else if (!State.fUndefOp && State.enmUndefOp == kUndefOp_All)
+ {
+ RTPrintf("%s: error at %#RX64: unexpected valid instruction (op=%d)\n", argv0, State.uAddress, State.Dis.pCurInstr->uOpcode);
+ pfnFormatter(&State);
+ rcRet = VERR_GENERAL_FAILURE;
+ }
+ else if (State.fUndefOp && State.enmUndefOp == kUndefOp_Fail)
+ {
+ RTPrintf("%s: error at %#RX64: undefined opcode (op=%d)\n", argv0, State.uAddress, State.Dis.pCurInstr->uOpcode);
+ pfnFormatter(&State);
+ rcRet = VERR_GENERAL_FAILURE;
+ }
+ else
+ {
+ /* Use db for odd encodings that we can't make the assembler use. */
+ if ( State.enmUndefOp == kUndefOp_DefineByte
+ && DISFormatYasmIsOddEncoding(&State.Dis))
+ {
+ RTPrintf(" db");
+ for (unsigned off = 0; off < State.cbInstr; off++)
+ RTPrintf(off ? ", %03xh" : " %03xh", State.Dis.abInstr[off]);
+ RTPrintf(" ; ");
+ }
+
+ pfnFormatter(&State);
+ }
+ }
+ else
+ {
+ State.cbInstr = State.pbNext - State.pbInstr;
+ if (!State.cbLeft)
+ RTPrintf("%s: error at %#RX64: read beyond the end (%Rrc)\n", argv0, State.uAddress, rc);
+ else if (State.cbInstr)
+ RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d\n", argv0, State.uAddress, rc, State.cbInstr);
+ else
+ {
+ RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d!\n", argv0, State.uAddress, rc, State.cbInstr);
+ if (rcRet == VINF_SUCCESS)
+ rcRet = rc;
+ break;
+ }
+ }
+
+ /* Highlight this instruction? */
+ if (uHighlightAddr - State.uAddress < State.cbInstr)
+ RTPrintf("; ^^^^^^^^^^^^^^^^^^^^^\n");
+
+ /* Check that the size-only mode returns the smae size on success. */
+ if (RT_SUCCESS(rc))
+ {
+ uint32_t cbInstrOnly = 32;
+ uint8_t abInstr[sizeof(State.Dis.abInstr)];
+ memcpy(abInstr, State.Dis.abInstr, sizeof(State.Dis.abInstr));
+ int rcOnly = DISInstrWithPrefetchedBytes(State.uAddress, enmCpuMode, 0 /*fFilter - none */,
+ abInstr, State.Dis.cbCachedInstr, MyDisasInstrRead, &State,
+ &State.Dis, &cbInstrOnly);
+ if ( rcOnly != rc
+ || cbInstrOnly != State.cbInstr)
+ {
+ RTPrintf("; Instruction size only check failed rc=%Rrc cbInstrOnly=%#x exepcted %Rrc and %#x\n",
+ rcOnly, cbInstrOnly, rc, State.cbInstr);
+ rcRet = VERR_GENERAL_FAILURE;
+ break;
+ }
+ }
+
+ /* next */
+ State.uAddress += State.cbInstr;
+ State.pbInstr += State.cbInstr;
+ }
+
+ return rcRet;
+}
+
+/**
+ * Converts a hex char to a number.
+ *
+ * @returns 0..15 on success, -1 on failure.
+ * @param ch The character.
+ */
+static int HexDigitToNum(char ch)
+{
+ switch (ch)
+ {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'A':
+ case 'a': return 0xa;
+ case 'B':
+ case 'b': return 0xb;
+ case 'C':
+ case 'c': return 0xc;
+ case 'D':
+ case 'd': return 0xd;
+ case 'E':
+ case 'e': return 0xe;
+ case 'F':
+ case 'f': return 0xf;
+ default:
+ RTPrintf("error: Invalid hex digit '%c'\n", ch);
+ return -1;
+ }
+}
+
+/**
+ * Prints usage info.
+ *
+ * @returns 1.
+ * @param argv0 The program name.
+ */
+static int Usage(const char *argv0)
+{
+ RTStrmPrintf(g_pStdErr,
+"usage: %s [options] <file1> [file2..fileN]\n"
+" or: %s [options] <-x|--hex-bytes> <hex byte> [more hex..]\n"
+" or: %s <--help|-h>\n"
+"\n"
+"Options:\n"
+" --address|-a <address>\n"
+" The base address. Default: 0\n"
+" --max-bytes|-b <bytes>\n"
+" The maximum number of bytes to disassemble. Default: 1GB\n"
+" --cpumode|-c <16|32|64>\n"
+" The cpu mode. Default: 32\n"
+" --listing|-l, --no-listing|-L\n"
+" Enables or disables listing mode. Default: --no-listing\n"
+" --offset|-o <offset>\n"
+" The file offset at which to start disassembling. Default: 0\n"
+" --style|-s <default|yasm|masm>\n"
+" The assembly output style. Default: default\n"
+" --undef-op|-u <fail|all|db>\n"
+" How to treat undefined opcodes. Default: fail\n"
+ , argv0, argv0, argv0);
+ return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+ RTR3InitExe(argc, &argv, 0);
+ const char * const argv0 = RTPathFilename(argv[0]);
+
+ /* options */
+ uint64_t uAddress = 0;
+ uint64_t uHighlightAddr = UINT64_MAX;
+ ASMSTYLE enmStyle = kAsmStyle_Default;
+ UNDEFOPHANDLING enmUndefOp = kUndefOp_Fail;
+ bool fListing = true;
+ DISCPUMODE enmCpuMode = DISCPUMODE_32BIT;
+ RTFOFF off = 0;
+ RTFOFF cbMax = _1G;
+ bool fHexBytes = false;
+
+ /*
+ * Parse arguments.
+ */
+ static const RTGETOPTDEF g_aOptions[] =
+ {
+ { "--address", 'a', RTGETOPT_REQ_UINT64 },
+ { "--cpumode", 'c', RTGETOPT_REQ_UINT32 },
+ { "--bytes", 'b', RTGETOPT_REQ_INT64 },
+ { "--listing", 'l', RTGETOPT_REQ_NOTHING },
+ { "--no-listing", 'L', RTGETOPT_REQ_NOTHING },
+ { "--offset", 'o', RTGETOPT_REQ_INT64 },
+ { "--style", 's', RTGETOPT_REQ_STRING },
+ { "--undef-op", 'u', RTGETOPT_REQ_STRING },
+ { "--hex-bytes", 'x', RTGETOPT_REQ_NOTHING },
+ };
+
+ int ch;
+ RTGETOPTUNION ValueUnion;
+ RTGETOPTSTATE GetState;
+ RTGetOptInit(&GetState, argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
+ while ( (ch = RTGetOpt(&GetState, &ValueUnion))
+ && ch != VINF_GETOPT_NOT_OPTION)
+ {
+ switch (ch)
+ {
+ case 'a':
+ uAddress = ValueUnion.u64;
+ break;
+
+ case 'b':
+ cbMax = ValueUnion.i64;
+ break;
+
+ case 'c':
+ if (ValueUnion.u32 == 16)
+ enmCpuMode = DISCPUMODE_16BIT;
+ else if (ValueUnion.u32 == 32)
+ enmCpuMode = DISCPUMODE_32BIT;
+ else if (ValueUnion.u32 == 64)
+ enmCpuMode = DISCPUMODE_64BIT;
+ else
+ {
+ RTStrmPrintf(g_pStdErr, "%s: Invalid CPU mode value %RU32\n", argv0, ValueUnion.u32);
+ return 1;
+ }
+ break;
+
+ case 'h':
+ return Usage(argv0);
+
+ case 'l':
+ fListing = true;
+ break;
+
+ case 'L':
+ fListing = false;
+ break;
+
+ case 'o':
+ off = ValueUnion.i64;
+ break;
+
+ case 's':
+ if (!strcmp(ValueUnion.psz, "default"))
+ enmStyle = kAsmStyle_Default;
+ else if (!strcmp(ValueUnion.psz, "yasm"))
+ enmStyle = kAsmStyle_yasm;
+ else if (!strcmp(ValueUnion.psz, "masm"))
+ {
+ enmStyle = kAsmStyle_masm;
+ RTStrmPrintf(g_pStdErr, "%s: masm style isn't implemented yet\n", argv0);
+ return 1;
+ }
+ else
+ {
+ RTStrmPrintf(g_pStdErr, "%s: unknown assembly style: %s\n", argv0, ValueUnion.psz);
+ return 1;
+ }
+ break;
+
+ case 'u':
+ if (!strcmp(ValueUnion.psz, "fail"))
+ enmUndefOp = kUndefOp_Fail;
+ else if (!strcmp(ValueUnion.psz, "all"))
+ enmUndefOp = kUndefOp_All;
+ else if (!strcmp(ValueUnion.psz, "db"))
+ enmUndefOp = kUndefOp_DefineByte;
+ else
+ {
+ RTStrmPrintf(g_pStdErr, "%s: unknown undefined opcode handling method: %s\n", argv0, ValueUnion.psz);
+ return 1;
+ }
+ break;
+
+ case 'x':
+ fHexBytes = true;
+ break;
+
+ case 'V':
+ RTPrintf("$Revision: 155244 $\n");
+ return 0;
+
+ default:
+ return RTGetOptPrintError(ch, &ValueUnion);
+ }
+ }
+ int iArg = GetState.iNext - 1; /** @todo Not pretty, add RTGetOptInit flag for this. */
+ if (iArg >= argc)
+ return Usage(argv0);
+
+ int rc = VINF_SUCCESS;
+ if (fHexBytes)
+ {
+ /*
+ * Convert the remaining arguments from a hex byte string into
+ * a buffer that we disassemble.
+ */
+ size_t cb = 0;
+ uint8_t *pb = NULL;
+ for ( ; iArg < argc; iArg++)
+ {
+ char ch2;
+ const char *psz = argv[iArg];
+ while (*psz)
+ {
+ /** @todo this stuff belongs in IPRT, same stuff as mac address reading. Could be reused for IPv6 with a different item size.*/
+ /* skip white space, and for the benefit of linux panics '<' and '>'. */
+ while (RT_C_IS_SPACE(ch2 = *psz) || ch2 == '<' || ch2 == '>' || ch2 == ',' || ch2 == ';')
+ {
+ if (ch2 == '<')
+ uHighlightAddr = uAddress + cb;
+ psz++;
+ }
+
+ if (ch2 == '0' && (psz[1] == 'x' || psz[1] == 'X'))
+ {
+ psz += 2;
+ ch2 = *psz;
+ }
+
+ if (!ch2)
+ break;
+
+ /* one digit followed by a space or EOS, or two digits. */
+ int iNum = HexDigitToNum(*psz++);
+ if (iNum == -1)
+ return 1;
+ if (!RT_C_IS_SPACE(ch2 = *psz) && ch2 != '\0' && ch2 != '>' && ch2 != ',' && ch2 != ';')
+ {
+ int iDigit = HexDigitToNum(*psz++);
+ if (iDigit == -1)
+ return 1;
+ iNum = iNum * 16 + iDigit;
+ }
+
+ /* add the byte */
+ if (!(cb % 4 /*64*/))
+ {
+ pb = (uint8_t *)RTMemRealloc(pb, cb + 64);
+ if (!pb)
+ {
+ RTPrintf("%s: error: RTMemRealloc failed\n", argv[0]);
+ return 1;
+ }
+ }
+ pb[cb++] = (uint8_t)iNum;
+ }
+ }
+
+ /*
+ * Disassemble it.
+ */
+ rc = MyDisasmBlock(argv0, enmCpuMode, uAddress, uHighlightAddr, pb, cb, enmStyle, fListing, enmUndefOp);
+ }
+ else
+ {
+ /*
+ * Process the files.
+ */
+ for ( ; iArg < argc; iArg++)
+ {
+ /*
+ * Read the file into memory.
+ */
+ void *pvFile;
+ size_t cbFile;
+ rc = RTFileReadAllEx(argv[iArg], off, cbMax, RTFILE_RDALL_O_DENY_NONE, &pvFile, &cbFile);
+ if (RT_FAILURE(rc))
+ {
+ RTStrmPrintf(g_pStdErr, "%s: %s: %Rrc\n", argv0, argv[iArg], rc);
+ break;
+ }
+
+ /*
+ * Disassemble it.
+ */
+ rc = MyDisasmBlock(argv0, enmCpuMode, uAddress, uHighlightAddr, (uint8_t *)pvFile, cbFile, enmStyle, fListing, enmUndefOp);
+ RTFileReadAllFree(pvFile, cbFile);
+ if (RT_FAILURE(rc))
+ break;
+ }
+ }
+
+ return RT_SUCCESS(rc) ? 0 : 1;
+}
+