DisasmCore.cpp revision 03e8e21575a0d6ace51c528e7a6fcc35ce69cae7
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*******************************************************************************/
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync/*******************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync* Defined Constants And Macros *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync*******************************************************************************/
b0b15690f00527424b2d5fb88456d747252322f7vboxsync/** This must be less or equal to DISSTATE::abInstr.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync/** Whether we can do unaligned access. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Internal Functions *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
efff36b306e370346025647a158689021df2e1d1vboxsync/** @name Parsers
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync/** Floating point parsing */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/*******************************************************************************
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync* Global Variables *
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync*******************************************************************************/
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync/** Parser opcode table for full disassembly. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
16a9adc14900ca18e6909679a579f6833425e030vboxsync/** Parser opcode table for only calculating instruction size. */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/********************************************************************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Read functions for getting the opcode bytes
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ********************************************************************************************************************************/
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @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
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync * DISInstrEx API.)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Function for handling a 8-bit cache miss.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @returns The requested byte.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the byte relative to the
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * instruction.
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsyncDECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * Read a byte (8-bit) instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested byte.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param uAddress The address.
9496f2d398b49813176939d7a339ae513d5175efvboxsyncDECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * 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))
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return *(uint16_t const *)&pDis->abInstr[offInstr];
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Read a word (16-bit) instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @returns The requested word.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
9496f2d398b49813176939d7a339ae513d5175efvboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
16a9adc14900ca18e6909679a579f6833425e030vboxsync 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]);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * Function for handling a 32-bit cache miss.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @returns The requested dword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync * @param offInstr The offset of the dword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (RT_UNLIKELY(offInstr + 4 > DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
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 * Read a dword (32-bit) instruction.
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns The requested dword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncDECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (RT_UNLIKELY(offInstr + 4 > pDis->cbCachedInstr))
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync 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]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Function for handling a 64-bit cache miss.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @returns The requested qword.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pDis The disassembler state.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param offInstr The offset of the qword relative to the
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * instruction.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncDECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (RT_UNLIKELY(offInstr + 8 > DIS_MAX_INSTR_LENGTH))
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync 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],
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
9496f2d398b49813176939d7a339ae513d5175efvboxsync 0, 0, 0, 0);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
16a9adc14900ca18e6909679a579f6833425e030vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
9496f2d398b49813176939d7a339ae513d5175efvboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Read a qword (64-bit) instruction.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @returns The requested qword.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param pDis The disassembler state.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param uAddress The address.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncDECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_UNLIKELY(offInstr + 8 > pDis->cbCachedInstr))
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return *(uint64_t const *)&pDis->abInstr[offInstr];
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync//*****************************************************************************
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync//*****************************************************************************
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncstatic size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync // Store the opcode format string for disasmPrintf
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Note! Multibyte opcodes are always marked harmless until the final byte.
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Not filtered out -> full disassembly */
16a9adc14900ca18e6909679a579f6833425e030vboxsync // Should contain the parameter type on input
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync offInstr = pDis->pfnDisasmFnTable[pOp->idxParse4](offInstr, pOp, pDis, &pDis->Param4);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (fFiltered == false) pDis->Param4.cb = DISGetParamSize(pDis, &pDis->Param4);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync // else simple one byte instruction
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/* Floating point opcode parsing */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // Should contain the parameter type on input
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Not filtered out -> full disassembly */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Note: redundant, but just in case this ever changes */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // Little hack to make sure the ModRM byte is included in the returned size
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/********************************************************************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * SIB byte: (not 16-bit mode)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * 7 - 6 5 - 3 2-0
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Scale Index Base
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ********************************************************************************************************************************/
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // [scaled index] + disp32
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync { /* sign-extend to 64 bits */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return; /* Already fetched everything in ParseSIB; no size returned */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.B extends the Base field if not scaled index + disp32 */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Additional 32 bits displacement. No change in long mode. */
59a2c1c0a4a0762b46bc5ff056f5705ec9c0a660vboxsyncstatic size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.B extends the Base field. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Base |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* REX.X extends the Index field. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDis->SIB.Bits.Index |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Additional 32 bits displacement. No change in long mode. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/********************************************************************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * 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);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (subtype == OP_PARM_v || subtype == OP_PARM_NONE || subtype == OP_PARM_y)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* make gcc happy */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync 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. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Intel� 64 and IA-32 Architectures Software Developer�s Manual: 3.4.1.1 */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic void disasmModRMReg16(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX };
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync static const uint8_t s_auIndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI };
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParam->Index.idxGenReg = s_auIndexModRMReg16[idx];
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic void disasmModRMSReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncstatic size_t UseModRM(size_t const 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 break; /* memory operand */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync reg = rm; /* the RM field specifies the xmm register */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else no break */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // Use YMM register if VEX.L is set.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /** @todo bound */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* 32 bits displacement */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync { //register address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {//16 bits addressing mode
b0b15690f00527424b2d5fb88456d747252322f7vboxsync 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);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * 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 */
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);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 2: /* Effective address + 32 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* 16 bits mode */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 0: /* Effective address */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* else register address */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync 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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync { /* SIB byte follows ModRM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync offInstr = ParseSIB_SizeOnly(offInstr, pOp, pDis, pParam);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
217fa436516d137a409bb493cb7d350898f64666vboxsync case 1: /* Effective address + 8 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 2: /* Effective address + 32 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* 16 bits mode */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case 0: //effective address
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* else register address */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 1: /* Effective address + 8 bits displacement */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case 2: /* Effective address + 32 bits displacement */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncstatic size_t ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseModRM(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
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * encoding of the MOD field in the MODR/M byte.
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* REX.R extends the Reg field. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* 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(offInstr, pOp, pDis, pParam);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* Disregard the mod bits for certain instructions (mov crx, mov drx).
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * From the AMD manual:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * encoding of the MOD field in the MODR/M byte.
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* REX.R extends the Reg field. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* 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)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseImmUlong(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseImmUlong_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmQword(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseImmQword_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmV(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic 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);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmZ_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmBRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmBRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseImmVRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* 32 bits relative immediate sign extended to 64 bits. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync// Relative displacement for branches (rel. to next instruction)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmVRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Both 32 & 64 bits mode use 32 bits relative immediates. */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseImmAddr(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* far 16:32 pointer */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * near 32 bits pointer
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so we treat it like displacement.
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * near 64 bits pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so we treat it like displacement.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* far 16:16 pointer */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * 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.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
9496f2d398b49813176939d7a339ae513d5175efvboxsync // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync // far 16:32 pointer
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync // far 16:16 pointer
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync // immediate far pointers - only 16:16 or 16:32
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsyncstatic size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync * Sets up flags for stored in OPC fixed registers.
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* No parameter at all. */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 32-bit EAX..EDI registers. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Use 32-bit registers. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* Use 64-bit registers. */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Use 16-bit registers. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Segment ES..GS registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 16-bit AX..DI registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN16_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* 8-bit AL..DL, AH..DH registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxGenReg += DISGREG_SPL - DISGREG_AH;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* FPU registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* else - not supported for now registers. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
c7ff622115966b69b482bd2896662e40d823b22fvboxsync//*****************************************************************************
c7ff622115966b69b482bd2896662e40d823b22fvboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
76364cddabfeb143dad91862d41a5638d8860b25vboxsync//*****************************************************************************
76364cddabfeb143dad91862d41a5638d8860b25vboxsync//*****************************************************************************
76364cddabfeb143dad91862d41a5638d8860b25vboxsyncstatic size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* This is used to avoid a bunch of special hacks to get the ModRM byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync included when encountering invalid opcodes in groups. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
cba6719bd64ec749967bbe931230452664109857vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseVexDest(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxYmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->Base.idxXmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync case OP_PARM_B: // Always OP_PARM_By. Change if it is not so.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if ((pDis->fPrefix & DISPREFIX_REX) && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W))
16a9adc14900ca18e6909679a579f6833425e030vboxsync // TODO: Check if the register number is correct
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->Base.idxGenReg = (pDis->bVexDestReg >> 1) ^ 0xf;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /* 2nd byte */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* default to the non-prefixed table. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Table entry is valid, so use the extension table. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Cancel prefix changes. */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Table entry is valid, so use the extension table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Cancel prefix changes. */
090d729e786b999dc285f8ea267f9effd1319544vboxsync if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Table entry is valid, so use the extension table. */
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync /* Cancel prefix changes. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* 3rd byte */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* default to the non-prefixed table. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync /* Handle opcode table extensions that rely on the address, repne prefix byte. */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Table entry is valid, so use the extension table. */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Cancel prefix changes. */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync if ((pDis->fPrefix & DISPREFIX_OPSIZE) && g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4])
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* 0x66F2 */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pOpcode = g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4];
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* Table entry is valid, so use the extension table. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Cancel prefix changes. */
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync else if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
44fc72ff17b23a9b970505fcf8d6da1019ddcec5vboxsync pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync /* Table entry is valid, so use the extension table. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Cancel prefix changes. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4])
16a9adc14900ca18e6909679a579f6833425e030vboxsync pOpcode = g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4];
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Table entry is valid, so use the extension table. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Cancel prefix changes. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* 3rd byte */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* default to the non-prefixed table. */
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Table entry is valid, so use the extension table. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Cancel prefix changes. */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return disParseInstruction(offInstr, pOpcode, pDis);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsync//*****************************************************************************
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncstatic size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//*****************************************************************************
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncstatic size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncstatic size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
16a9adc14900ca18e6909679a579f6833425e030vboxsync// It would appear the ModRM byte must always be present. How else can you
16a9adc14900ca18e6909679a579f6833425e030vboxsync// determine the offset of the imm8_opcode byte otherwise?
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync//*****************************************************************************
a3369a746b56a8966dd78619f4d191c9662f400dvboxsyncstatic size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /** @todo This code needs testing! Esp. wrt invalid opcodes. */
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsyncstatic size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync//*****************************************************************************
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync//*****************************************************************************
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncstatic size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Cannot easily skip this hack because of monitor and vmcall! */
16a9adc14900ca18e6909679a579f6833425e030vboxsync //little hack to make sure the ModRM byte is included in the returned size
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync//*****************************************************************************
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsyncstatic size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncstatic size_t ParseVex2b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync // VEX.R (equivalent to REX.R)
4a23807f02e9920d92c8449bd93d84501add460avboxsync if (!(byte & 0x80) && pDis->uCpuMode == DISCPUMODE_64BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* REX prefix byte */
5b465a7c1237993faf8bb50120d247f3f0319adavboxsync // OPSIZE 0x66 prefix
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync /* TODO: Check if we need to set this prefix */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // REPE 0xF3 prefix
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // REPNE 0xF2 prefix
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return disParseInstruction(offInstr, pOpCode, pDis);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic size_t ParseVex3b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
case OP_BTC:
case OP_BTR:
case OP_BTS:
case OP_CMPXCHG:
case OP_XADD:
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:
switch (opcode)
case OP_INVALID:
if (pcbInstr)
case OP_SEG:
case OP_LOCK:
case OP_ADDRSIZE:
case OP_OPSIZE:
pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
case OP_REPE:
case OP_REPNE:
case OP_REX:
&& (opcode != OP_LES || pDis->uCpuMode == DISCPUMODE_64BIT || !(disReadByte(pDis, offInstr + 1) & 0x80)))
if (pcbInstr)
return paOneByteMap;
PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
if (!cbPretched)
DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
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);