VirtualBox

source: vbox/trunk/include/VBox/dis.h@ 53094

Last change on this file since 53094 was 53094, checked in by vboxsync, 10 years ago

DIS: #6251: AVX / VEX instructions support (two byte instructions only) and some fixes to the other tables.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.4 KB
Line 
1/** @file
2 * DIS - The VirtualBox Disassembler.
3 */
4
5/*
6 * Copyright (C) 2006-2012 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___VBox_dis_h
27#define ___VBox_dis_h
28
29#include <VBox/types.h>
30#include <VBox/disopcode.h>
31#include <iprt/assert.h>
32
33
34RT_C_DECLS_BEGIN
35
36
37/** @name Prefix byte flags (DISSTATE::fPrefix).
38 * @{
39 */
40#define DISPREFIX_NONE UINT8_C(0x00)
41/** non-default address size. */
42#define DISPREFIX_ADDRSIZE UINT8_C(0x01)
43/** non-default operand size. */
44#define DISPREFIX_OPSIZE UINT8_C(0x02)
45/** lock prefix. */
46#define DISPREFIX_LOCK UINT8_C(0x04)
47/** segment prefix. */
48#define DISPREFIX_SEG UINT8_C(0x08)
49/** rep(e) prefix (not a prefix, but we'll treat is as one). */
50#define DISPREFIX_REP UINT8_C(0x10)
51/** rep(e) prefix (not a prefix, but we'll treat is as one). */
52#define DISPREFIX_REPNE UINT8_C(0x20)
53/** REX prefix (64 bits) */
54#define DISPREFIX_REX UINT8_C(0x40)
55/** @} */
56
57/** @name VEX.Lvvvv prefix destination register flag.
58 * @{
59 */
60#define VEX_LEN256 UINT8_C(0x01)
61#define VEXREG_IS256B(x) ((x) & VEX_LEN256)
62/* Convert second byte of VEX prefix to internal format */
63#define VEX_2B2INT(x) ((((x) >> 2) & 0x1f))
64#define VEX_HAS_REX_R(x) (!((x) & 0x80))
65 /** @} */
66
67/** @name 64 bits prefix byte flags (DISSTATE::fRexPrefix).
68 * Requires VBox/disopcode.h.
69 * @{
70 */
71#define DISPREFIX_REX_OP_2_FLAGS(a) (a - OP_PARM_REX_START)
72/*#define DISPREFIX_REX_FLAGS DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX) - 0, which is no flag */
73#define DISPREFIX_REX_FLAGS_B DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_B)
74#define DISPREFIX_REX_FLAGS_X DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_X)
75#define DISPREFIX_REX_FLAGS_XB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_XB)
76#define DISPREFIX_REX_FLAGS_R DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_R)
77#define DISPREFIX_REX_FLAGS_RB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RB)
78#define DISPREFIX_REX_FLAGS_RX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RX)
79#define DISPREFIX_REX_FLAGS_RXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RXB)
80#define DISPREFIX_REX_FLAGS_W DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_W)
81#define DISPREFIX_REX_FLAGS_WB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WB)
82#define DISPREFIX_REX_FLAGS_WX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WX)
83#define DISPREFIX_REX_FLAGS_WXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WXB)
84#define DISPREFIX_REX_FLAGS_WR DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WR)
85#define DISPREFIX_REX_FLAGS_WRB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRB)
86#define DISPREFIX_REX_FLAGS_WRX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRX)
87#define DISPREFIX_REX_FLAGS_WRXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRXB)
88/** @} */
89AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_B));
90AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_X));
91AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_W));
92AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_R));
93
94/** @name Operand type (DISOPCODE::fOpType).
95 * @{
96 */
97#define DISOPTYPE_INVALID RT_BIT_32(0)
98#define DISOPTYPE_HARMLESS RT_BIT_32(1)
99#define DISOPTYPE_CONTROLFLOW RT_BIT_32(2)
100#define DISOPTYPE_POTENTIALLY_DANGEROUS RT_BIT_32(3)
101#define DISOPTYPE_DANGEROUS RT_BIT_32(4)
102#define DISOPTYPE_PORTIO RT_BIT_32(5)
103#define DISOPTYPE_PRIVILEGED RT_BIT_32(6)
104#define DISOPTYPE_PRIVILEGED_NOTRAP RT_BIT_32(7)
105#define DISOPTYPE_UNCOND_CONTROLFLOW RT_BIT_32(8)
106#define DISOPTYPE_RELATIVE_CONTROLFLOW RT_BIT_32(9)
107#define DISOPTYPE_COND_CONTROLFLOW RT_BIT_32(10)
108#define DISOPTYPE_INTERRUPT RT_BIT_32(11)
109#define DISOPTYPE_ILLEGAL RT_BIT_32(12)
110#define DISOPTYPE_RRM_DANGEROUS RT_BIT_32(14) /**< Some additional dangerous ones when recompiling raw r0. */
111#define DISOPTYPE_RRM_DANGEROUS_16 RT_BIT_32(15) /**< Some additional dangerous ones when recompiling 16-bit raw r0. */
112#define DISOPTYPE_RRM_MASK (DISOPTYPE_RRM_DANGEROUS | DISOPTYPE_RRM_DANGEROUS_16)
113#define DISOPTYPE_INHIBIT_IRQS RT_BIT_32(16) /**< Will or can inhibit irqs (sti, pop ss, mov ss) */
114#define DISOPTYPE_PORTIO_READ RT_BIT_32(17)
115#define DISOPTYPE_PORTIO_WRITE RT_BIT_32(18)
116#define DISOPTYPE_INVALID_64 RT_BIT_32(19) /**< Invalid in 64 bits mode */
117#define DISOPTYPE_ONLY_64 RT_BIT_32(20) /**< Only valid in 64 bits mode */
118#define DISOPTYPE_DEFAULT_64_OP_SIZE RT_BIT_32(21) /**< Default 64 bits operand size */
119#define DISOPTYPE_FORCED_64_OP_SIZE RT_BIT_32(22) /**< Forced 64 bits operand size; regardless of prefix bytes */
120#define DISOPTYPE_REXB_EXTENDS_OPREG RT_BIT_32(23) /**< REX.B extends the register field in the opcode byte */
121#define DISOPTYPE_MOD_FIXED_11 RT_BIT_32(24) /**< modrm.mod is always 11b */
122#define DISOPTYPE_FORCED_32_OP_SIZE_X86 RT_BIT_32(25) /**< Forced 32 bits operand size; regardless of prefix bytes (only in 16 & 32 bits mode!) */
123#define DISOPTYPE_SSE RT_BIT_32(29) /**< SSE,SSE2,SSE3,AVX,++ instruction. Not implemented yet! */
124#define DISOPTYPE_MMX RT_BIT_32(30) /**< MMX,MMXExt,3DNow,++ instruction. Not implemented yet! */
125#define DISOPTYPE_FPU RT_BIT_32(31) /**< FPU instruction. Not implemented yet! */
126#define DISOPTYPE_ALL UINT32_C(0xffffffff)
127/** @} */
128
129/** @name Parameter usage flags.
130 * @{
131 */
132#define DISUSE_BASE RT_BIT_64(0)
133#define DISUSE_INDEX RT_BIT_64(1)
134#define DISUSE_SCALE RT_BIT_64(2)
135#define DISUSE_REG_GEN8 RT_BIT_64(3)
136#define DISUSE_REG_GEN16 RT_BIT_64(4)
137#define DISUSE_REG_GEN32 RT_BIT_64(5)
138#define DISUSE_REG_GEN64 RT_BIT_64(6)
139#define DISUSE_REG_FP RT_BIT_64(7)
140#define DISUSE_REG_MMX RT_BIT_64(8)
141#define DISUSE_REG_XMM RT_BIT_64(9)
142#define DISUSE_REG_YMM RT_BIT_64(10)
143#define DISUSE_REG_CR RT_BIT_64(11)
144#define DISUSE_REG_DBG RT_BIT_64(12)
145#define DISUSE_REG_SEG RT_BIT_64(13)
146#define DISUSE_REG_TEST RT_BIT_64(14)
147#define DISUSE_DISPLACEMENT8 RT_BIT_64(15)
148#define DISUSE_DISPLACEMENT16 RT_BIT_64(16)
149#define DISUSE_DISPLACEMENT32 RT_BIT_64(17)
150#define DISUSE_DISPLACEMENT64 RT_BIT_64(18)
151#define DISUSE_RIPDISPLACEMENT32 RT_BIT_64(19)
152#define DISUSE_IMMEDIATE8 RT_BIT_64(20)
153#define DISUSE_IMMEDIATE8_REL RT_BIT_64(21)
154#define DISUSE_IMMEDIATE16 RT_BIT_64(22)
155#define DISUSE_IMMEDIATE16_REL RT_BIT_64(23)
156#define DISUSE_IMMEDIATE32 RT_BIT_64(24)
157#define DISUSE_IMMEDIATE32_REL RT_BIT_64(25)
158#define DISUSE_IMMEDIATE64 RT_BIT_64(26)
159#define DISUSE_IMMEDIATE64_REL RT_BIT_64(27)
160#define DISUSE_IMMEDIATE_ADDR_0_32 RT_BIT_64(28)
161#define DISUSE_IMMEDIATE_ADDR_16_32 RT_BIT_64(29)
162#define DISUSE_IMMEDIATE_ADDR_0_16 RT_BIT_64(30)
163#define DISUSE_IMMEDIATE_ADDR_16_16 RT_BIT_64(31)
164/** DS:ESI */
165#define DISUSE_POINTER_DS_BASED RT_BIT_64(32)
166/** ES:EDI */
167#define DISUSE_POINTER_ES_BASED RT_BIT_64(33)
168#define DISUSE_IMMEDIATE16_SX8 RT_BIT_64(34)
169#define DISUSE_IMMEDIATE32_SX8 RT_BIT_64(35)
170#define DISUSE_IMMEDIATE64_SX8 RT_BIT_64(36)
171
172/** Mask of immediate use flags. */
173#define DISUSE_IMMEDIATE ( DISUSE_IMMEDIATE8 \
174 | DISUSE_IMMEDIATE16 \
175 | DISUSE_IMMEDIATE32 \
176 | DISUSE_IMMEDIATE64 \
177 | DISUSE_IMMEDIATE8_REL \
178 | DISUSE_IMMEDIATE16_REL \
179 | DISUSE_IMMEDIATE32_REL \
180 | DISUSE_IMMEDIATE64_REL \
181 | DISUSE_IMMEDIATE_ADDR_0_32 \
182 | DISUSE_IMMEDIATE_ADDR_16_32 \
183 | DISUSE_IMMEDIATE_ADDR_0_16 \
184 | DISUSE_IMMEDIATE_ADDR_16_16 \
185 | DISUSE_IMMEDIATE16_SX8 \
186 | DISUSE_IMMEDIATE32_SX8 \
187 | DISUSE_IMMEDIATE64_SX8)
188/** Check if the use flags indicates an effective address. */
189#define DISUSE_IS_EFFECTIVE_ADDR(a_fUseFlags) (!!( (a_fUseFlags) \
190 & ( DISUSE_BASE \
191 | DISUSE_INDEX \
192 | DISUSE_DISPLACEMENT32 \
193 | DISUSE_DISPLACEMENT64 \
194 | DISUSE_DISPLACEMENT16 \
195 | DISUSE_DISPLACEMENT8 \
196 | DISUSE_RIPDISPLACEMENT32) ))
197/** @} */
198
199/** @name 64-bit general register indexes.
200 * This matches the AMD64 register encoding. It is found used in
201 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
202 * @note Safe to assume same values as the 16-bit and 32-bit general registers.
203 * @{
204 */
205#define DISGREG_RAX UINT8_C(0)
206#define DISGREG_RCX UINT8_C(1)
207#define DISGREG_RDX UINT8_C(2)
208#define DISGREG_RBX UINT8_C(3)
209#define DISGREG_RSP UINT8_C(4)
210#define DISGREG_RBP UINT8_C(5)
211#define DISGREG_RSI UINT8_C(6)
212#define DISGREG_RDI UINT8_C(7)
213#define DISGREG_R8 UINT8_C(8)
214#define DISGREG_R9 UINT8_C(9)
215#define DISGREG_R10 UINT8_C(10)
216#define DISGREG_R11 UINT8_C(11)
217#define DISGREG_R12 UINT8_C(12)
218#define DISGREG_R13 UINT8_C(13)
219#define DISGREG_R14 UINT8_C(14)
220#define DISGREG_R15 UINT8_C(15)
221/** @} */
222
223/** @name 32-bit general register indexes.
224 * This matches the AMD64 register encoding. It is found used in
225 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
226 * @note Safe to assume same values as the 16-bit and 64-bit general registers.
227 * @{
228 */
229#define DISGREG_EAX UINT8_C(0)
230#define DISGREG_ECX UINT8_C(1)
231#define DISGREG_EDX UINT8_C(2)
232#define DISGREG_EBX UINT8_C(3)
233#define DISGREG_ESP UINT8_C(4)
234#define DISGREG_EBP UINT8_C(5)
235#define DISGREG_ESI UINT8_C(6)
236#define DISGREG_EDI UINT8_C(7)
237#define DISGREG_R8D UINT8_C(8)
238#define DISGREG_R9D UINT8_C(9)
239#define DISGREG_R10D UINT8_C(10)
240#define DISGREG_R11D UINT8_C(11)
241#define DISGREG_R12D UINT8_C(12)
242#define DISGREG_R13D UINT8_C(13)
243#define DISGREG_R14D UINT8_C(14)
244#define DISGREG_R15D UINT8_C(15)
245/** @} */
246
247/** @name 16-bit general register indexes.
248 * This matches the AMD64 register encoding. It is found used in
249 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
250 * @note Safe to assume same values as the 32-bit and 64-bit general registers.
251 * @{
252 */
253#define DISGREG_AX UINT8_C(0)
254#define DISGREG_CX UINT8_C(1)
255#define DISGREG_DX UINT8_C(2)
256#define DISGREG_BX UINT8_C(3)
257#define DISGREG_SP UINT8_C(4)
258#define DISGREG_BP UINT8_C(5)
259#define DISGREG_SI UINT8_C(6)
260#define DISGREG_DI UINT8_C(7)
261#define DISGREG_R8W UINT8_C(8)
262#define DISGREG_R9W UINT8_C(9)
263#define DISGREG_R10W UINT8_C(10)
264#define DISGREG_R11W UINT8_C(11)
265#define DISGREG_R12W UINT8_C(12)
266#define DISGREG_R13W UINT8_C(13)
267#define DISGREG_R14W UINT8_C(14)
268#define DISGREG_R15W UINT8_C(15)
269/** @} */
270
271/** @name 8-bit general register indexes.
272 * This mostly (?) matches the AMD64 register encoding. It is found used in
273 * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
274 * @{
275 */
276#define DISGREG_AL UINT8_C(0)
277#define DISGREG_CL UINT8_C(1)
278#define DISGREG_DL UINT8_C(2)
279#define DISGREG_BL UINT8_C(3)
280#define DISGREG_AH UINT8_C(4)
281#define DISGREG_CH UINT8_C(5)
282#define DISGREG_DH UINT8_C(6)
283#define DISGREG_BH UINT8_C(7)
284#define DISGREG_R8B UINT8_C(8)
285#define DISGREG_R9B UINT8_C(9)
286#define DISGREG_R10B UINT8_C(10)
287#define DISGREG_R11B UINT8_C(11)
288#define DISGREG_R12B UINT8_C(12)
289#define DISGREG_R13B UINT8_C(13)
290#define DISGREG_R14B UINT8_C(14)
291#define DISGREG_R15B UINT8_C(15)
292#define DISGREG_SPL UINT8_C(16)
293#define DISGREG_BPL UINT8_C(17)
294#define DISGREG_SIL UINT8_C(18)
295#define DISGREG_DIL UINT8_C(19)
296/** @} */
297
298/** @name Segment registerindexes.
299 * This matches the AMD64 register encoding. It is found used in
300 * DISOPPARAM::Base.idxSegReg.
301 * @{
302 */
303typedef enum
304{
305 DISSELREG_ES = 0,
306 DISSELREG_CS = 1,
307 DISSELREG_SS = 2,
308 DISSELREG_DS = 3,
309 DISSELREG_FS = 4,
310 DISSELREG_GS = 5,
311 /** End of the valid register index values. */
312 DISSELREG_END,
313 /** The usual 32-bit paranoia. */
314 DIS_SEGREG_32BIT_HACK = 0x7fffffff
315} DISSELREG;
316/** @} */
317
318/** @name FPU register indexes.
319 * This matches the AMD64 register encoding. It is found used in
320 * DISOPPARAM::Base.idxFpuReg.
321 * @{
322 */
323#define DISFPREG_ST0 UINT8_C(0)
324#define DISFPREG_ST1 UINT8_C(1)
325#define DISFPREG_ST2 UINT8_C(2)
326#define DISFPREG_ST3 UINT8_C(3)
327#define DISFPREG_ST4 UINT8_C(4)
328#define DISFPREG_ST5 UINT8_C(5)
329#define DISFPREG_ST6 UINT8_C(6)
330#define DISFPREG_ST7 UINT8_C(7)
331/** @} */
332
333/** @name Control register indexes.
334 * This matches the AMD64 register encoding. It is found used in
335 * DISOPPARAM::Base.idxCtrlReg.
336 * @{
337 */
338#define DISCREG_CR0 UINT8_C(0)
339#define DISCREG_CR1 UINT8_C(1)
340#define DISCREG_CR2 UINT8_C(2)
341#define DISCREG_CR3 UINT8_C(3)
342#define DISCREG_CR4 UINT8_C(4)
343#define DISCREG_CR8 UINT8_C(8)
344/** @} */
345
346/** @name Debug register indexes.
347 * This matches the AMD64 register encoding. It is found used in
348 * DISOPPARAM::Base.idxDbgReg.
349 * @{
350 */
351#define DISDREG_DR0 UINT8_C(0)
352#define DISDREG_DR1 UINT8_C(1)
353#define DISDREG_DR2 UINT8_C(2)
354#define DISDREG_DR3 UINT8_C(3)
355#define DISDREG_DR4 UINT8_C(4)
356#define DISDREG_DR5 UINT8_C(5)
357#define DISDREG_DR6 UINT8_C(6)
358#define DISDREG_DR7 UINT8_C(7)
359/** @} */
360
361/** @name MMX register indexes.
362 * This matches the AMD64 register encoding. It is found used in
363 * DISOPPARAM::Base.idxMmxReg.
364 * @{
365 */
366#define DISMREG_MMX0 UINT8_C(0)
367#define DISMREG_MMX1 UINT8_C(1)
368#define DISMREG_MMX2 UINT8_C(2)
369#define DISMREG_MMX3 UINT8_C(3)
370#define DISMREG_MMX4 UINT8_C(4)
371#define DISMREG_MMX5 UINT8_C(5)
372#define DISMREG_MMX6 UINT8_C(6)
373#define DISMREG_MMX7 UINT8_C(7)
374/** @} */
375
376/** @name SSE register indexes.
377 * This matches the AMD64 register encoding. It is found used in
378 * DISOPPARAM::Base.idxXmmReg.
379 * @{
380 */
381#define DISXREG_XMM0 UINT8_C(0)
382#define DISXREG_XMM1 UINT8_C(1)
383#define DISXREG_XMM2 UINT8_C(2)
384#define DISXREG_XMM3 UINT8_C(3)
385#define DISXREG_XMM4 UINT8_C(4)
386#define DISXREG_XMM5 UINT8_C(5)
387#define DISXREG_XMM6 UINT8_C(6)
388#define DISXREG_XMM7 UINT8_C(7)
389/** @} */
390
391
392/**
393 * Opcode parameter (operand) details.
394 */
395typedef struct DISOPPARAM
396{
397 /** A combination of DISUSE_XXX. */
398 uint64_t fUse;
399 /** Immediate value or address, applicable if any of the flags included in
400 * DISUSE_IMMEDIATE are set in fUse. */
401 uint64_t uValue;
402 /** Disposition. */
403 union
404 {
405 /** 64-bit displacement, applicable if DISUSE_DISPLACEMENT64 is set in fUse. */
406 int64_t i64;
407 uint64_t u64;
408 /** 32-bit displacement, applicable if DISUSE_DISPLACEMENT32 or
409 * DISUSE_RIPDISPLACEMENT32 is set in fUse. */
410 int32_t i32;
411 uint32_t u32;
412 /** 16-bit displacement, applicable if DISUSE_DISPLACEMENT16 is set in fUse. */
413 int32_t i16;
414 uint32_t u16;
415 /** 8-bit displacement, applicable if DISUSE_DISPLACEMENT8 is set in fUse. */
416 int32_t i8;
417 uint32_t u8;
418 } uDisp;
419 /** The base register from ModR/M or SIB, applicable if DISUSE_BASE is
420 * set in fUse. */
421 union
422 {
423 /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN8,
424 * DISUSE_REG_GEN16, DISUSE_REG_GEN32 or DISUSE_REG_GEN64 is set in fUse. */
425 uint8_t idxGenReg;
426 /** FPU stack register index (DISFPREG_XXX), applicable if DISUSE_REG_FP is
427 * set in fUse. 1:1 indexes. */
428 uint8_t idxFpuReg;
429 /** MMX register index (DISMREG_XXX), applicable if DISUSE_REG_MMX is
430 * set in fUse. 1:1 indexes. */
431 uint8_t idxMmxReg;
432 /** SSE register index (DISXREG_XXX), applicable if DISUSE_REG_XMM is
433 * set in fUse. 1:1 indexes. */
434 uint8_t idxXmmReg;
435 /** SSE2 register index (DISYREG_XXX), applicable if DISUSE_REG_YMM is
436 * set in fUse. 1:1 indexes. */
437 uint8_t idxYmmReg;
438 /** Segment register index (DISSELREG_XXX), applicable if DISUSE_REG_SEG is
439 * set in fUse. */
440 uint8_t idxSegReg;
441 /** Test register, TR0-TR7, present on early IA32 CPUs, applicable if
442 * DISUSE_REG_TEST is set in fUse. No index defines for these. */
443 uint8_t idxTestReg;
444 /** Control register index (DISCREG_XXX), applicable if DISUSE_REG_CR is
445 * set in fUse. 1:1 indexes. */
446 uint8_t idxCtrlReg;
447 /** Debug register index (DISDREG_XXX), applicable if DISUSE_REG_DBG is
448 * set in fUse. 1:1 indexes. */
449 uint8_t idxDbgReg;
450 } Base;
451 /** The SIB index register meaning, applicable if DISUSE_INDEX is
452 * set in fUse. */
453 union
454 {
455 /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN8,
456 * DISUSE_REG_GEN16, DISUSE_REG_GEN32 or DISUSE_REG_GEN64 is set in fUse. */
457 uint8_t idxGenReg;
458 } Index;
459 /** 2, 4 or 8, if DISUSE_SCALE is set in fUse. */
460 uint8_t uScale;
461 /** Parameter size. */
462 uint8_t cb;
463 /** Copy of the corresponding DISOPCODE::fParam1 / DISOPCODE::fParam2 /
464 * DISOPCODE::fParam3. */
465 uint32_t fParam;
466} DISOPPARAM;
467AssertCompileSize(DISOPPARAM, 32);
468/** Pointer to opcode parameter. */
469typedef DISOPPARAM *PDISOPPARAM;
470/** Pointer to opcode parameter. */
471typedef const DISOPPARAM *PCDISOPPARAM;
472
473
474/**
475 * Opcode descriptor.
476 */
477typedef struct DISOPCODE
478{
479#ifndef DIS_CORE_ONLY
480 const char *pszOpcode;
481#endif
482 /** Parameter \#1 parser index. */
483 uint8_t idxParse1;
484 /** Parameter \#2 parser index. */
485 uint8_t idxParse2;
486 /** Parameter \#3 parser index. */
487 uint8_t idxParse3;
488 /** Parameter \#4 parser index. */
489 uint8_t idxParse4;
490 /** The opcode identifier. This DIS specific, @see grp_dis_opcodes and
491 * VBox/disopcode.h. */
492 uint16_t uOpcode;
493 /** Parameter \#1 info, @see grp_dis_opparam. */
494 uint16_t fParam1;
495 /** Parameter \#2 info, @see grp_dis_opparam. */
496 uint16_t fParam2;
497 /** Parameter \#3 info, @see grp_dis_opparam. */
498 uint16_t fParam3;
499 /** Parameter \#4 info, @see grp_dis_opparam. */
500 uint16_t fParam4;
501 /** padding unused */
502 uint16_t uPadding;
503 /** Operand type flags, DISOPTYPE_XXX. */
504 uint32_t fOpType;
505} DISOPCODE;
506/** Pointer to const opcode. */
507typedef const struct DISOPCODE *PCDISOPCODE;
508
509
510/**
511 * Callback for reading instruction bytes.
512 *
513 * @returns VBox status code, bytes in DISSTATE::abInstr and byte count in
514 * DISSTATE::cbCachedInstr.
515 * @param pDis Pointer to the disassembler state. The user
516 * argument can be found in DISSTATE::pvUser if needed.
517 * @param offInstr The offset relative to the start of the instruction.
518 *
519 * To get the source address, add this to
520 * DISSTATE::uInstrAddr.
521 *
522 * To calculate the destination buffer address, use it
523 * as an index into DISSTATE::abInstr.
524 *
525 * @param cbMinRead The minimum number of bytes to read.
526 * @param cbMaxRead The maximum number of bytes that may be read.
527 */
528typedef DECLCALLBACK(int) FNDISREADBYTES(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead);
529/** Pointer to a opcode byte reader. */
530typedef FNDISREADBYTES *PFNDISREADBYTES;
531
532/** Parser callback.
533 * @remark no DECLCALLBACK() here because it's considered to be internal and
534 * there is no point in enforcing CDECL. */
535typedef size_t FNDISPARSE(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam);
536/** Pointer to a disassembler parser function. */
537typedef FNDISPARSE *PFNDISPARSE;
538/** Pointer to a const disassembler parser function pointer. */
539typedef PFNDISPARSE const *PCPFNDISPARSE;
540
541/**
542 * The diassembler state and result.
543 */
544typedef struct DISSTATE
545{
546 /** The number of valid bytes in abInstr. */
547 uint8_t cbCachedInstr;
548 /** SIB fields. */
549 union
550 {
551 /** Bitfield view */
552 struct
553 {
554 uint8_t Base;
555 uint8_t Index;
556 uint8_t Scale;
557 } Bits;
558 } SIB;
559 /** ModRM fields. */
560 union
561 {
562 /** Bitfield view */
563 struct
564 {
565 uint8_t Rm;
566 uint8_t Reg;
567 uint8_t Mod;
568 } Bits;
569 } ModRM;
570 /** The CPU mode (DISCPUMODE). */
571 uint8_t uCpuMode;
572 /** The addressing mode (DISCPUMODE). */
573 uint8_t uAddrMode;
574 /** The operand mode (DISCPUMODE). */
575 uint8_t uOpMode;
576 /** Per instruction prefix settings. */
577 uint8_t fPrefix;
578 /** REX prefix value (64 bits only). */
579 uint8_t fRexPrefix;
580 /** Segment prefix value (DISSELREG). */
581 uint8_t idxSegPrefix;
582 /** Last prefix byte (for SSE2 extension tables). */
583 uint8_t bLastPrefix;
584 /** Last significan opcode byte of instruction. */
585 uint8_t bOpCode;
586 /** The size of the prefix bytes. */
587 uint8_t cbPrefix;
588 /** The instruction size. */
589 uint8_t cbInstr;
590 /** VEX presence flag, destination register and size */
591 uint8_t bVexDestReg;
592 /** Unused bytes. */
593 uint8_t abUnused[2];
594 /** Internal: instruction filter */
595 uint32_t fFilter;
596 /** Internal: pointer to disassembly function table */
597 PCPFNDISPARSE pfnDisasmFnTable;
598#if ARCH_BITS == 32
599 uint32_t uPtrPadding1;
600#endif
601 /** Pointer to the current instruction. */
602 PCDISOPCODE pCurInstr;
603#if ARCH_BITS == 32
604 uint32_t uPtrPadding2;
605#endif
606 /** The instruction bytes. */
607 uint8_t abInstr[16];
608 /** SIB displacment. */
609 int32_t i32SibDisp;
610
611 /** Return code set by a worker function like the opcode bytes readers. */
612 int32_t rc;
613 /** The address of the instruction. */
614 RTUINTPTR uInstrAddr;
615 /** Optional read function */
616 PFNDISREADBYTES pfnReadBytes;
617#if ARCH_BITS == 32
618 uint32_t uPadding3;
619#endif
620 /** User data supplied as an argument to the APIs. */
621 void *pvUser;
622#if ARCH_BITS == 32
623 uint32_t uPadding4;
624#endif
625 /** Parameters. */
626 DISOPPARAM Param1;
627 DISOPPARAM Param2;
628 DISOPPARAM Param3;
629 DISOPPARAM Param4;
630} DISSTATE;
631AssertCompileSize(DISSTATE, 0xd8);
632
633/** @deprecated Use DISSTATE and change Cpu and DisState to Dis. */
634typedef DISSTATE DISCPUSTATE;
635
636
637
638DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
639 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
640DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
641 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
642DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
643 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
644 PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
645
646DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr);
647DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
648 PDISSTATE pDis, uint32_t *pcbInstr);
649DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
650 PFNDISREADBYTES pfnReadBytes, void *pvUser,
651 PDISSTATE pDis, uint32_t *pcbInstr);
652DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
653 void const *pvPrefetched, size_t cbPretched,
654 PFNDISREADBYTES pfnReadBytes, void *pvUser,
655 PDISSTATE pDis, uint32_t *pcbInstr);
656
657DISDECL(int) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam);
658DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam);
659DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis);
660
661
662
663/** @name Flags returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
664 * @{
665 */
666#define DISQPV_FLAG_8 UINT8_C(0x01)
667#define DISQPV_FLAG_16 UINT8_C(0x02)
668#define DISQPV_FLAG_32 UINT8_C(0x04)
669#define DISQPV_FLAG_64 UINT8_C(0x08)
670#define DISQPV_FLAG_FARPTR16 UINT8_C(0x10)
671#define DISQPV_FLAG_FARPTR32 UINT8_C(0x20)
672/** @} */
673
674/** @name Types returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
675 * @{ */
676#define DISQPV_TYPE_REGISTER UINT8_C(1)
677#define DISQPV_TYPE_ADDRESS UINT8_C(2)
678#define DISQPV_TYPE_IMMEDIATE UINT8_C(3)
679/** @} */
680
681typedef struct
682{
683 union
684 {
685 uint8_t val8;
686 uint16_t val16;
687 uint32_t val32;
688 uint64_t val64;
689
690 struct
691 {
692 uint16_t sel;
693 uint32_t offset;
694 } farptr;
695 } val;
696
697 uint8_t type;
698 uint8_t size;
699 uint8_t flags;
700} DISQPVPARAMVAL;
701/** Pointer to opcode parameter value. */
702typedef DISQPVPARAMVAL *PDISQPVPARAMVAL;
703
704/** Indicates which parameter DISQueryParamVal should operate on. */
705typedef enum DISQPVWHICH
706{
707 DISQPVWHICH_DST = 1,
708 DISQPVWHICH_SRC,
709 DISQPVWHAT_32_BIT_HACK = 0x7fffffff
710} DISQPVWHICH;
711DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype);
712DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
713
714DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
715DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
716DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
717DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
718DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal);
719DISDECL(int) DISFetchRegSegEx(PCPUMCTXCORE pCtx, DISSELREG sel, PCPUMSELREG *ppSelReg);
720DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
721DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
722DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
723DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
724DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val);
725DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
726DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
727DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
728DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
729
730
731/**
732 * Try resolve an address into a symbol name.
733 *
734 * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
735 *
736 * @returns VBox status code.
737 * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
738 * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
739 * content of pszBuf is truncated and zero terminated.
740 * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
741 *
742 * @param pDis Pointer to the disassembler CPU state.
743 * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
744 * DIS_FMT_SEL_GET_REG to access this.
745 * @param uAddress The segment address.
746 * @param pszBuf Where to store the symbol name
747 * @param cchBuf The size of the buffer.
748 * @param poff If not a perfect match, then this is where the offset from the return
749 * symbol to the specified address is returned.
750 * @param pvUser The user argument.
751 */
752typedef DECLCALLBACK(int) FNDISGETSYMBOL(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser);
753/** Pointer to a FNDISGETSYMBOL(). */
754typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
755
756/**
757 * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
758 */
759#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
760
761/**
762 * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
763 * @returns Selector value.
764 */
765#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
766
767/**
768 * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
769 * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
770 */
771#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
772
773/** @internal */
774#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
775/** @internal */
776#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
777
778
779/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
780 * @{
781 */
782/** Put the address to the right. */
783#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
784/** Put the address to the left. */
785#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
786/** Put the address in comments.
787 * For some assemblers this implies placing it to the right. */
788#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
789/** Put the instruction bytes to the right of the disassembly. */
790#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
791/** Put the instruction bytes to the left of the disassembly. */
792#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
793/** Put the instruction bytes in comments.
794 * For some assemblers this implies placing the bytes to the right. */
795#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
796/** Put the bytes in square brackets. */
797#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
798/** Put spaces between the bytes. */
799#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
800/** Display the relative +/- offset of branch instructions that uses relative addresses,
801 * and put the target address in parenthesis. */
802#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(8)
803/** Strict assembly. The assembly should, when ever possible, make the
804 * assembler reproduce the exact same binary. (Refers to the yasm
805 * strict keyword.) */
806#define DIS_FMT_FLAGS_STRICT RT_BIT_32(9)
807/** Checks if the given flags are a valid combination. */
808#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
809 ( !((fFlags) & ~UINT32_C(0x000003ff)) \
810 && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
811 && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
812 || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
813 && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
814 && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
815 || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
816 )
817/** @} */
818
819DISDECL(size_t) DISFormatYasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
820DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
821DISDECL(size_t) DISFormatMasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
822DISDECL(size_t) DISFormatMasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
823DISDECL(size_t) DISFormatGas( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
824DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
825
826/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
827 * reader, memory reader); */
828
829DISDECL(bool) DISFormatYasmIsOddEncoding(PDISSTATE pDis);
830
831
832RT_C_DECLS_END
833
834#endif
835
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette