DisasmCore.cpp revision 389b9f89a42b9efcb0d843a6a45c54418dd02e11
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync/** @file
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * VBox disassembler:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Core components
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync/*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Copyright (C) 2006-2007 innotek GmbH
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License as published by the Free Software Foundation,
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header Files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#ifdef USING_VISUAL_STUDIO
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync# include <stdafx.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#endif
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
662d52947eeb3fc8fca3b23991a5eee47077f896vboxsync#include <VBox/dis.h>
da957c069c2a3c582fe265ff88170ce4c42b499dvboxsync#include <VBox/disopcode.h>
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#include <VBox/err.h>
16a9adc14900ca18e6909679a579f6833425e030vboxsync#define LOG_GROUP LOG_GROUP_DIS
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/log.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/assert.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/string.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/stdarg.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "DisasmInternal.h"
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include "DisasmTables.h"
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync# include <stdlib.h>
efff36b306e370346025647a158689021df2e1d1vboxsync# include <stdio.h>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#endif
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/*******************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync* Internal Functions *
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync*******************************************************************************/
efff36b306e370346025647a158689021df2e1d1vboxsyncstatic int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic void disasmAddString(char *psz, const char *pszString);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic void disasmAddStringF(char *psz, uint32_t cbString, const char *pszFormat, ...);
efff36b306e370346025647a158689021df2e1d1vboxsyncstatic void disasmAddChar(char *psz, char ch);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync# define disasmAddString(psz, pszString) do {} while (0)
efff36b306e370346025647a158689021df2e1d1vboxsync# ifdef _MSC_VER
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync# define disasmAddStringF __noop
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync# else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync# define disasmAddStringF(psz, cbString, pszFormat...) do {} while (0) /* Arg wanna get rid of that warning */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync# endif
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync# define disasmAddChar(psz, ch) do {} while (0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#endif
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic unsigned QueryModRM(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, int *pSibInc = NULL);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic unsigned QueryModRM_SizeOnly(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, int *pSibInc = NULL);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic void UseSIB(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic unsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Global Variables *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
0abd77741a608f6c41c8dfcd4781b8b84adf1044vboxsyncPFNDISPARSE pfnFullDisasm[IDX_ParseMax] =
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseIllegal,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseModRM,
9496f2d398b49813176939d7a339ae513d5175efvboxsync UseModRM,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmByte,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmBRel,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmUshort,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmV,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmVRel,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmAddr,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseFixedReg,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmUlong,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmQword,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseTwoByteEsc,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseImmGrpl,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseShiftGrp2,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp3,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp4,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp5,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Parse3DNow,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp6,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp7,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp8,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp9,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp10,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp12,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp13,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp14,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp15,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseGrp16,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseModFence,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseYv,
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync ParseYb,
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync ParseXv,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseXb,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseEscFP,
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync ParseNopPause,
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync ParseImmByteSX
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync};
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsyncPFNDISPARSE pfnCalcSize[IDX_ParseMax] =
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ParseIllegal,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseModRM_SizeOnly,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync UseModRM,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseImmByte_SizeOnly,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseImmBRel_SizeOnly,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseImmUshort_SizeOnly,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseImmV_SizeOnly,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseImmVRel_SizeOnly,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseImmAddr_SizeOnly,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ParseFixedReg,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmUlong_SizeOnly,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmQword_SizeOnly,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseTwoByteEsc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseImmGrpl,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseShiftGrp2,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp3,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp4,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp5,
9496f2d398b49813176939d7a339ae513d5175efvboxsync Parse3DNow,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ParseGrp6,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp7,
21029597fc4b76d0db0c9542daee201447281781vboxsync ParseGrp8,
21029597fc4b76d0db0c9542daee201447281781vboxsync ParseGrp9,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp10,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ParseGrp12,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp13,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp14,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp15,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseGrp16,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseModFence,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseYv,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseYb,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ParseXv,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseXb,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseEscFP,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseNopPause,
9496f2d398b49813176939d7a339ae513d5175efvboxsync ParseImmByteSX_SizeOnly
16a9adc14900ca18e6909679a579f6833425e030vboxsync};
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Array for accessing 32-bit general registers in VMMREGFRAME structure
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * by register's index from disasm.
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic const unsigned g_aReg32Index[] =
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_EAX */
9496f2d398b49813176939d7a339ae513d5175efvboxsync RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_ECX */
9496f2d398b49813176939d7a339ae513d5175efvboxsync RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_EDX */
9496f2d398b49813176939d7a339ae513d5175efvboxsync RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_EBX */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, esp), /* USE_REG_ESP */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ebp), /* USE_REG_EBP */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, esi), /* USE_REG_ESI */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, edi) /* USE_REG_EDI */
16a9adc14900ca18e6909679a579f6833425e030vboxsync};
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Macro for accessing 32-bit general purpose registers in CPUMCTXCORE structure.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsync#define DIS_READ_REG32(p, idx) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]))
16a9adc14900ca18e6909679a579f6833425e030vboxsync#define DIS_WRITE_REG32(p, idx, val) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]) = val)
16a9adc14900ca18e6909679a579f6833425e030vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Array for accessing 16-bit general registers in CPUMCTXCORE structure
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * by register's index from disasm.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic const unsigned g_aReg16Index[] =
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_AX */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_CX */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_DX */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_BX */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, esp), /* USE_REG_SP */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ebp), /* USE_REG_BP */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, esi), /* USE_REG_SI */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, edi) /* USE_REG_DI */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync};
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Macro for accessing 16-bit general purpose registers in CPUMCTXCORE structure.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync#define DIS_READ_REG16(p, idx) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]))
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync#define DIS_WRITE_REG16(p, idx, val) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]) = val)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Array for accessing 8-bit general registers in CPUMCTXCORE structure
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * by register's index from disasm.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstatic const unsigned g_aReg8Index[] =
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_AL */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_CL */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_DL */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_BL */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, eax) + 1, /* USE_REG_AH */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ecx) + 1, /* USE_REG_CH */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, edx) + 1, /* USE_REG_DH */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RT_OFFSETOF(CPUMCTXCORE, ebx) + 1 /* USE_REG_BH */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync};
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Macro for accessing 8-bit general purpose registers in CPUMCTXCORE structure.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsync#define DIS_READ_REG8(p, idx) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]))
16a9adc14900ca18e6909679a579f6833425e030vboxsync#define DIS_WRITE_REG8(p, idx, val) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]) = val)
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Array for accessing segment registers in CPUMCTXCORE structure
16a9adc14900ca18e6909679a579f6833425e030vboxsync * by register's index from disasm.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic const unsigned g_aRegSegIndex[] =
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, es), /* USE_REG_ES */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, cs), /* USE_REG_CS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, ss), /* USE_REG_SS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, ds), /* USE_REG_DS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, fs), /* USE_REG_FS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, gs) /* USE_REG_GS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync};
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic const unsigned g_aRegHidSegIndex[] =
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, esHid), /* USE_REG_ES */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, csHid), /* USE_REG_CS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, ssHid), /* USE_REG_SS */
16a9adc14900ca18e6909679a579f6833425e030vboxsync RT_OFFSETOF(CPUMCTXCORE, dsHid), /* USE_REG_DS */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync RT_OFFSETOF(CPUMCTXCORE, fsHid), /* USE_REG_FS */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync RT_OFFSETOF(CPUMCTXCORE, gsHid) /* USE_REG_GS */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync};
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/**
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Macro for accessing segment registers in CPUMCTXCORE structure.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync#define DIS_READ_REGSEG(p, idx) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync#define DIS_WRITE_REGSEG(p, idx, val) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])) = val)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/**
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Parses one instruction.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * The result is found in pCpu.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync *
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @returns Success indicator.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param pCpu Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param InstructionAddr Pointer to the instruction to parse.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @param pcbInstruction Where to store the size of the instruction.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * NULL is allowed.
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncDISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /*
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Reset instruction settings
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->prefix = PREFIX_NONE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->prefix_seg = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->lastprefix = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->addrmode = pCpu->mode;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->opmode = pCpu->mode;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->ModRM = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->SIB = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param1.parval = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param2.parval = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param3.parval = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param1.szParam[0] = '\0';
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param2.szParam[0] = '\0';
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param3.szParam[0] = '\0';
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param1.flags = 0;
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync pCpu->param2.flags = 0;
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync pCpu->param3.flags = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param1.size = 0;
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync pCpu->param2.size = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->param3.size = 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pCpu->pfnReadBytes = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->uFilter = OPTYPE_ALL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->pfnDisasmFnTable = pfnFullDisasm;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return VBOX_SUCCESS(disCoreOne(pCpu, InstructionAddr, pcbInstruction));
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync}
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync
22ec733a5e041fcdfe02fce2eafc9faf8b0077ddvboxsync/**
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Parses one guest instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * The result is found in pCpu and pcbInstruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns VBox status code.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param InstructionAddr Address of the instruction to decode. What this means
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * is left to the pfnReadBytes function.
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync * @param uCpuMode The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * @param pfnReadBytes Callback for reading instruction bytes.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pvUser User argument for the instruction reader. (Ends up in apvUserData[0].)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pCpu Pointer to cpu structure. Will be initialized.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pcbInstruction Where to store the size of the instruction.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * NULL is allowed.
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync */
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsyncDISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, unsigned uCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync PDISCPUSTATE pCpu, unsigned *pcbInstruction)
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync{
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync /*
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * Reset instruction settings
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync */
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->prefix = PREFIX_NONE;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->prefix_seg = 0;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->lastprefix = 0;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->mode = uCpuMode;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->addrmode = uCpuMode;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->opmode = uCpuMode;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->ModRM = 0;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->SIB = 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->param1.parval = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->param2.parval = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->param3.parval = 0;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->param1.szParam[0] = '\0';
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->param2.szParam[0] = '\0';
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync pCpu->param3.szParam[0] = '\0';
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->param1.flags = 0;
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync pCpu->param2.flags = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->param3.flags = 0;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->param1.size = 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->param2.size = 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->param3.size = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->pfnReadBytes = pfnReadBytes;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->apvUserData[0] = pvUser;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->uFilter = OPTYPE_ALL;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->pfnDisasmFnTable = pfnFullDisasm;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return disCoreOne(pCpu, InstructionAddr, pcbInstruction);
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync}
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync/**
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * Internal worker for DISCoreOne and DISCoreOneEx.
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync *
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * @returns VBox status code.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pCpu Initialized cpu state.
ffbe6daf773e38167f3cabaf1f063d84ecd063e9vboxsync * @param InstructionAddr Instruction address.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * @param pcbInstruction Where to store the instruction size. Can be NULL.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsyncstatic int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /*
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * Parse byte by byte.
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync */
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync unsigned iByte = 0;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync while(1)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync uint8_t codebyte = DISReadByte(pCpu, InstructionAddr+iByte);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync uint8_t opcode = g_aOneByteMapX86[codebyte].opcode;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* Hardcoded assumption about OP_* values!! */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (opcode <= OP_LOCK)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->lastprefix = opcode;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync switch(opcode)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_INVALID:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AssertMsgFailed(("Invalid opcode!!\n"));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return VERR_GENERAL_FAILURE; /** @todo better error code. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync // segment override prefix byte
9496f2d398b49813176939d7a339ae513d5175efvboxsync case OP_SEG:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->prefix_seg = g_aOneByteMapX86[codebyte].param1 - OP_PARM_REG_SEG_START;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->prefix |= PREFIX_SEG;
9496f2d398b49813176939d7a339ae513d5175efvboxsync iByte += sizeof(uint8_t);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync continue; //fetch the next byte
9496f2d398b49813176939d7a339ae513d5175efvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync // lock prefix byte
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_LOCK:
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->prefix |= PREFIX_LOCK;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync iByte += sizeof(uint8_t);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync continue; //fetch the next byte
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync // address size override prefix byte
9496f2d398b49813176939d7a339ae513d5175efvboxsync case OP_ADRSIZE:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->prefix |= PREFIX_ADDRSIZE;
9496f2d398b49813176939d7a339ae513d5175efvboxsync if(pCpu->mode == CPUMODE_16BIT)
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->addrmode = CPUMODE_32BIT;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync else pCpu->addrmode = CPUMODE_16BIT;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync iByte += sizeof(uint8_t);
9496f2d398b49813176939d7a339ae513d5175efvboxsync continue; //fetch the next byte
16a9adc14900ca18e6909679a579f6833425e030vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync // operand size override prefix byte
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync case OP_OPSIZE:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->prefix |= PREFIX_OPSIZE;
9496f2d398b49813176939d7a339ae513d5175efvboxsync if(pCpu->mode == CPUMODE_16BIT)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->opmode = CPUMODE_32BIT;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync else pCpu->opmode = CPUMODE_16BIT;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync iByte += sizeof(uint8_t);
9496f2d398b49813176939d7a339ae513d5175efvboxsync continue; //fetch the next byte
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync // rep and repne are not really prefixes, but we'll treat them as such
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_REPE:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pCpu->prefix |= PREFIX_REP;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync iByte += sizeof(uint8_t);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync continue; //fetch the next byte
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case OP_REPNE:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync pCpu->prefix |= PREFIX_REPNE;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync iByte += sizeof(uint8_t);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync continue; //fetch the next byte
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync unsigned uIdx = iByte;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync iByte += sizeof(uint8_t); //first opcode byte
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->opaddr = InstructionAddr + uIdx;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->opcode = codebyte;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync int cbInc = ParseInstruction(InstructionAddr + iByte, &g_aOneByteMapX86[pCpu->opcode], pCpu);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync iByte += cbInc;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync break;
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync pCpu->opsize = iByte;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (pcbInstruction)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync *pcbInstruction = iByte;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return VINF_SUCCESS;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync//*****************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync//*****************************************************************************
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncDISDECL(int) DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync int subtype = OP_PARM_VSUBTYPE(pParam->param);
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if(subtype == OP_PARM_v)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync {
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync }
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync switch(subtype)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_PARM_b:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 1;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync case OP_PARM_w:
9496f2d398b49813176939d7a339ae513d5175efvboxsync return 2;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_PARM_d:
9496f2d398b49813176939d7a339ae513d5175efvboxsync return 4;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_PARM_q:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case OP_PARM_dq:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 8;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync case OP_PARM_p:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if(pCpu->addrmode == CPUMODE_32BIT)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 8;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync else
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 4;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync default:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if(pParam->size)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return pParam->size;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync else //@todo dangerous!!!
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync return 4;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync }
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync}
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsyncDISDECL(int) DISDetectSegReg(PDISCPUSTATE pCpu, POP_PARAMETER pParam)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync if(pCpu->prefix & PREFIX_SEG)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync /* Use specified SEG: prefix. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return pCpu->prefix_seg;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* Guess segment register by parameter type. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if(pParam->flags & USE_REG_GEN32)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if(pParam->base.reg_gen32 == USE_REG_ESP || pParam->base.reg_gen32 == USE_REG_EBP)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return USE_REG_SS;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if(pParam->flags & USE_REG_GEN16)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if(pParam->base.reg_gen16 == USE_REG_SP || pParam->base.reg_gen16 == USE_REG_BP)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return USE_REG_SS;
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* Default is use DS: for data access. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return USE_REG_DS;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncDISDECL(uint8_t) DISQuerySegPrefixByte(PDISCPUSTATE pCpu)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync{
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync Assert(pCpu->prefix & PREFIX_SEG);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync switch(pCpu->prefix_seg)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync case USE_REG_ES:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0x26;
9496f2d398b49813176939d7a339ae513d5175efvboxsync case USE_REG_CS:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0x2E;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync case USE_REG_SS:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0x36;
16a9adc14900ca18e6909679a579f6833425e030vboxsync case USE_REG_DS:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return 0x3E;
9496f2d398b49813176939d7a339ae513d5175efvboxsync case USE_REG_FS:
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return 0x64;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync case USE_REG_GS:
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return 0x65;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync default:
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync AssertFailed();
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync return 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync/**
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync * Returns the value of the specified 8 bits general purpose register
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync *
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncDISDECL(int) DISFetchReg8(PCPUMCTXCORE pCtx, uint32_t reg8, uint8_t *pVal)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync{
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync *pVal = DIS_READ_REG8(pCtx, reg8);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return VINF_SUCCESS;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync}
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync/**
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync * Returns the value of the specified 16 bits general purpose register
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync *
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncDISDECL(int) DISFetchReg16(PCPUMCTXCORE pCtx, uint32_t reg16, uint16_t *pVal)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync{
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync *pVal = DIS_READ_REG16(pCtx, reg16);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VINF_SUCCESS;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Returns the value of the specified 16 bits general purpose register
16a9adc14900ca18e6909679a579f6833425e030vboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncDISDECL(int) DISFetchReg32(PCPUMCTXCORE pCtx, uint32_t reg32, uint32_t *pVal)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync *pVal = DIS_READ_REG32(pCtx, reg32);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VINF_SUCCESS;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Returns the value of the specified segment register
16a9adc14900ca18e6909679a579f6833425e030vboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncDISDECL(int) DISFetchRegSeg(PCPUMCTXCORE pCtx, uint32_t sel, RTSEL *pVal)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
16a9adc14900ca18e6909679a579f6833425e030vboxsync *pVal = DIS_READ_REGSEG(pCtx, sel);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return VINF_SUCCESS;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Returns the value of the specified segment register including a pointer to the hidden register in the supplied cpu context
16a9adc14900ca18e6909679a579f6833425e030vboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncDISDECL(int) DISFetchRegSegEx(PCPUMCTXCORE pCtx, uint32_t sel, RTSEL *pVal, CPUMSELREGHID **ppSelHidReg)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync *pVal = DIS_READ_REGSEG(pCtx, sel);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync *ppSelHidReg = (CPUMSELREGHID *)((char *)pCtx + g_aRegHidSegIndex[sel]);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync return VINF_SUCCESS;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync/**
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * Updates the value of the specified 32 bits general purpose register
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync *
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncDISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, uint32_t reg32, uint32_t val32)
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync DIS_WRITE_REG32(pRegFrame, reg32, val32);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync return VINF_SUCCESS;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
efff36b306e370346025647a158689021df2e1d1vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Updates the value of the specified 16 bits general purpose register
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncDISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, uint32_t reg16, uint16_t val16)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync DIS_WRITE_REG16(pRegFrame, reg16, val16);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Updates the specified 8 bits general purpose register
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncDISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, uint32_t reg8, uint8_t val8)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync DIS_WRITE_REG8(pRegFrame, reg8, val8);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Updates the specified segment register
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncDISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, uint32_t sel, RTSEL val)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync DIS_WRITE_REGSEG(pCtx, sel, val);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Returns the value of the parameter in pParam
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @returns VBox error code
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pCtx CPU context structure pointer
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * set correctly.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pParam Pointer to the parameter to parse
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pParamVal Pointer to parameter value (OUT)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param parmtype Parameter type
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
7b067f3f07310bff46d1d6a4ac94d8b9bb7ccccdvboxsyncDISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync memset(pParamVal, 0, sizeof(*pParamVal));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & (USE_BASE|USE_INDEX|USE_DISPLACEMENT32|USE_DISPLACEMENT16|USE_DISPLACEMENT8))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // Effective address
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->type = PARMTYPE_ADDRESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->size = pParam->size;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_BASE)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_REG_GEN8)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->flags |= PARAM_VAL8;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(VBOX_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen8, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_REG_GEN16)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->flags |= PARAM_VAL16;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(VBOX_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen16, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_REG_GEN32)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->flags |= PARAM_VAL32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(VBOX_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen32, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertFailed();
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VERR_INVALID_PARAMETER;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // Note that scale implies index (SIB byte)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_INDEX)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync uint32_t val32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->flags |= PARAM_VAL32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(VBOX_FAILURE(DISFetchReg32(pCtx, pParam->index.reg_gen, &val32))) return VERR_INVALID_PARAMETER;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_SCALE)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync val32 *= pParam->scale;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val32 += val32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_DISPLACEMENT8)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pCpu->mode & CPUMODE_32BIT)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val32 += (int32_t)pParam->disp8;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val16 += (int16_t)pParam->disp8;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_DISPLACEMENT16)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pCpu->mode & CPUMODE_32BIT)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val32 += (int32_t)pParam->disp16;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val16 += pParam->disp16;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_DISPLACEMENT32)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pCpu->mode & CPUMODE_32BIT)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val32 += pParam->disp32;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Assert(0);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & (USE_REG_GEN8|USE_REG_GEN16|USE_REG_GEN32|USE_REG_FP|USE_REG_MMX|USE_REG_XMM|USE_REG_CR|USE_REG_DBG|USE_REG_SEG|USE_REG_TEST))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(parmtype == PARAM_DEST)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // Caller needs to interpret the register according to the instruction (source/target, special value etc)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->type = PARMTYPE_REGISTER;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->size = pParam->size;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync //else PARAM_SOURCE
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->type = PARMTYPE_IMMEDIATE;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(pParam->flags & USE_REG_GEN8)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->flags |= PARAM_VAL8;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint8_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(VBOX_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen8, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & USE_REG_GEN16)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->flags |= PARAM_VAL16;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint16_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(VBOX_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen16, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & USE_REG_GEN32)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->flags |= PARAM_VAL32;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint32_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(VBOX_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen32, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync // Caller needs to interpret the register according to the instruction (source/target, special value etc)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->type = PARMTYPE_REGISTER;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & USE_IMMEDIATE)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->type = PARMTYPE_IMMEDIATE;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & (USE_IMMEDIATE8|USE_IMMEDIATE8_REL))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->flags |= PARAM_VAL8;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->size == 2)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint16_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->val.val16 = (uint8_t)pParam->parval;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint8_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->val.val8 = (uint8_t)pParam->parval;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & (USE_IMMEDIATE16|USE_IMMEDIATE16_REL|USE_IMMEDIATE_ADDR_0_16|USE_IMMEDIATE16_SX8))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->flags |= PARAM_VAL16;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint16_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->val.val16 = (uint16_t)pParam->parval;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync Assert(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE16_SX8)) );
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & (USE_IMMEDIATE32|USE_IMMEDIATE32_REL|USE_IMMEDIATE_ADDR_0_32|USE_IMMEDIATE32_SX8))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->flags |= PARAM_VAL32;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->size = sizeof(uint32_t);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync pParamVal->val.val32 = (uint32_t)pParam->parval;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync Assert(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE32_SX8)) );
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync else
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if(pParam->flags & (USE_IMMEDIATE64))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
efff36b306e370346025647a158689021df2e1d1vboxsync pParamVal->flags |= PARAM_VAL64;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->size = sizeof(uint64_t);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParamVal->val.val64 = pParam->parval;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(pParamVal->size == pParam->size);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(pParam->flags & (USE_IMMEDIATE_ADDR_16_16))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParamVal->flags |= PARAM_VALFARPTR16;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pParamVal->size = sizeof(uint16_t)*2;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->parval >> 16);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->parval);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(pParamVal->size == pParam->size);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync else
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if(pParam->flags & (USE_IMMEDIATE_ADDR_16_32))
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParamVal->flags |= PARAM_VALFARPTR32;
fe813b3594039ba864493438e78ee0e7132bc445vboxsync pParamVal->size = sizeof(uint16_t) + sizeof(uint32_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->parval >> 32);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParamVal->val.farptr.offset = (uint32_t)(pParam->parval & 0xFFFFFFFF);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(pParam->size == 8);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return VINF_SUCCESS;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncunsigned ParseInstruction(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, PDISCPUSTATE pCpu)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync{
ff88d4153cd65650577e8c2d1a5a3fdfa0404a80vboxsync int size = 0;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fFiltered = false;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
fe813b3594039ba864493438e78ee0e7132bc445vboxsync // Store the opcode format string for disasmPrintf
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#ifndef DIS_CORE_ONLY
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->pszOpcode = pOp->pszOpcode;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#endif
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->pCurInstr = pOp;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync if ((pOp->optype & pCpu->uFilter) == 0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fFiltered = true;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->pfnDisasmFnTable = pfnCalcSize;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* Not filtered out -> full disassembly */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->pfnDisasmFnTable = pfnFullDisasm;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync // Should contain the parameter type on input
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->param1.param = pOp->param1;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->param2.param = pOp->param2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->param3.param = pOp->param3;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pOp->idxParse1 != IDX_ParseNop) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync size += pCpu->pfnDisasmFnTable[pOp->idxParse1](lpszCodeBlock, pOp, &pCpu->param1, pCpu);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pCpu->param1.size = DISGetParamSize(pCpu, &pCpu->param1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pOp->idxParse2 != IDX_ParseNop) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync size += pCpu->pfnDisasmFnTable[pOp->idxParse2](lpszCodeBlock+size, pOp, &pCpu->param2, pCpu);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pCpu->param2.size = DISGetParamSize(pCpu, &pCpu->param2);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pOp->idxParse3 != IDX_ParseNop) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync size += pCpu->pfnDisasmFnTable[pOp->idxParse3](lpszCodeBlock+size, pOp, &pCpu->param3, pCpu);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (fFiltered == false) pCpu->param3.size = DISGetParamSize(pCpu, &pCpu->param3);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync // else simple one byte instruction
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return size;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync/* Floating point opcode parsing */
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseEscFP(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync int index;
16a9adc14900ca18e6909679a579f6833425e030vboxsync const OPCODE *fpop;
16a9adc14900ca18e6909679a579f6833425e030vboxsync unsigned size = 0;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync index = pCpu->opcode - 0xD8;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(pCpu->ModRM <= 0xBF)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync fpop = &(g_paMapX86_FP_Low[index])[MODRM_REG(pCpu->ModRM)];
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pCpu->pCurInstr = (PCOPCODE)fpop;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync // Should contain the parameter type on input
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->param1.parval = fpop->param1;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->param2.parval = fpop->param2;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if ((fpop->optype & pCpu->uFilter) == 0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->pfnDisasmFnTable = pfnCalcSize;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* Not filtered out -> full disassembly */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pCpu->pfnDisasmFnTable = pfnFullDisasm;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync // Little hack to make sure the ModRM byte is included in the returned size
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if(fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size = sizeof(uint8_t); //ModRM byte
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(fpop->idxParse1 != IDX_ParseNop) {
fe813b3594039ba864493438e78ee0e7132bc445vboxsync size += pCpu->pfnDisasmFnTable[fpop->idxParse1](lpszCodeBlock+size, (PCOPCODE)fpop, pParam, pCpu);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(fpop->idxParse2 != IDX_ParseNop) {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size += pCpu->pfnDisasmFnTable[fpop->idxParse2](lpszCodeBlock+size, (PCOPCODE)fpop, pParam, pCpu);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync else
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size = sizeof(uint8_t); //ModRM byte only
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fpop = &(g_paMapX86_FP_High[index])[pCpu->ModRM - 0xC0];
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pCpu->pCurInstr = (PCOPCODE)fpop;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync /*
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync * Apply filter to instruction type to determine if a full disassembly is required.
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync * @note Multibyte opcodes are always marked harmless until the final byte.
fe813b3594039ba864493438e78ee0e7132bc445vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if ((fpop->optype & pCpu->uFilter) == 0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->pfnDisasmFnTable = pfnCalcSize;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync else
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Not filtered out -> full disassembly */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCpu->pfnDisasmFnTable = pfnFullDisasm;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync // Store the opcode format string for disasmPrintf
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync#ifndef DIS_CORE_ONLY
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pCpu->pszOpcode = fpop->pszOpcode;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync#endif
fe813b3594039ba864493438e78ee0e7132bc445vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return size;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// SIB byte: (32 bits mode only)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync// 7 - 6 5 - 3 2-0
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync// Scale Index Base
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncconst char *szSIBBaseReg[8] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncconst char *szSIBIndexReg[8] = {"EAX", "ECX", "EDX", "EBX", NULL, "EBP", "ESI", "EDI"};
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncconst char *szSIBScale[4] = {"", "*2", "*4", "*8"};
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync//*****************************************************************************
594521f7faf13f7a88f31e6cd76629bd67340229vboxsyncvoid UseSIB(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync{
fe813b3594039ba864493438e78ee0e7132bc445vboxsync int scale, base, index;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync char szTemp[32];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync szTemp[0] = '\0';
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync scale = SIB_SCALE(pCpu->SIB);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync base = SIB_BASE(pCpu->SIB);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync index = SIB_INDEX(pCpu->SIB);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if(szSIBIndexReg[index])
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
af90f37ee9175da3aed36bda13519a917cc4effbvboxsync pParam->flags |= USE_INDEX;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->index.reg_gen = index;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(scale != 0)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->flags |= USE_SCALE;
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->scale = (1<<scale);
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if(base == 5 && MODRM_MOD(pCpu->ModRM) == 0)
7a3f491705173bc08122f2c7d26d48a8b4c5ceecvboxsync disasmAddStringF(szTemp, sizeof(szTemp), "%s%s", szSIBIndexReg[index], szSIBScale[scale]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync disasmAddStringF(szTemp, sizeof(szTemp), "%s+%s%s", szSIBBaseReg[base], szSIBIndexReg[index], szSIBScale[scale]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync else
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if(base != 5 || MODRM_MOD(pCpu->ModRM) != 0)
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync disasmAddStringF(szTemp, sizeof(szTemp), "%s", szSIBBaseReg[base]);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if(base == 5 && MODRM_MOD(pCpu->ModRM) == 0)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync // [scaled index] + disp32
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmAddString(pParam->szParam, &szTemp[0]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pParam->flags |= USE_DISPLACEMENT32;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pParam->disp32 = pCpu->disp;
fe813b3594039ba864493438e78ee0e7132bc445vboxsync disasmAddChar(pParam->szParam, '+');
9496f2d398b49813176939d7a339ae513d5175efvboxsync disasmPrintDisp32(pParam);
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync disasmAddString(pParam->szParam, szTemp);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->flags |= USE_BASE | USE_REG_GEN32;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync pParam->base.reg_gen32 = base;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return; /* Already fetched everything in ParseSIB; no size returned */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync}
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync//*****************************************************************************
fe813b3594039ba864493438e78ee0e7132bc445vboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncunsigned ParseSIB(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync unsigned size = sizeof(uint8_t), base;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync pCpu->SIB = DISReadByte(pCpu, lpszCodeBlock);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync lpszCodeBlock += size;
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync base = SIB_BASE(pCpu->SIB);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync if(base == 5 && MODRM_MOD(pCpu->ModRM) == 0)
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync {//additional 32 bits displacement
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync size += sizeof(int32_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return size;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncunsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync{
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync unsigned size = sizeof(uint8_t), base;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync pCpu->SIB = DISReadByte(pCpu, lpszCodeBlock);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync lpszCodeBlock += size;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync base = SIB_BASE(pCpu->SIB);
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync if(base == 5 && MODRM_MOD(pCpu->ModRM) == 0)
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync {//additional 32 bits displacement
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync size += sizeof(int32_t);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return size;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync// ModR/M byte:
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync// 7 - 6 5 - 3 2-0
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync// Mod Reg/Opcode R/M
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncunsigned UseModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int reg = MODRM_REG(pCpu->ModRM);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int rm = MODRM_RM(pCpu->ModRM);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int mod = MODRM_MOD(pCpu->ModRM);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync int vtype = OP_PARM_VTYPE(pParam->param);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync switch(vtype)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_G: //general purpose register
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmModRMReg(pCpu, pOp, reg, pParam, 0);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync default:
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (IS_OP_PARM_RARE(vtype))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync switch(vtype)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_C: //control register
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "CR%d", reg);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_CR;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->base.reg_ctrl = reg;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_D: //debug register
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "DR%d", reg);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_DBG;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->base.reg_dbg = reg;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return 0;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case OP_PARM_P: //MMX register
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "MM%d", reg);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_MMX;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->base.reg_mmx = reg;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_S: //segment register
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmModRMSReg(pCpu, pOp, reg, pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_SEG;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_T: //test register
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "TR%d", reg);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_TEST;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->base.reg_test = reg;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_V: //XMM register
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "XMM%d", reg);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_XMM;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->base.reg_xmm = reg;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case OP_PARM_W: //XMM register or memory operand
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (mod == 3)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "XMM%d", rm);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_REG_XMM;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->base.reg_xmm = rm;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return 0;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* else memory operand */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync //TODO: bound
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(pCpu->addrmode == CPUMODE_32BIT)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {//32 bits addressing mode
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync switch(mod)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case 0: //effective address
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmGetPtrString(pCpu, pOp, pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddChar(pParam->szParam, '[');
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(rm == 4) {//SIB byte follows ModRM
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(rm == 5) {//32 bits displacement
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_DISPLACEMENT32;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->disp32 = pCpu->disp;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmPrintDisp32(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else {//register address
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_BASE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmModRMReg(pCpu, pOp, rm, pParam, 1);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddChar(pParam->szParam, ']');
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case 1: //effective address + 8 bits displacement
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmGetPtrString(pCpu, pOp, pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddChar(pParam->szParam, '[');
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(rm == 4) {//SIB byte follows ModRM
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_BASE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmModRMReg(pCpu, pOp, rm, pParam, 1);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->disp8 = pCpu->disp;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParam->flags |= USE_DISPLACEMENT8;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(pParam->disp8 != 0)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(pParam->disp8 > 0)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddChar(pParam->szParam, '+');
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmPrintDisp8(pParam);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmAddChar(pParam->szParam, ']');
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync case 2: //effective address + 32 bits displacement
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmGetPtrString(pCpu, pOp, pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddChar(pParam->szParam, '[');
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(rm == 4) {//SIB byte follows ModRM
16a9adc14900ca18e6909679a579f6833425e030vboxsync UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync else
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_BASE;
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmModRMReg(pCpu, pOp, rm, pParam, 1);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->disp32 = pCpu->disp;
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_DISPLACEMENT32;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pParam->disp32 != 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddChar(pParam->szParam, '+');
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmPrintDisp32(pParam);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddChar(pParam->szParam, ']');
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync case 3: //registers
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmModRMReg(pCpu, pOp, rm, pParam, 0);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync break;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {//16 bits addressing mode
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch(mod)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 0: //effective address
cba6719bd64ec749967bbe931230452664109857vboxsync disasmGetPtrString(pCpu, pOp, pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddChar(pParam->szParam, '[');
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if(rm == 6)
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync {//16 bits displacement
cba6719bd64ec749967bbe931230452664109857vboxsync pParam->disp16 = pCpu->disp;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_DISPLACEMENT16;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmPrintDisp16(pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync {
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pParam->flags |= USE_BASE;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmModRMReg16(pCpu, pOp, rm, pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync disasmAddChar(pParam->szParam, ']');
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 1: //effective address + 8 bits displacement
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmGetPtrString(pCpu, pOp, pParam);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync disasmAddChar(pParam->szParam, '[');
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmModRMReg16(pCpu, pOp, rm, pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->disp8 = pCpu->disp;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->flags |= USE_BASE | USE_DISPLACEMENT8;
090d729e786b999dc285f8ea267f9effd1319544vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pParam->disp8 != 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pParam->disp8 > 0)
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddChar(pParam->szParam, '+');
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmPrintDisp8(pParam);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmAddChar(pParam->szParam, ']');
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync case 2: //effective address + 16 bits displacement
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmGetPtrString(pCpu, pOp, pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmAddChar(pParam->szParam, '[');
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmModRMReg16(pCpu, pOp, rm, pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->disp16 = pCpu->disp;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pParam->flags |= USE_BASE | USE_DISPLACEMENT16;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if(pParam->disp16 != 0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync disasmAddChar(pParam->szParam, '+');
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync disasmPrintDisp16(pParam);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync disasmAddChar(pParam->szParam, ']');
9496f2d398b49813176939d7a339ae513d5175efvboxsync break;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync case 3: //registers
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync disasmModRMReg(pCpu, pOp, rm, pParam, 0);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
caf54c14752060b187e3fca12a6f71f4b13126b8vboxsync return 0; //everything was already fetched in ParseModRM
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync//*****************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync// Query the size of the ModRM parameters and fetch the immediate data (if any)
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsyncunsigned QueryModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, int *pSibInc)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync int mod, rm, sibinc;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync unsigned size = 0;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync rm = MODRM_RM(pCpu->ModRM);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync mod = MODRM_MOD(pCpu->ModRM);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync if(!pSibInc)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync pSibInc = &sibinc;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync *pSibInc = 0;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(pCpu->addrmode == CPUMODE_32BIT)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {//32 bits addressing mode
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(mod != 3 && rm == 4)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {//SIB byte follows ModRM
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *pSibInc = ParseSIB(lpszCodeBlock, pOp, pParam, pCpu);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync lpszCodeBlock += *pSibInc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size += *pSibInc;
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync }
090d729e786b999dc285f8ea267f9effd1319544vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch(mod)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 0: //effective address
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(rm == 5) {//32 bits displacement
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size += sizeof(int32_t);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync }
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync //else register address
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync case 1: //effective address + 8 bits displacement
16a9adc14900ca18e6909679a579f6833425e030vboxsync pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size += sizeof(char);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync case 2: //effective address + 32 bits displacement
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
16a9adc14900ca18e6909679a579f6833425e030vboxsync size += sizeof(int32_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 3: //registers
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {//16 bits addressing mode
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch(mod)
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync {
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync case 0: //effective address
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync if(rm == 6) {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pCpu->disp = DISReadWord(pCpu, lpszCodeBlock);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync size += sizeof(uint16_t);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync }
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync break;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync case 1: //effective address + 8 bits displacement
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync size += sizeof(char);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync break;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync case 2: //effective address + 16 bits displacement
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync pCpu->disp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync size += sizeof(uint16_t);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync break;
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync case 3: //registers
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync break;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync }
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync }
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return size;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync}
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync// Query the size of the ModRM parameters and fetch the immediate data (if any)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncunsigned QueryModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, int *pSibInc)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync{
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync int mod, rm, sibinc;
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync unsigned size = 0;
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync rm = MODRM_RM(pCpu->ModRM);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync mod = MODRM_MOD(pCpu->ModRM);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(!pSibInc)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync {
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync pSibInc = &sibinc;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync }
81c82bebae20d8743f59b8f3c38f0b1b7310abb3vboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync *pSibInc = 0;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync if(pCpu->addrmode == CPUMODE_32BIT)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync {//32 bits addressing mode
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync if(mod != 3 && rm == 4)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync {//SIB byte follows ModRM
16a9adc14900ca18e6909679a579f6833425e030vboxsync *pSibInc = ParseSIB_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu);
16a9adc14900ca18e6909679a579f6833425e030vboxsync lpszCodeBlock += *pSibInc;
16a9adc14900ca18e6909679a579f6833425e030vboxsync size += *pSibInc;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync switch(mod)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync case 0: //effective address
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(rm == 5) {//32 bits displacement
16a9adc14900ca18e6909679a579f6833425e030vboxsync size += sizeof(int32_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync //else register address
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync case 1: //effective address + 8 bits displacement
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size += sizeof(char);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 2: //effective address + 32 bits displacement
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size += sizeof(int32_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case 3: //registers
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {//16 bits addressing mode
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync switch(mod)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case 0: //effective address
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if(rm == 6) {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync size += sizeof(uint16_t);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case 1: //effective address + 8 bits displacement
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync size += sizeof(char);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync case 2: //effective address + 16 bits displacement
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync size += sizeof(uint16_t);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync case 3: //registers
efff36b306e370346025647a158689021df2e1d1vboxsync break;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync }
efff36b306e370346025647a158689021df2e1d1vboxsync }
efff36b306e370346025647a158689021df2e1d1vboxsync return size;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync//*****************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync//*****************************************************************************
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncunsigned ParseIllegal(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertFailed();
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return 0;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync//*****************************************************************************
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync//*****************************************************************************
efff36b306e370346025647a158689021df2e1d1vboxsyncunsigned ParseModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync{
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync unsigned size = sizeof(uint8_t); //ModRM byte
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync int sibinc;
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync lpszCodeBlock += sizeof(uint8_t);
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync size += QueryModRM(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync lpszCodeBlock += sibinc;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync UseModRM(lpszCodeBlock, pOp, pParam, pCpu);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync return size;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync}
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncunsigned ParseModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync{
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync unsigned size = sizeof(uint8_t); //ModRM byte
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync int sibinc;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync lpszCodeBlock += sizeof(uint8_t);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync size += QueryModRM_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync lpszCodeBlock += sibinc;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync /* UseModRM is not necessary here; we're only interested in the opcode size */
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync return size;
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync}
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//*****************************************************************************
27b178e99b06a68ef52353b15bc647674d2006bcvboxsyncunsigned ParseModFence(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync ////AssertMsgFailed(("??\n"));
16a9adc14900ca18e6909679a579f6833425e030vboxsync //nothing to do apparently
16a9adc14900ca18e6909679a579f6833425e030vboxsync return 0;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmByte(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_IMMEDIATE8;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%02Xh", (uint32_t)pParam->parval);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(uint8_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmByte_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(uint8_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
bbede9c189def47a9880f0ffb03c0c230c774185vboxsyncunsigned ParseImmByteSX(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync{
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync if(pCpu->opmode == CPUMODE_32BIT)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync {
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync pParam->parval = (uint32_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pParam->flags |= USE_IMMEDIATE32_SX8;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync else
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync {
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync pParam->parval = (uint16_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_IMMEDIATE16_SX8;
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return sizeof(uint8_t);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync//*****************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync//*****************************************************************************
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncunsigned ParseImmByteSX_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return sizeof(uint8_t);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncunsigned ParseImmUshort(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_IMMEDIATE16;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return sizeof(uint16_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync//*****************************************************************************
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsyncunsigned ParseImmUshort_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync{
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync return sizeof(uint16_t);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync}
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync//*****************************************************************************
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync//*****************************************************************************
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncunsigned ParseImmUlong(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_IMMEDIATE32;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(uint32_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmUlong_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(uint32_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmQword(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_IMMEDIATE64;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08X", (uint32_t)pParam->parval);
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddStringF(&pParam->szParam[9], sizeof(pParam->szParam)-9, "%08Xh", (uint32_t)(pParam->parval >> 32));
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(uint64_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmQword_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(uint64_t);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmV(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pCpu->opmode == CPUMODE_32BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
16a9adc14900ca18e6909679a579f6833425e030vboxsync pParam->flags |= USE_IMMEDIATE32;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync return sizeof(uint32_t);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync }
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync else
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_IMMEDIATE16;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint32_t)pParam->parval);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return sizeof(uint16_t);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncunsigned ParseImmV_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync if(pCpu->opmode == CPUMODE_32BIT)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync return sizeof(uint32_t);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync return sizeof(uint16_t);
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync//*****************************************************************************
9496f2d398b49813176939d7a339ae513d5175efvboxsync// Relative displacement for branches (rel. to next instruction)
9496f2d398b49813176939d7a339ae513d5175efvboxsync//*****************************************************************************
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsyncunsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_IMMEDIATE8_REL;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%02Xh)", (uint32_t)pParam->parval);
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync return sizeof(char);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync}
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync//*****************************************************************************
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync// Relative displacement for branches (rel. to next instruction)
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync//*****************************************************************************
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncunsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync{
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync return sizeof(char);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync}
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// Relative displacement for branches (rel. to next instruction)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsyncunsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if(pCpu->opmode == CPUMODE_32BIT)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
9496f2d398b49813176939d7a339ae513d5175efvboxsync pParam->flags |= USE_IMMEDIATE32_REL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%08Xh)", (uint32_t)pParam->parval);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync return sizeof(int32_t);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync }
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_IMMEDIATE16_REL;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%04Xh)", (uint32_t)pParam->parval);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return sizeof(uint16_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsync// Relative displacement for branches (rel. to next instruction)
16a9adc14900ca18e6909679a579f6833425e030vboxsync//*****************************************************************************
16a9adc14900ca18e6909679a579f6833425e030vboxsyncunsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync if(pCpu->opmode == CPUMODE_32BIT)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync return sizeof(int32_t);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return sizeof(uint16_t);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync//*****************************************************************************
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncunsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync disasmGetPtrString(pCpu, pOp, pParam);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if(pCpu->addrmode == CPUMODE_32BIT)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync {
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync {// far 16:32 pointer
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
4a23807f02e9920d92c8449bd93d84501add460avboxsync pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
4a23807f02e9920d92c8449bd93d84501add460avboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
fe813b3594039ba864493438e78ee0e7132bc445vboxsync return sizeof(uint32_t) + sizeof(uint16_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {// near 32 bits pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so we treat it like displacement.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->disp32 = DISReadDWord(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_DISPLACEMENT32;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
5b465a7c1237993faf8bb50120d247f3f0319adavboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08Xh]", pParam->disp32);
09127e6ed46502ff8a6a521713ee8ace53667683vboxsync return sizeof(uint32_t);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync }
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync }
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync else
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {// far 16:16 pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return sizeof(uint32_t);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {// near 16 bits pointer
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so we treat it like displacement.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync pParam->flags |= USE_DISPLACEMENT16;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return sizeof(uint16_t);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//*****************************************************************************
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync//*****************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncunsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
cba6719bd64ec749967bbe931230452664109857vboxsync if(pCpu->addrmode == CPUMODE_32BIT)
cba6719bd64ec749967bbe931230452664109857vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {// far 16:32 pointer
9496f2d398b49813176939d7a339ae513d5175efvboxsync return sizeof(uint32_t) + sizeof(uint16_t);
cba6719bd64ec749967bbe931230452664109857vboxsync }
cba6719bd64ec749967bbe931230452664109857vboxsync else
cba6719bd64ec749967bbe931230452664109857vboxsync {// near 32 bits pointer
cba6719bd64ec749967bbe931230452664109857vboxsync return sizeof(uint32_t);
cba6719bd64ec749967bbe931230452664109857vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
cba6719bd64ec749967bbe931230452664109857vboxsync else
{
if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
{// far 16:16 pointer
return sizeof(uint32_t);
}
else
{// near 16 bits pointer
return sizeof(uint16_t);
}
}
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
/*
* Sets up flags for stored in OPC fixed registers.
*/
if(pParam->param == OP_PARM_NONE)
{
/* No parameter at all. */
return 0;
}
if(pParam->param < OP_PARM_REG_SEG_START)
{
/* 32-bit EAX..EDI registers. */
if(pCpu->opmode == CPUMODE_32BIT)
{
/* Use 32-bit registers. */
pParam->base.reg_gen32 = pParam->param - OP_PARM_REG_GEN32_START;
pParam->flags |= USE_REG_GEN32;
pParam->size = 4;
}
else
{
/* Use 16-bit registers. */
pParam->base.reg_gen16 = pParam->param - OP_PARM_REG_GEN32_START;
pParam->flags |= USE_REG_GEN16;
pParam->size = 2;
pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
}
}
else
if(pParam->param < OP_PARM_REG_GEN16_START)
{
/* Segment ES..GS registers. */
pParam->base.reg_seg = pParam->param - OP_PARM_REG_SEG_START;
pParam->flags |= USE_REG_SEG;
pParam->size = 2;
}
else
if(pParam->param < OP_PARM_REG_GEN8_START)
{
/* 16-bit AX..DI registers. */
pParam->base.reg_gen16 = pParam->param - OP_PARM_REG_GEN16_START;
pParam->flags |= USE_REG_GEN16;
pParam->size = 2;
}
else
if(pParam->param < OP_PARM_REG_FP_START)
{
/* 8-bit AL..DL, AH..DH registers. */
pParam->base.reg_gen8 = pParam->param - OP_PARM_REG_GEN8_START;
pParam->flags |= USE_REG_GEN8;
pParam->size = 1;
}
else
if(pParam->param <= OP_PARM_REGFP_7)
{
/* FPU registers. */
pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
pParam->flags |= USE_REG_FP;
pParam->size = 10;
}
/* else - not supported for now registers. */
return 0;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmGetPtrString(pCpu, pOp, pParam);
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
pParam->flags |= USE_POINTER_DS_BASED;
if(pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen32 = USE_REG_ESI;
pParam->flags |= USE_REG_GEN32;
}
else
{
pParam->base.reg_gen16 = USE_REG_SI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
pParam->flags |= USE_POINTER_DS_BASED;
if(pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen32 = USE_REG_ESI;
pParam->flags |= USE_REG_GEN32;
}
else
{
pParam->base.reg_gen16 = USE_REG_SI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmGetPtrString(pCpu, pOp, pParam);
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
pParam->flags |= USE_POINTER_ES_BASED;
if(pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen32 = USE_REG_EDI;
pParam->flags |= USE_REG_GEN32;
}
else
{
pParam->base.reg_gen16 = USE_REG_DI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
pParam->flags |= USE_POINTER_ES_BASED;
if(pCpu->addrmode == CPUMODE_32BIT)
{
pParam->base.reg_gen32 = USE_REG_EDI;
pParam->flags |= USE_REG_GEN32;
}
else
{
pParam->base.reg_gen16 = USE_REG_DI;
pParam->flags |= USE_REG_GEN16;
}
return 0; //no additional opcode bytes
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
const OPCODE *pOpcode;
int size = sizeof(uint8_t);
//2nd byte
pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
/* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
/** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
if (pCpu->lastprefix)
{
switch(pCpu->lastprefix)
{
case OP_OPSIZE: /* 0x66 */
if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
{
/* Table entry is valid, so use the extension table. */
pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
/* Cancel prefix changes. */
pCpu->prefix &= ~PREFIX_OPSIZE;
pCpu->opmode = pCpu->mode;
}
break;
case OP_REPNE: /* 0xF2 */
if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
{
/* Table entry is valid, so use the extension table. */
pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
/* Cancel prefix changes. */
pCpu->prefix &= ~PREFIX_REPNE;
}
break;
case OP_REPE: /* 0xF3 */
if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
{
/* Table entry is valid, so use the extension table. */
pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
/* Cancel prefix changes. */
pCpu->prefix &= ~PREFIX_REP;
}
break;
}
}
size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0;
if (pCpu->prefix & PREFIX_REP)
{
pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
pCpu->prefix &= ~PREFIX_REP;
}
else
pOp = &g_aMapX86_NopPause[0]; /* NOP */
size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
int idx = (pCpu->opcode - 0x80) * 8;
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
int idx;
unsigned size = 0, modrm, reg;
switch(pCpu->opcode)
{
case 0xC0:
case 0xC1:
idx = (pCpu->opcode - 0xC0)*8;
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
idx = (pCpu->opcode - 0xD0 + 2)*8;
break;
default:
AssertMsgFailed(("Oops\n"));
return sizeof(uint8_t);
}
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
int idx = (pCpu->opcode - 0xF6) * 8;
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
// It would appear the ModRM byte must always be present. How else can you
// determine the offset of the imm8_opcode byte otherwise?
//
//*****************************************************************************
unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrmsize;
#ifdef DEBUG_Sander
//needs testing
AssertMsgFailed(("Test me\n"));
#endif
pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
AssertMsgFailed(("Oops!\n")); //shouldn't happen!
#endif
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
size += sizeof(uint8_t); //imm8_opcode uint8_t
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg, rm, mod;
modrm = DISReadByte(pCpu, lpszCodeBlock);
mod = MODRM_MOD(modrm);
reg = MODRM_REG(modrm);
rm = MODRM_RM(modrm);
if (mod == 3 && rm == 0)
{
pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
}
else
if (mod == 3 && rm == 1)
{
pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
}
else
pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
if(pCpu->prefix & PREFIX_OPSIZE)
{
reg += 8; //2nd table
}
pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
if(pCpu->prefix & PREFIX_OPSIZE)
{
reg += 8; //2nd table
}
pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
if(pCpu->prefix & PREFIX_OPSIZE)
{
reg += 8; //2nd table
}
pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg, mod, rm;
modrm = DISReadByte(pCpu, lpszCodeBlock);
mod = MODRM_MOD(modrm);
reg = MODRM_REG(modrm);
rm = MODRM_RM(modrm);
if (mod == 3 && rm == 0)
pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
else
pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
//*****************************************************************************
unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
{
unsigned size = 0, modrm, reg;
modrm = DISReadByte(pCpu, lpszCodeBlock);
reg = MODRM_REG(modrm);
pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
//little hack to make sure the ModRM byte is included in the returned size
if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
{
size = sizeof(uint8_t); //ModRM byte
}
size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
return size;
}
//*****************************************************************************
const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
//*****************************************************************************
void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam, int fRegAddr)
{
int subtype, type, mod;
mod = MODRM_MOD(pCpu->ModRM);
type = OP_PARM_VTYPE(pParam->param);
subtype = OP_PARM_VSUBTYPE(pParam->param);
if (fRegAddr)
{
subtype = OP_PARM_d;
}
else
if(subtype == OP_PARM_v || subtype == OP_PARM_NONE)
{
subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
}
switch(subtype)
{
case OP_PARM_b:
disasmAddString(pParam->szParam, szModRMReg8[idx]);
pParam->flags |= USE_REG_GEN8;
pParam->base.reg_gen8 = idx;
break;
case OP_PARM_w:
disasmAddString(pParam->szParam, szModRMReg16[idx]);
pParam->flags |= USE_REG_GEN16;
pParam->base.reg_gen16 = idx;
break;
case OP_PARM_d:
disasmAddString(pParam->szParam, szModRMReg32[idx]);
pParam->flags |= USE_REG_GEN32;
pParam->base.reg_gen32 = idx;
break;
default:
#ifdef IN_RING3
Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
DIS_THROW(ExceptionInvalidModRM);
#else
AssertMsgFailed(("Oops!\n"));
#endif
break;
}
}
//*****************************************************************************
const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
int BaseModRMReg16[8] = { USE_REG_BX, USE_REG_BX, USE_REG_BP, USE_REG_BP, USE_REG_SI, USE_REG_DI, USE_REG_BP, USE_REG_BX};
int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
//*****************************************************************************
void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
{
disasmAddString(pParam->szParam, szModRMReg1616[idx]);
pParam->flags |= USE_REG_GEN16;
pParam->base.reg_gen16 = BaseModRMReg16[idx];
if(idx < 4)
{
pParam->flags |= USE_INDEX;
pParam->index.reg_gen = IndexModRMReg16[idx];
}
}
//*****************************************************************************
const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
//*****************************************************************************
void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
{
#if 0 //def DEBUG_Sander
AssertMsg(idx < (int)ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
#endif
#ifdef IN_RING3
if(idx >= (int)ELEMENTS(szModRMSegReg))
{
Log(("disasmModRMSReg %d failed!!\n", idx));
DIS_THROW(ExceptionInvalidParameter);
}
#endif
idx = RT_MIN(idx, (int)ELEMENTS(szModRMSegReg)-1);
disasmAddString(pParam->szParam, szModRMSegReg[idx]);
pParam->flags |= USE_REG_SEG;
pParam->base.reg_seg = idx;
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintAbs32(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintDisp32(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintDisp8(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
}
//*****************************************************************************
//*****************************************************************************
void disasmPrintDisp16(POP_PARAMETER pParam)
{
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
}
//*****************************************************************************
//*****************************************************************************
void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
{
int subtype = OP_PARM_VSUBTYPE(pParam->param);
if(subtype == OP_PARM_v)
{
subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
}
switch(subtype)
{
case OP_PARM_a: //two words or dwords depending on operand size (bound only)
break;
case OP_PARM_b:
disasmAddString(pParam->szParam, "byte ptr ");
break;
case OP_PARM_w:
disasmAddString(pParam->szParam, "word ptr ");
break;
case OP_PARM_d:
disasmAddString(pParam->szParam, "dword ptr ");
break;
case OP_PARM_q:
case OP_PARM_dq:
disasmAddString(pParam->szParam, "qword ptr ");
break;
case OP_PARM_p:
disasmAddString(pParam->szParam, "far ptr ");
break;
case OP_PARM_s:
break; //??
case OP_PARM_z:
break;
default:
break; //no pointer type specified/necessary
}
if (pCpu->prefix & PREFIX_SEG)
disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->prefix_seg]);
}
#ifndef IN_GC
//*****************************************************************************
/* Read functions for getting the opcode bytes */
//*****************************************************************************
uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if(pCpu->pfnReadBytes)
{
uint8_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
if(VBOX_FAILURE(rc))
{
Log(("DISReadByte failed!!\n"));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint8_t *)pAddress;
#endif
}
//*****************************************************************************
//*****************************************************************************
uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if(pCpu->pfnReadBytes)
{
uint16_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
if(VBOX_FAILURE(rc))
{
Log(("DISReadWord failed!!\n"));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint16_t *)pAddress;
#endif
}
//*****************************************************************************
//*****************************************************************************
uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if(pCpu->pfnReadBytes)
{
uint32_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
if(VBOX_FAILURE(rc))
{
Log(("DISReadDWord failed!!\n"));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint32_t *)pAddress;
#endif
}
//*****************************************************************************
//*****************************************************************************
uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
{
if(pCpu->pfnReadBytes)
{
uint64_t temp = 0;
int rc;
rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
if(VBOX_FAILURE(rc))
{
Log(("DISReadQWord %x failed!!\n", pAddress));
DIS_THROW(ExceptionMemRead);
}
return temp;
}
#ifdef IN_RING0
AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
return 0;
#else
else return *(uint64_t *)pAddress;
#endif
}
#endif /* IN_GC */
#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
//*****************************************************************************
//*****************************************************************************
void disasmAddString(char *psz, const char *pszAdd)
{
strcat(psz, pszAdd);
}
//*****************************************************************************
//*****************************************************************************
void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
{
va_list args;
va_start(args, pszFormat);
RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
va_end(args);
}
//*****************************************************************************
//*****************************************************************************
void disasmAddChar(char *psz, char ch)
{
char sz[2];
sz[0] = ch;
sz[1] = '\0';
strcat(psz, sz);
}
#endif /* !DIS_CORE_ONLY */