DisasmCore.cpp revision 643ac6d84030a2ec7e6d6f536f2b547a8a196858
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * VBox Disassembler - Core Components.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2012 Oracle Corporation
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * available from http://www.virtualbox.org. This file is free software;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * General Public License (GPL) as published by the Free Software
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Header Files *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Internal Functions *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic int disInstrWorker(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic unsigned disParseInstruction(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISCPUSTATE pCpu);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic unsigned QueryModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic unsigned QueryModRM_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic void UseSIB(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncstatic unsigned ParseSIB_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsyncstatic void disasmModRMReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam, int fRegAddr);
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsyncstatic void disasmModRMReg16(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic void disasmModRMSReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic void disValidateLockSequence(PDISCPUSTATE pCpu);
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync/* Read functions */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic uint8_t disReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic uint16_t disReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic uint32_t disReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic uint64_t disReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** @name Parsers
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** Floating point parsing */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/*******************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync* Global Variables *
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync*******************************************************************************/
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync/** Parser opcode table for full disassembly. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync/** Parser opcode table for only calculating instruction size. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Parses one guest instruction.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * The result is found in pCpu and pcbInstr.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pvInstr Address of the instruction to decode. This is a
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * real address in the current context that can be
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * accessed without faulting. (Consider
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * DISInstrWithReader if this isn't the case.)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pCpu Pointer to cpu structure. Will be initialized.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pcbInstr Where to store the size of the instruction.
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * NULL is allowed. This is also stored in
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * PDISCPUSTATE::opsize.
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsyncDISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbInstr)
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync return DISInstEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pCpu, pcbInstr);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Parses one guest instruction.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * The result is found in pCpu and pcbInstr.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @returns VBox status code.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param uInstrAddr Address of the instruction to decode. What this means
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * is left to the pfnReadBytes function.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pfnReadBytes Callback for reading instruction bytes.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pCpu Pointer to cpu structure. Will be initialized.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pcbInstr Where to store the size of the instruction.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * NULL is allowed. This is also stored in
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * PDISCPUSTATE::opsize.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsyncDISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync return DISInstEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pCpu, pcbInstr);
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * Disassembles on instruction, details in @a pCpu and length in @a pcbInstr.
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * @returns VBox status code.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param uInstrAddr Address of the instruction to decode. What this means
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * is left to the pfnReadBytes function.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pfnReadBytes Callback for reading instruction bytes.
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param fFilter Instruction type filter.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * @param pCpu Pointer to CPU structure. With the exception of
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * DISCPUSTATE::pvUser2, the structure will be
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * completely initialized by this API, i.e. no input is
4fcfe0bd966753617b7ab5fb81fb24709914fc1cvboxsync * taken from it.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pcbInstr Where to store the size of the instruction. (This
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * is also stored in PDISCPUSTATE::opsize.) Optional.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncDISDECL(int) DISInstEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Initialize the CPU state.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Note! The RT_BZERO make ASSUMPTIONS about the placement of pvUser2.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pCpu->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync return disInstrWorker(pCpu, uInstrAddr, paOneByteMap, pcbInstr);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Internal worker for DISInstEx.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @returns VBox status code.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pCpu Initialized cpu state.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param paOneByteMap The one byte opcode map to use.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param uInstrAddr Instruction address.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @param pcbInstr Where to store the instruction size. Can be NULL.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic int disInstrWorker(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Parse byte by byte.
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync unsigned iByte = 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync uint8_t codebyte = disReadByte(pCpu, uInstrAddr+iByte);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Hardcoded assumption about OP_* values!! */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync // segment override prefix byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pCpu->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync continue; //fetch the next byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync // lock prefix byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync continue; //fetch the next byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync // address size override prefix byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync continue; //fetch the next byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync // operand size override prefix byte
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync pCpu->opmode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
a7d402dcc23137e7b9527be6de80400043a5fbf4vboxsync continue; //fetch the next byte
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync // rep and repne are not really prefixes, but we'll treat them as such
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync continue; //fetch the next byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync continue; //fetch the next byte
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* REX prefix byte */
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync pCpu->prefix_rex = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync pCpu->opmode = DISCPUMODE_64BIT; /* overrides size prefix byte */
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync continue; //fetch the next byte
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync cbInc = disParseInstruction(uInstrAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu);
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync AssertMsg(pCpu->opsize == iByte || RT_FAILURE_NP(pCpu->rc), ("%u %u\n", pCpu->opsize, iByte));
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync//*****************************************************************************
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync//*****************************************************************************
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsyncstatic unsigned disParseInstruction(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISCPUSTATE pCpu)
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync bool fFiltered = false;
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync // Store the opcode format string for disasmPrintf
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync * Note! Multibyte opcodes are always marked harmless until the final byte.
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync /* Not filtered out -> full disassembly */
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync // Should contain the parameter type on input
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync size += pCpu->pfnDisasmFnTable[pOp->idxParse1](uCodePtr, pOp, &pCpu->param1, pCpu);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (fFiltered == false) pCpu->param1.cb = DISGetParamSize(pCpu, &pCpu->param1);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync size += pCpu->pfnDisasmFnTable[pOp->idxParse2](uCodePtr+size, pOp, &pCpu->param2, pCpu);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (fFiltered == false) pCpu->param2.cb = DISGetParamSize(pCpu, &pCpu->param2);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync size += pCpu->pfnDisasmFnTable[pOp->idxParse3](uCodePtr+size, pOp, &pCpu->param3, pCpu);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (fFiltered == false) pCpu->param3.cb = DISGetParamSize(pCpu, &pCpu->param3);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync // else simple one byte instruction
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync//*****************************************************************************
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync/* Floating point opcode parsing */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync//*****************************************************************************
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncunsigned ParseEscFP(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync unsigned size = 0;
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync // Should contain the parameter type on input
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Not filtered out -> full disassembly */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Correct the operand size if the instruction is marked as forced or default 64 bits */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Note: redundant, but just in case this ever changes */
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync // Little hack to make sure the ModRM byte is included in the returned size
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
72730eaca1e865cb4503d6f8f00bc00bc5e1c038vboxsync size += pCpu->pfnDisasmFnTable[fpop->idxParse1](uCodePtr+size, (PCDISOPCODE)fpop, pParam, pCpu);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync size += pCpu->pfnDisasmFnTable[fpop->idxParse2](uCodePtr+size, (PCDISOPCODE)fpop, pParam, pCpu);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync// SIB byte: (32 bits mode only)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync// 7 - 6 5 - 3 2-0
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync// Scale Index Base
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic const char *szSIBBaseReg[8] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic const char *szSIBIndexReg[8] = {"EAX", "ECX", "EDX", "EBX", NULL, "EBP", "ESI", "EDI"};
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic const char *szSIBBaseReg64[16] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic const char *szSIBIndexReg64[16]= {"RAX", "RCX", "RDX", "RBX", NULL, "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED) || defined(_MSC_VER)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncstatic const char *szSIBScale[4] = {"", "*2", "*4", "*8"};
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncvoid UseSIB(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync // [scaled index] + disp32
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync { /* sign-extend to 64 bits */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync return; /* Already fetched everything in ParseSIB; no size returned */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncunsigned ParseSIB(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* REX.B extends the Base field if not scaled index + disp32 */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync if (!(pCpu->SIB.Bits.Base == 5 && pCpu->ModRM.Bits.Mod == 0))
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pCpu->SIB.Bits.Base |= ((!!(pCpu->prefix_rex & DISPREFIX_REX_FLAGS_B)) << 3);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pCpu->SIB.Bits.Index |= ((!!(pCpu->prefix_rex & DISPREFIX_REX_FLAGS_X)) << 3);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Additional 32 bits displacement. No change in long mode. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncunsigned ParseSIB_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* REX.B extends the Base field. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pCpu->SIB.Bits.Base |= ((!!(pCpu->prefix_rex & DISPREFIX_REX_FLAGS_B)) << 3);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* REX.X extends the Index field. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync pCpu->SIB.Bits.Index |= ((!!(pCpu->prefix_rex & DISPREFIX_REX_FLAGS_X)) << 3);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* Additional 32 bits displacement. No change in long mode. */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync// ModR/M byte:
25747178cb66800d8386c20b8ffd87f78f24f4e5vboxsync// 7 - 6 5 - 3 2-0
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync//*****************************************************************************
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsyncunsigned UseModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync break; /* memory operand */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync reg = rm; /* the RM field specifies the xmm register */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* else no break */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* @todo bound */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync Assert(pCpu->addrmode == DISCPUMODE_32BIT || pCpu->addrmode == DISCPUMODE_64BIT);
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync case 0: //effective address
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync { /* SIB byte follows ModRM */
24ab761b2beb5af0393c6f2585b6351d8b3085f0vboxsync /* 32 bits displacement */
switch (mod)
unsigned QueryModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
unsigned sibinc;
unsigned size = 0;
if (!pSibInc)
*pSibInc = 0;
switch (mod)
size += sizeof(char);
switch (mod)
size += sizeof(char);
return size;
unsigned QueryModRM_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
unsigned sibinc;
unsigned size = 0;
if (!pSibInc)
*pSibInc = 0;
switch (mod)
size += sizeof(char);
switch (mod)
size += sizeof(char);
return size;
AssertFailed();
* This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
return size;
unsigned ParseModRM_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
* This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
return size;
return sizeof(uint8_t);
unsigned ParseImmByte_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint8_t);
return sizeof(uint8_t);
unsigned ParseImmByteSX_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint8_t);
return sizeof(uint16_t);
unsigned ParseImmUshort_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint16_t);
return sizeof(uint32_t);
unsigned ParseImmUlong_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
return sizeof(uint64_t);
unsigned ParseImmQword_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint64_t);
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint16_t);
unsigned ParseImmV_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint16_t);
return sizeof(uint16_t);
return sizeof(uint32_t);
unsigned ParseImmZ_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint16_t);
return sizeof(uint32_t);
unsigned ParseImmBRel_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(int32_t);
return sizeof(int32_t);
return sizeof(int16_t);
unsigned ParseImmVRel_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(int16_t);
return sizeof(int32_t);
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint32_t);
return sizeof(uint16_t);
unsigned ParseImmAddr_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
return sizeof(uint64_t);
return sizeof(uint32_t);
return sizeof(uint16_t);
return sizeof(uint32_t);
unsigned ParseImmAddrF_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return sizeof(uint32_t);
unsigned ParseTwoByteEsc(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseThreeByteEsc4(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return size;
unsigned ParseThreeByteEsc5(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
return size;
unsigned size = 0;
return size;
return size;
int idx;
return sizeof(uint8_t);
return size;
return size;
return size;
return size;
#ifdef DEBUG_Sander
#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
return size;
static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"};
static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"};
static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"};
static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
static const int BaseModRMReg16[8] = { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX};
static void disasmModRMReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam, int fRegAddr)
if (fRegAddr)
case DISCPUMODE_32BIT:
case DISCPUMODE_64BIT:
case DISCPUMODE_16BIT:
switch (subtype)
case OP_PARM_b:
case OP_PARM_w:
case OP_PARM_d:
case OP_PARM_q:
DECL_NO_INLINE(static, void)
AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.16Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, sizeof(pCpu->abInstr), pCpu->abInstr));
DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
#ifdef IN_RING0
return VERR_DIS_NO_READ_CALLBACK;
return VINF_SUCCESS;
return bTemp;
uTemp.u = 0;
return uTemp.u;
uTemp.u = 0;
return uTemp.u;
uTemp.u = 0;
return uTemp.u;
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: