DisasmCore.cpp revision c2e9d2e74a22023533b45a005c3e90a29d2eb216
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * VBox Disassembler - Core Components.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2012 Oracle Corporation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header Files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/*******************************************************************************
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync* Defined Constants And Macros *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync*******************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/** This must be less or equal to DISSTATE::abInstr. */
efff36b306e370346025647a158689021df2e1d1vboxsync/** Whether we can do unaligned access. */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync/*******************************************************************************
efff36b306e370346025647a158689021df2e1d1vboxsync* Internal Functions *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync/** @name Parsers
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/** Floating point parsing */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/*******************************************************************************
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync* Global Variables *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Parser opcode table for full disassembly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/** Parser opcode table for only calculating instruction size. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/********************************************************************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Read functions for getting the opcode bytes
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ********************************************************************************************************************************/
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr;
16a9adc14900ca18e6909679a579f6833425e030vboxsync size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Read more bytes into the DISSTATE::abInstr buffer, advance
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * DISSTATE::cbCachedInstr.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Will set DISSTATE::rc on failure, but still advance cbCachedInstr.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * The caller shall fend off reads beyond the DISSTATE::abInstr buffer.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param pDis The disassembler state.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param offInstr The offset of the read request.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param cbMin The size of the read request that needs to be
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * satisfied.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncDECL_NO_INLINE(static, void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Adjust the incoming request to not overlap with bytes that has already
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * been read and to make sure we don't leave unread gaps.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Do the read.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * (No need to zero anything on failure as abInstr is already zeroed by the
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * DISInstrEx API.)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Function for handling a 8-bit cache miss.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns The requested byte.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis The disassembler state.
aa834e89e076db44fa8fe82d177748f0a45d14c2vboxsync * @param offInstr The offset of the byte relative to the
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync * Read a byte (8-bit) instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested byte.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis The disassembler state.
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * @param uAddress The address.
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsyncDECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync * Function for handling a 16-bit cache miss.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns The requested word.
ffbe6daf773e38167f3cabaf1f063d84ecd063e9vboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the word relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsyncDECL_NO_INLINE(static, uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr + 2 > DIS_MAX_INSTR_LENGTH))
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync return *(uint16_t const *)&pDis->abInstr[offInstr];
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * Read a word (16-bit) instruction.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * @returns The requested word.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * @param pDis The disassembler state.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * @param offInstr The offset of the qword relative to the
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * instruction.
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsyncDECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync if (RT_UNLIKELY(offInstr + 2 > pDis->cbCachedInstr))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint16_t const *)&pDis->abInstr[offInstr];
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Function for handling a 32-bit cache miss.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested dword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param offInstr The offset of the dword relative to the
16a9adc14900ca18e6909679a579f6833425e030vboxsync * instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsyncDECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr + 4 > DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync switch ((RTUINTPTR)DIS_MAX_INSTR_LENGTH - offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint32_t const *)&pDis->abInstr[offInstr];
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * Read a dword (32-bit) instruction.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * @returns The requested dword.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * @param pDis The disassembler state.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync if (RT_UNLIKELY(offInstr + 4 > pDis->cbCachedInstr))
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return *(uint32_t const *)&pDis->abInstr[offInstr];
16a9adc14900ca18e6909679a579f6833425e030vboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Function for handling a 64-bit cache miss.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested qword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncDECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (RT_UNLIKELY(offInstr + 8 > DIS_MAX_INSTR_LENGTH))
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync switch ((RTUINTPTR)DIS_MAX_INSTR_LENGTH - offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5], 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
9496f2d398b49813176939d7a339ae513d5175efvboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Read a qword (64-bit) instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested qword.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param uAddress The address.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncDECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (RT_UNLIKELY(offInstr + 8 > pDis->cbCachedInstr))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync//*****************************************************************************
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync//*****************************************************************************
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncstatic size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
9496f2d398b49813176939d7a339ae513d5175efvboxsync // Store the opcode format string for disasmPrintf
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Note! Multibyte opcodes are always marked harmless until the final byte.
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync /* Not filtered out -> full disassembly */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync // Should contain the parameter type on input
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
16a9adc14900ca18e6909679a579f6833425e030vboxsync // else simple one byte instruction
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync/* Floating point opcode parsing */
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync // Should contain the parameter type on input
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Apply filter to instruction type to determine if a full disassembly is required.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* Not filtered out -> full disassembly */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Note: redundant, but just in case this ever changes */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // Little hack to make sure the ModRM byte is included in the returned size
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/********************************************************************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * SIB byte: (not 16-bit mode)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * 7 - 6 5 - 3 2-0
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Scale Index Base
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync ********************************************************************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // [scaled index] + disp32
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { /* sign-extend to 64 bits */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return; /* Already fetched everything in ParseSIB; no size returned */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Base field if not scaled index + disp32 */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Additional 32 bits displacement. No change in long mode. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Base field. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->SIB.Bits.Base |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.X extends the Index field. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Additional 32 bits displacement. No change in long mode. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/********************************************************************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * ModR/M byte:
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * 7 - 6 5 - 3 2-0
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ********************************************************************************************************************************/
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void disasmModRMReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, int fRegAddr)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* make gcc happy */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Intel� 64 and IA-32 Architectures Software Developer�s Manual: 3.4.1.1 */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsyncstatic void disasmModRMReg16(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX };
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync static const uint8_t s_auIndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI };
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Index.idxGenReg = s_auIndexModRMReg16[idx];
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsyncstatic void disasmModRMSReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic size_t UseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break; /* memory operand */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg = rm; /* the RM field specifies the xmm register */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else no break */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /** @todo bound */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { //register address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {//16 bits addressing mode
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {//16 bits displacement
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT8;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT16;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync// Query the size of the ModRM parameters and fetch the immediate data (if any)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t QueryModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (mod != 3 && rm == 4) /* SIB byte follows ModRM */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case 0: /* Effective address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 16 bits mode */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: /* Effective address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->i32SibDisp = (int16_t)disReadWord(pDis, offInstr);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync// Parse the ModRM parameters and fetch the immediate data (if any)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t QueryModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
51a01524909c95ee04b636218b6a89b29fb81825vboxsync { /* SIB byte follows ModRM */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync offInstr = ParseSIB_SizeOnly(offInstr, pOp, pDis, pParam);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 0: //effective address
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* else register address */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 1: /* Effective address + 8 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 16 bits mode */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncstatic size_t ParseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* Disregard the mod bits for certain instructions (mov crx, mov drx).
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * From the AMD manual:
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
51a01524909c95ee04b636218b6a89b29fb81825vboxsync * encoding of the MOD field in the MODR/M byte.
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* REX.R extends the Reg field. */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = QueryModRM(offInstr, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
51a01524909c95ee04b636218b6a89b29fb81825vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Disregard the mod bits for certain instructions (mov crx, mov drx).
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * From the AMD manual:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
217fa436516d137a409bb493cb7d350898f64666vboxsync * encoding of the MOD field in the MODR/M byte.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.R extends the Reg field. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync offInstr += QueryModRM_SizeOnly(offInstr, pOp, pDis, pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* UseModRM is not necessary here; we're only interested in the opcode size */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseModFence(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* Note! Only used in group 15, so we must account for the mod/rm byte. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByte(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByte_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByteSX(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = (uint32_t)(int8_t)disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = (uint64_t)(int8_t)disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pParam->uValue = (uint16_t)(int8_t)disReadByte(pDis, offInstr);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmByteSX_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUshort(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUshort_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUlong(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmUlong_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmQword(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmQword_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmV(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseImmV_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmZ(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* 64 bits op mode means *sign* extend to 64 bits. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmZ_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return sizeof(uint16_t);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync// Relative displacement for branches (rel. to next instruction)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmBRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// Relative displacement for branches (rel. to next instruction)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmBRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync// Relative displacement for branches (rel. to next instruction)
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmVRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 32 bits relative immediate sign extended to 64 bits. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmVRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Both 32 & 64 bits mode use 32 bits relative immediates. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmAddr(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* far 16:32 pointer */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
16a9adc14900ca18e6909679a579f6833425e030vboxsync * near 32 bits pointer
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
16a9adc14900ca18e6909679a579f6833425e030vboxsync * so we treat it like displacement.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * near 64 bits pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * so we treat it like displacement.
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* far 16:16 pointer */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * near 16 bits pointer
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * so we treat it like displacement.
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // far 16:32 pointer
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // far 16:16 pointer
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // immediate far pointers - only 16:16 or 16:32
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Sets up flags for stored in OPC fixed registers.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* No parameter at all. */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync /* 32-bit EAX..EDI registers. */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync /* Use 32-bit registers. */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync /* Use 64-bit registers. */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync /* Use 16-bit registers. */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Segment ES..GS registers. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* 16-bit AX..DI registers. */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN16_START;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* 8-bit AL..DL, AH..DH registers. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* FPU registers. */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* else - not supported for now registers. */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncstatic size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncstatic size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync /* This is used to avoid a bunch of special hacks to get the ModRM byte
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync included when encountering invalid opcodes in groups. */
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncstatic size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 2nd byte */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* default to the non-prefixed table. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
9daee41d5cb5a2e8390f015a486e67a6cd52b836vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 3rd byte */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* default to the non-prefixed table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Table entry is valid, so use the extension table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync /* Table entry is valid, so use the extension table. */
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync /* Cancel prefix changes. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 3rd byte */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* default to the non-prefixed table. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Table entry is valid, so use the extension table. */
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync /* Cancel prefix changes. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsync//*****************************************************************************
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncstatic size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync// It would appear the ModRM byte must always be present. How else can you
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync// determine the offset of the imm8_opcode byte otherwise?
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /** @todo This code needs testing! */
9496f2d398b49813176939d7a339ae513d5175efvboxsync size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync Assert(offStrict == offRet - 1); NOREF(offStrict); /* the imm8_opcode */
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync//*****************************************************************************
090d729e786b999dc285f8ea267f9effd1319544vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync /* Cannot easily skip this hack because of monitor and vmcall! */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync //little hack to make sure the ModRM byte is included in the returned size
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncstatic size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncstatic size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync//*****************************************************************************
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync//*****************************************************************************
61d064a54f03596920c3918f58ecc7764074a5d8vboxsyncstatic size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync//*****************************************************************************
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync//*****************************************************************************
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsyncstatic size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * Validates the lock sequence.
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * The AMD manual lists the following instructions:
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * CMPXCHG8B
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * CMPXCHG16B
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * @param pDis Fully disassembled instruction.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * Filter out the valid lock sequences.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync /* simple: no variations */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /* simple: /r - reject register destination. */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * Lots of variants but its sufficient to check that param 1
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * is a memory operand.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync * Invalid lock sequence, make it a OP_ILLUD2.
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync * Internal worker for DISInstEx.
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync * @returns VBox status code.
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync * @param pDis Initialized disassembler state.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param paOneByteMap The one byte opcode map to use.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pcbInstr Where to store the instruction size. Can be NULL.
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Parse byte by byte.
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Hardcoded assumption about OP_* values!! */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
16a9adc14900ca18e6909679a579f6833425e030vboxsync // segment override prefix byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync continue; //fetch the next byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // lock prefix byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync continue; //fetch the next byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // address size override prefix byte
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync continue; //fetch the next byte
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync // operand size override prefix byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync // rep and repne are not really prefixes, but we'll treat them as such
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* REX prefix byte */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
16a9adc14900ca18e6909679a579f6833425e030vboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* first opcode byte. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Inlined worker that initializes the disassembler state.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @returns The primary opcode map to use.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pDis The disassembler state.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param uInstrAddr The instruction address.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param enmCpuMode The CPU mode.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param fFilter The instruction filter settings.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pfnReadBytes The byte reader, can be NULL.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pvUser The the user data for the reader.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncdisInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Reads some bytes into the cache.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * While this will set DISSTATE::rc on failure, the caller should disregard
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * this since that is what would happen if we didn't prefetch bytes prior to the
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * instruction parsing.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pDis The disassembler state.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncDECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Read some bytes into the cache. (If this fail we continue as nothing
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * has gone wrong since this is what would happen if we didn't precharge
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * the cache here.)
c0a370e600bb60153a269fb32b5f709347c35768vboxsync int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
c0a370e600bb60153a269fb32b5f709347c35768vboxsync Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @returns VBox status code.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param uInstrAddr Address of the instruction to decode. What this means
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * is left to the pfnReadBytes function.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param fFilter Instruction type filter.
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pDis Pointer to disassembler state (output).
c0a370e600bb60153a269fb32b5f709347c35768vboxsync * @param pcbInstr Where to store the size of the instruction. (This
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * is also stored in PDISSTATE::cbInstr.) Optional.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncDISDECL(int) DISInstEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return disInstrWorker(pDis, paOneByteMap, pcbInstr);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * Disassembles on instruction partially or fully from prefetched bytes, details
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * in @a pDis and length in @a pcbInstr.
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync * @returns VBox status code.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param uInstrAddr Address of the instruction to decode. What this means
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * is left to the pfnReadBytes function.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pvPrefetched Pointer to the prefetched bytes.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param cbPrefetched The number of valid bytes pointed to by @a
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * pbPrefetched.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pfnReadBytes Callback for reading instruction bytes.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param fFilter Instruction type filter.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis Pointer to disassembler state (output).
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * @param pcbInstr Where to store the size of the instruction. (This
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * is also stored in PDISSTATE::cbInstr.) Optional.
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsyncDISDECL(int) DISInstWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return disInstrWorker(pDis, paOneByteMap, pcbInstr);
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsync * Parses one guest instruction.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * The result is found in pDis and pcbInstr.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @returns VBox status code.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param uInstrAddr Address of the instruction to decode. What this means
9496f2d398b49813176939d7a339ae513d5175efvboxsync * is left to the pfnReadBytes function.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * @param pDis Pointer to disassembler state (output).
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pcbInstr Where to store the size of the instruction.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * NULL is allowed. This is also stored in
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * PDISSTATE::cbInstr.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncDISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync return DISInstEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * Parses one guest instruction.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * The result is found in pDis and pcbInstr.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @returns VBox status code.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pvInstr Address of the instruction to decode. This is a
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * real address in the current context that can be
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * accessed without faulting. (Consider
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * DISInstrWithReader if this isn't the case.)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pDis Pointer to disassembler state (output).
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param pcbInstr Where to store the size of the instruction.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * NULL is allowed. This is also stored in
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * PDISSTATE::cbInstr.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncDISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return DISInstEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);