VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmCore.cpp@ 53131

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

DIS: 6251: Added AVX/VEX 3-byte instructions support.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 103.9 KB
Line 
1/* $Id: DisasmCore.cpp 53131 2014-10-23 17:13:53Z vboxsync $ */
2/** @file
3 * VBox Disassembler - Core Components.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DIS
23#include <VBox/dis.h>
24#include <VBox/disopcode.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/param.h>
29#include <iprt/string.h>
30#include <iprt/stdarg.h>
31#include "DisasmInternal.h"
32
33
34/*******************************************************************************
35* Defined Constants And Macros *
36*******************************************************************************/
37/** This must be less or equal to DISSTATE::abInstr.
38 * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */
39#define DIS_MAX_INSTR_LENGTH 15
40
41/** Whether we can do unaligned access. */
42#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
43# define DIS_HOST_UNALIGNED_ACCESS_OK
44#endif
45
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50/** @name Parsers
51 * @{ */
52static FNDISPARSE ParseIllegal;
53static FNDISPARSE ParseModRM;
54static FNDISPARSE ParseModRM_SizeOnly;
55static FNDISPARSE UseModRM;
56static FNDISPARSE ParseImmByte;
57static FNDISPARSE ParseImmByte_SizeOnly;
58static FNDISPARSE ParseImmByteSX;
59static FNDISPARSE ParseImmByteSX_SizeOnly;
60static FNDISPARSE ParseImmBRel;
61static FNDISPARSE ParseImmBRel_SizeOnly;
62static FNDISPARSE ParseImmUshort;
63static FNDISPARSE ParseImmUshort_SizeOnly;
64static FNDISPARSE ParseImmV;
65static FNDISPARSE ParseImmV_SizeOnly;
66static FNDISPARSE ParseImmVRel;
67static FNDISPARSE ParseImmVRel_SizeOnly;
68static FNDISPARSE ParseImmZ;
69static FNDISPARSE ParseImmZ_SizeOnly;
70
71static FNDISPARSE ParseImmAddr;
72static FNDISPARSE ParseImmAddr_SizeOnly;
73static FNDISPARSE ParseImmAddrF;
74static FNDISPARSE ParseImmAddrF_SizeOnly;
75static FNDISPARSE ParseFixedReg;
76static FNDISPARSE ParseImmUlong;
77static FNDISPARSE ParseImmUlong_SizeOnly;
78static FNDISPARSE ParseImmQword;
79static FNDISPARSE ParseImmQword_SizeOnly;
80static FNDISPARSE ParseInvOpModRm;
81
82static FNDISPARSE ParseTwoByteEsc;
83static FNDISPARSE ParseThreeByteEsc4;
84static FNDISPARSE ParseThreeByteEsc5;
85static FNDISPARSE ParseImmGrpl;
86static FNDISPARSE ParseShiftGrp2;
87static FNDISPARSE ParseGrp3;
88static FNDISPARSE ParseGrp4;
89static FNDISPARSE ParseGrp5;
90static FNDISPARSE Parse3DNow;
91static FNDISPARSE ParseGrp6;
92static FNDISPARSE ParseGrp7;
93static FNDISPARSE ParseGrp8;
94static FNDISPARSE ParseGrp9;
95static FNDISPARSE ParseGrp10;
96static FNDISPARSE ParseGrp12;
97static FNDISPARSE ParseGrp13;
98static FNDISPARSE ParseGrp14;
99static FNDISPARSE ParseGrp15;
100static FNDISPARSE ParseGrp16;
101static FNDISPARSE ParseModFence;
102static FNDISPARSE ParseNopPause;
103static FNDISPARSE ParseVex2b;
104static FNDISPARSE ParseVex3b;
105static FNDISPARSE ParseVexDest;
106
107static FNDISPARSE ParseYv;
108static FNDISPARSE ParseYb;
109static FNDISPARSE ParseXv;
110static FNDISPARSE ParseXb;
111
112/** Floating point parsing */
113static FNDISPARSE ParseEscFP;
114/** @} */
115
116
117/*******************************************************************************
118* Global Variables *
119*******************************************************************************/
120/** Parser opcode table for full disassembly. */
121static PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
122{
123 ParseIllegal,
124 ParseModRM,
125 UseModRM,
126 ParseImmByte,
127 ParseImmBRel,
128 ParseImmUshort,
129 ParseImmV,
130 ParseImmVRel,
131 ParseImmAddr,
132 ParseFixedReg,
133 ParseImmUlong,
134 ParseImmQword,
135 ParseTwoByteEsc,
136 ParseImmGrpl,
137 ParseShiftGrp2,
138 ParseGrp3,
139 ParseGrp4,
140 ParseGrp5,
141 Parse3DNow,
142 ParseGrp6,
143 ParseGrp7,
144 ParseGrp8,
145 ParseGrp9,
146 ParseGrp10,
147 ParseGrp12,
148 ParseGrp13,
149 ParseGrp14,
150 ParseGrp15,
151 ParseGrp16,
152 ParseModFence,
153 ParseYv,
154 ParseYb,
155 ParseXv,
156 ParseXb,
157 ParseEscFP,
158 ParseNopPause,
159 ParseImmByteSX,
160 ParseImmZ,
161 ParseThreeByteEsc4,
162 ParseThreeByteEsc5,
163 ParseImmAddrF,
164 ParseInvOpModRm,
165 ParseVex2b,
166 ParseVex3b,
167 ParseVexDest
168};
169
170/** Parser opcode table for only calculating instruction size. */
171static PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
172{
173 ParseIllegal,
174 ParseModRM_SizeOnly,
175 UseModRM,
176 ParseImmByte_SizeOnly,
177 ParseImmBRel_SizeOnly,
178 ParseImmUshort_SizeOnly,
179 ParseImmV_SizeOnly,
180 ParseImmVRel_SizeOnly,
181 ParseImmAddr_SizeOnly,
182 ParseFixedReg,
183 ParseImmUlong_SizeOnly,
184 ParseImmQword_SizeOnly,
185 ParseTwoByteEsc,
186 ParseImmGrpl,
187 ParseShiftGrp2,
188 ParseGrp3,
189 ParseGrp4,
190 ParseGrp5,
191 Parse3DNow,
192 ParseGrp6,
193 ParseGrp7,
194 ParseGrp8,
195 ParseGrp9,
196 ParseGrp10,
197 ParseGrp12,
198 ParseGrp13,
199 ParseGrp14,
200 ParseGrp15,
201 ParseGrp16,
202 ParseModFence,
203 ParseYv,
204 ParseYb,
205 ParseXv,
206 ParseXb,
207 ParseEscFP,
208 ParseNopPause,
209 ParseImmByteSX_SizeOnly,
210 ParseImmZ_SizeOnly,
211 ParseThreeByteEsc4,
212 ParseThreeByteEsc5,
213 ParseImmAddrF_SizeOnly,
214 ParseInvOpModRm,
215 ParseVex2b,
216 ParseVex3b,
217 ParseVexDest
218};
219
220
221
222
223
224/********************************************************************************************************************************
225 *
226 *
227 * Read functions for getting the opcode bytes
228 *
229 *
230 ********************************************************************************************************************************/
231
232/**
233 * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}
234 */
235static DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
236{
237#ifdef IN_RING0
238 NOREF(cbMinRead);
239 AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));
240 RT_BZERO(&pDis->abInstr[offInstr], cbMaxRead);
241 pDis->cbCachedInstr = offInstr + cbMaxRead;
242 return VERR_DIS_NO_READ_CALLBACK;
243#else
244 uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr;
245 size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
246 uint8_t cbToRead = cbLeftOnPage >= cbMaxRead
247 ? cbMaxRead
248 : cbLeftOnPage <= cbMinRead
249 ? cbMinRead
250 : (uint8_t)cbLeftOnPage;
251 memcpy(&pDis->abInstr[offInstr], pbSrc, cbToRead);
252 pDis->cbCachedInstr = offInstr + cbToRead;
253 return VINF_SUCCESS;
254#endif
255}
256
257
258/**
259 * Read more bytes into the DISSTATE::abInstr buffer, advance
260 * DISSTATE::cbCachedInstr.
261 *
262 * Will set DISSTATE::rc on failure, but still advance cbCachedInstr.
263 *
264 * The caller shall fend off reads beyond the DISSTATE::abInstr buffer.
265 *
266 * @param pDis The disassembler state.
267 * @param offInstr The offset of the read request.
268 * @param cbMin The size of the read request that needs to be
269 * satisfied.
270 */
271DECL_NO_INLINE(static, void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin)
272{
273 Assert(cbMin + offInstr <= sizeof(pDis->abInstr));
274
275 /*
276 * Adjust the incoming request to not overlap with bytes that has already
277 * been read and to make sure we don't leave unread gaps.
278 */
279 if (offInstr < pDis->cbCachedInstr)
280 {
281 Assert(offInstr + cbMin > pDis->cbCachedInstr);
282 cbMin -= pDis->cbCachedInstr - offInstr;
283 offInstr = pDis->cbCachedInstr;
284 }
285 else if (offInstr > pDis->cbCachedInstr)
286 {
287 cbMin += offInstr - pDis->cbCachedInstr;
288 offInstr = pDis->cbCachedInstr;
289 }
290
291 /*
292 * Do the read.
293 * (No need to zero anything on failure as abInstr is already zeroed by the
294 * DISInstrEx API.)
295 */
296 int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
297 if (RT_SUCCESS(rc))
298 {
299 Assert(pDis->cbCachedInstr >= offInstr + cbMin);
300 Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
301 }
302 else
303 {
304 Log(("disReadMore failed with rc=%Rrc!!\n", rc));
305 pDis->rc = rc;
306 }
307}
308
309
310/**
311 * Function for handling a 8-bit cache miss.
312 *
313 * @returns The requested byte.
314 * @param pDis The disassembler state.
315 * @param offInstr The offset of the byte relative to the
316 * instruction.
317 */
318DECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
319{
320 if (RT_UNLIKELY(offInstr >= DIS_MAX_INSTR_LENGTH))
321 {
322 Log(("disReadByte: too long instruction...\n"));
323 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
324 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
325 if (cbLeft > 0)
326 return pDis->abInstr[offInstr];
327 return 0;
328 }
329
330 disReadMore(pDis, (uint8_t)offInstr, 1);
331 return pDis->abInstr[offInstr];
332}
333
334
335/**
336 * Read a byte (8-bit) instruction.
337 *
338 * @returns The requested byte.
339 * @param pDis The disassembler state.
340 * @param uAddress The address.
341 */
342DECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
343{
344 if (RT_UNLIKELY(offInstr >= pDis->cbCachedInstr))
345 return disReadByteSlow(pDis, offInstr);
346
347 return pDis->abInstr[offInstr];
348}
349
350
351/**
352 * Function for handling a 16-bit cache miss.
353 *
354 * @returns The requested word.
355 * @param pDis The disassembler state.
356 * @param offInstr The offset of the word relative to the
357 * instruction.
358 */
359DECL_NO_INLINE(static, uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr)
360{
361 if (RT_UNLIKELY(offInstr + 2 > DIS_MAX_INSTR_LENGTH))
362 {
363 Log(("disReadWord: too long instruction...\n"));
364 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
365 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
366 switch (cbLeft)
367 {
368 case 1:
369 return pDis->abInstr[offInstr];
370 default:
371 if (cbLeft >= 2)
372 return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
373 return 0;
374 }
375 }
376
377 disReadMore(pDis, (uint8_t)offInstr, 2);
378#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
379 return *(uint16_t const *)&pDis->abInstr[offInstr];
380#else
381 return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
382#endif
383}
384
385
386/**
387 * Read a word (16-bit) instruction.
388 *
389 * @returns The requested word.
390 * @param pDis The disassembler state.
391 * @param offInstr The offset of the qword relative to the
392 * instruction.
393 */
394DECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
395{
396 if (RT_UNLIKELY(offInstr + 2 > pDis->cbCachedInstr))
397 return disReadWordSlow(pDis, offInstr);
398
399#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
400 return *(uint16_t const *)&pDis->abInstr[offInstr];
401#else
402 return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
403#endif
404}
405
406
407/**
408 * Function for handling a 32-bit cache miss.
409 *
410 * @returns The requested dword.
411 * @param pDis The disassembler state.
412 * @param offInstr The offset of the dword relative to the
413 * instruction.
414 */
415DECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
416{
417 if (RT_UNLIKELY(offInstr + 4 > DIS_MAX_INSTR_LENGTH))
418 {
419 Log(("disReadDWord: too long instruction...\n"));
420 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
421 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
422 switch (cbLeft)
423 {
424 case 1:
425 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
426 case 2:
427 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
428 case 3:
429 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
430 default:
431 if (cbLeft >= 4)
432 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
433 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
434 return 0;
435 }
436 }
437
438 disReadMore(pDis, (uint8_t)offInstr, 4);
439#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
440 return *(uint32_t const *)&pDis->abInstr[offInstr];
441#else
442 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
443 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
444#endif
445}
446
447
448/**
449 * Read a dword (32-bit) instruction.
450 *
451 * @returns The requested dword.
452 * @param pDis The disassembler state.
453 * @param offInstr The offset of the qword relative to the
454 * instruction.
455 */
456DECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
457{
458 if (RT_UNLIKELY(offInstr + 4 > pDis->cbCachedInstr))
459 return disReadDWordSlow(pDis, offInstr);
460
461#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
462 return *(uint32_t const *)&pDis->abInstr[offInstr];
463#else
464 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
465 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
466#endif
467}
468
469
470/**
471 * Function for handling a 64-bit cache miss.
472 *
473 * @returns The requested qword.
474 * @param pDis The disassembler state.
475 * @param offInstr The offset of the qword relative to the
476 * instruction.
477 */
478DECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
479{
480 if (RT_UNLIKELY(offInstr + 8 > DIS_MAX_INSTR_LENGTH))
481 {
482 Log(("disReadQWord: too long instruction...\n"));
483 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
484 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
485 switch (cbLeft)
486 {
487 case 1:
488 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
489 case 2:
490 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
491 case 3:
492 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
493 pDis->abInstr[offInstr + 2], 0, 0, 0, 0, 0);
494 case 4:
495 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
496 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
497 0, 0, 0, 0);
498 case 5:
499 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
500 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
501 pDis->abInstr[offInstr + 4], 0, 0, 0);
502 case 6:
503 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
504 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
505 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
506 0, 0);
507 case 7:
508 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
509 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
510 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
511 pDis->abInstr[offInstr + 6], 0);
512 default:
513 if (cbLeft >= 8)
514 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
515 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
516 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
517 pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
518 return 0;
519 }
520 }
521
522 disReadMore(pDis, (uint8_t)offInstr, 8);
523#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
524 return *(uint64_t const *)&pDis->abInstr[offInstr];
525#else
526 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
527 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
528 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
529 pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
530#endif
531}
532
533
534/**
535 * Read a qword (64-bit) instruction.
536 *
537 * @returns The requested qword.
538 * @param pDis The disassembler state.
539 * @param uAddress The address.
540 */
541DECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
542{
543 if (RT_UNLIKELY(offInstr + 8 > pDis->cbCachedInstr))
544 return disReadQWordSlow(pDis, offInstr);
545
546#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
547 return *(uint64_t const *)&pDis->abInstr[offInstr];
548#else
549 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
550 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
551 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
552 pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
553#endif
554}
555
556
557
558//*****************************************************************************
559//*****************************************************************************
560static size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
561{
562 Assert(pOp); Assert(pDis);
563
564 // Store the opcode format string for disasmPrintf
565 pDis->pCurInstr = pOp;
566
567 /*
568 * Apply filter to instruction type to determine if a full disassembly is required.
569 * Note! Multibyte opcodes are always marked harmless until the final byte.
570 */
571 bool fFiltered;
572 if ((pOp->fOpType & pDis->fFilter) == 0)
573 {
574 fFiltered = true;
575 pDis->pfnDisasmFnTable = g_apfnCalcSize;
576 }
577 else
578 {
579 /* Not filtered out -> full disassembly */
580 fFiltered = false;
581 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
582 }
583
584 // Should contain the parameter type on input
585 pDis->Param1.fParam = pOp->fParam1;
586 pDis->Param2.fParam = pOp->fParam2;
587 pDis->Param3.fParam = pOp->fParam3;
588 pDis->Param4.fParam = pOp->fParam4;
589
590 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
591 if (pDis->uCpuMode == DISCPUMODE_64BIT)
592 {
593 if (pOp->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
594 pDis->uOpMode = DISCPUMODE_64BIT;
595 else
596 if ( (pOp->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
597 && !(pDis->fPrefix & DISPREFIX_OPSIZE))
598 pDis->uOpMode = DISCPUMODE_64BIT;
599 }
600 else
601 if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
602 {
603 /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
604 Assert(pDis->uCpuMode != DISCPUMODE_64BIT);
605 pDis->uOpMode = DISCPUMODE_32BIT;
606 }
607
608 if (pOp->idxParse1 != IDX_ParseNop)
609 {
610 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
611 if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
612 }
613
614 if (pOp->idxParse2 != IDX_ParseNop)
615 {
616 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
617 if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
618 }
619
620 if (pOp->idxParse3 != IDX_ParseNop)
621 {
622 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
623 if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
624 }
625
626 if (pOp->idxParse4 != IDX_ParseNop)
627 {
628 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse4](offInstr, pOp, pDis, &pDis->Param4);
629 if (fFiltered == false) pDis->Param4.cb = DISGetParamSize(pDis, &pDis->Param4);
630 }
631 // else simple one byte instruction
632
633 return offInstr;
634}
635//*****************************************************************************
636/* Floating point opcode parsing */
637//*****************************************************************************
638static size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
639{
640 PCDISOPCODE fpop;
641 NOREF(pOp);
642
643 uint8_t ModRM = disReadByte(pDis, offInstr);
644 uint8_t index = pDis->bOpCode - 0xD8;
645 if (ModRM <= 0xBF)
646 {
647 fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
648 pDis->pCurInstr = fpop;
649
650 // Should contain the parameter type on input
651 pDis->Param1.fParam = fpop->fParam1;
652 pDis->Param2.fParam = fpop->fParam2;
653 }
654 else
655 {
656 fpop = &(g_apMapX86_FP_High[index])[ModRM - 0xC0];
657 pDis->pCurInstr = fpop;
658 }
659
660 /*
661 * Apply filter to instruction type to determine if a full disassembly is required.
662 * @note Multibyte opcodes are always marked harmless until the final byte.
663 */
664 if ((fpop->fOpType & pDis->fFilter) == 0)
665 pDis->pfnDisasmFnTable = g_apfnCalcSize;
666 else
667 /* Not filtered out -> full disassembly */
668 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
669
670 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
671 if (pDis->uCpuMode == DISCPUMODE_64BIT)
672 {
673 /* Note: redundant, but just in case this ever changes */
674 if (fpop->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
675 pDis->uOpMode = DISCPUMODE_64BIT;
676 else
677 if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
678 && !(pDis->fPrefix & DISPREFIX_OPSIZE))
679 pDis->uOpMode = DISCPUMODE_64BIT;
680 }
681
682 // Little hack to make sure the ModRM byte is included in the returned size
683 if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
684 offInstr++; //ModRM byte
685
686 if (fpop->idxParse1 != IDX_ParseNop)
687 offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
688
689 if (fpop->idxParse2 != IDX_ParseNop)
690 offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
691
692 return offInstr;
693}
694
695
696/********************************************************************************************************************************
697 *
698 *
699 * SIB byte: (not 16-bit mode)
700 * 7 - 6 5 - 3 2-0
701 * Scale Index Base
702 *
703 *
704 ********************************************************************************************************************************/
705static void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
706{
707 unsigned scale = pDis->SIB.Bits.Scale;
708 unsigned base = pDis->SIB.Bits.Base;
709 unsigned index = pDis->SIB.Bits.Index;
710
711 unsigned regtype;
712 if (pDis->uAddrMode == DISCPUMODE_32BIT)
713 regtype = DISUSE_REG_GEN32;
714 else
715 regtype = DISUSE_REG_GEN64;
716
717 if (index != 4)
718 {
719 pParam->fUse |= DISUSE_INDEX | regtype;
720 pParam->Index.idxGenReg = index;
721
722 if (scale != 0)
723 {
724 pParam->fUse |= DISUSE_SCALE;
725 pParam->uScale = (1<<scale);
726 }
727 }
728
729 if (base == 5 && pDis->ModRM.Bits.Mod == 0)
730 {
731 // [scaled index] + disp32
732 if (pDis->uAddrMode == DISCPUMODE_32BIT)
733 {
734 pParam->fUse |= DISUSE_DISPLACEMENT32;
735 pParam->uDisp.i32 = pDis->i32SibDisp;
736 }
737 else
738 { /* sign-extend to 64 bits */
739 pParam->fUse |= DISUSE_DISPLACEMENT64;
740 pParam->uDisp.i64 = pDis->i32SibDisp;
741 }
742 }
743 else
744 {
745 pParam->fUse |= DISUSE_BASE | regtype;
746 pParam->Base.idxGenReg = base;
747 }
748 return; /* Already fetched everything in ParseSIB; no size returned */
749}
750
751
752static size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
753{
754 NOREF(pOp); NOREF(pParam);
755
756 uint8_t SIB = disReadByte(pDis, offInstr);
757 offInstr++;
758
759 pDis->SIB.Bits.Base = SIB_BASE(SIB);
760 pDis->SIB.Bits.Index = SIB_INDEX(SIB);
761 pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
762
763 if (pDis->fPrefix & DISPREFIX_REX)
764 {
765 /* REX.B extends the Base field if not scaled index + disp32 */
766 if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
767 pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
768
769 pDis->SIB.Bits.Index |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3;
770 }
771
772 if ( pDis->SIB.Bits.Base == 5
773 && pDis->ModRM.Bits.Mod == 0)
774 {
775 /* Additional 32 bits displacement. No change in long mode. */
776 pDis->i32SibDisp = disReadDWord(pDis, offInstr);
777 offInstr += 4;
778 }
779 return offInstr;
780}
781
782
783static size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
784{
785 NOREF(pOp); NOREF(pParam);
786
787 uint8_t SIB = disReadByte(pDis, offInstr);
788 offInstr++;
789
790 pDis->SIB.Bits.Base = SIB_BASE(SIB);
791 pDis->SIB.Bits.Index = SIB_INDEX(SIB);
792 pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
793
794 if (pDis->fPrefix & DISPREFIX_REX)
795 {
796 /* REX.B extends the Base field. */
797 pDis->SIB.Bits.Base |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
798 /* REX.X extends the Index field. */
799 pDis->SIB.Bits.Index |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
800 }
801
802 if ( pDis->SIB.Bits.Base == 5
803 && pDis->ModRM.Bits.Mod == 0)
804 {
805 /* Additional 32 bits displacement. No change in long mode. */
806 offInstr += 4;
807 }
808 return offInstr;
809}
810
811
812
813/********************************************************************************************************************************
814 *
815 *
816 * ModR/M byte:
817 * 7 - 6 5 - 3 2-0
818 * Mod Reg/Opcode R/M
819 *
820 *
821 ********************************************************************************************************************************/
822static void disasmModRMReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, int fRegAddr)
823{
824 NOREF(pOp); NOREF(pDis);
825
826 unsigned type = OP_PARM_VTYPE(pParam->fParam);
827 unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
828 if (fRegAddr)
829 subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
830 else
831 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE || subtype == OP_PARM_y)
832 {
833 switch (pDis->uOpMode)
834 {
835 case DISCPUMODE_32BIT:
836 subtype = OP_PARM_d;
837 break;
838 case DISCPUMODE_64BIT:
839 subtype = OP_PARM_q;
840 break;
841 case DISCPUMODE_16BIT:
842 if (subtype != OP_PARM_y)
843 subtype = OP_PARM_w;
844 break;
845 default:
846 /* make gcc happy */
847 break;
848 }
849 }
850
851 switch (subtype)
852 {
853 case OP_PARM_b:
854 Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
855
856 /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
857 /* Intel® 64 and IA-32 Architectures Software Developer’s Manual: 3.4.1.1 */
858 if ( (pDis->fPrefix & DISPREFIX_REX)
859 && idx >= DISGREG_AH
860 && idx <= DISGREG_BH)
861 {
862 idx += (DISGREG_SPL - DISGREG_AH);
863 }
864
865 pParam->fUse |= DISUSE_REG_GEN8;
866 pParam->Base.idxGenReg = idx;
867 break;
868
869 case OP_PARM_w:
870 Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
871
872 pParam->fUse |= DISUSE_REG_GEN16;
873 pParam->Base.idxGenReg = idx;
874 break;
875
876 case OP_PARM_d:
877 Assert(idx < (pDis->fPrefix & DISPREFIX_REX ? 16U : 8U));
878
879 pParam->fUse |= DISUSE_REG_GEN32;
880 pParam->Base.idxGenReg = idx;
881 break;
882
883 case OP_PARM_q:
884 pParam->fUse |= DISUSE_REG_GEN64;
885 pParam->Base.idxGenReg = idx;
886 break;
887
888 default:
889 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
890 pDis->rc = VERR_DIS_INVALID_MODRM;
891 break;
892 }
893}
894
895
896static void disasmModRMReg16(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
897{
898 static const uint8_t s_auBaseModRMReg16[8] =
899 { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX };
900
901 NOREF(pDis); NOREF(pOp);
902 pParam->fUse |= DISUSE_REG_GEN16;
903 pParam->Base.idxGenReg = s_auBaseModRMReg16[idx];
904 if (idx < 4)
905 {
906 static const uint8_t s_auIndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI };
907 pParam->fUse |= DISUSE_INDEX;
908 pParam->Index.idxGenReg = s_auIndexModRMReg16[idx];
909 }
910}
911
912
913static void disasmModRMSReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
914{
915 NOREF(pOp);
916 if (idx >= DISSELREG_END)
917 {
918 Log(("disasmModRMSReg %d failed!!\n", idx));
919 pDis->rc = VERR_DIS_INVALID_PARAMETER;
920 return;
921 }
922
923 pParam->fUse |= DISUSE_REG_SEG;
924 pParam->Base.idxSegReg = (DISSELREG)idx;
925}
926
927
928static size_t UseModRM(size_t const offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
929{
930 unsigned vtype = OP_PARM_VTYPE(pParam->fParam);
931 uint8_t reg = pDis->ModRM.Bits.Reg;
932 uint8_t mod = pDis->ModRM.Bits.Mod;
933 uint8_t rm = pDis->ModRM.Bits.Rm;
934
935 switch (vtype)
936 {
937 case OP_PARM_G: //general purpose register
938 disasmModRMReg(reg, pOp, pDis, pParam, 0);
939 return offInstr;
940
941 default:
942 if (IS_OP_PARM_RARE(vtype))
943 {
944 switch (vtype)
945 {
946 case OP_PARM_C: //control register
947 pParam->fUse |= DISUSE_REG_CR;
948
949 if ( pDis->pCurInstr->uOpcode == OP_MOV_CR
950 && pDis->uOpMode == DISCPUMODE_32BIT
951 && (pDis->fPrefix & DISPREFIX_LOCK))
952 {
953 pDis->fPrefix &= ~DISPREFIX_LOCK;
954 pParam->Base.idxCtrlReg = DISCREG_CR8;
955 }
956 else
957 pParam->Base.idxCtrlReg = reg;
958 return offInstr;
959
960 case OP_PARM_D: //debug register
961 pParam->fUse |= DISUSE_REG_DBG;
962 pParam->Base.idxDbgReg = reg;
963 return offInstr;
964
965 case OP_PARM_Q: //MMX or memory operand
966 if (mod != 3)
967 break; /* memory operand */
968 reg = rm; /* the RM field specifies the xmm register */
969 /* else no break */
970
971 case OP_PARM_P: //MMX register
972 reg &= 7; /* REX.R has no effect here */
973 pParam->fUse |= DISUSE_REG_MMX;
974 pParam->Base.idxMmxReg = reg;
975 return offInstr;
976
977 case OP_PARM_S: //segment register
978 reg &= 7; /* REX.R has no effect here */
979 disasmModRMSReg(reg, pOp, pDis, pParam);
980 pParam->fUse |= DISUSE_REG_SEG;
981 return offInstr;
982
983 case OP_PARM_T: //test register
984 reg &= 7; /* REX.R has no effect here */
985 pParam->fUse |= DISUSE_REG_TEST;
986 pParam->Base.idxTestReg = reg;
987 return offInstr;
988
989 case OP_PARM_W: //XMM register or memory operand
990 if (mod != 3)
991 break; /* memory operand */
992 case OP_PARM_U: // XMM/YMM register
993 reg = rm; /* the RM field specifies the xmm register */
994 /* else no break */
995
996 case OP_PARM_V: //XMM register
997 if (VEXREG_IS256B(pDis->bVexDestReg)
998 && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_dq
999 && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_q
1000 && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_d
1001 && OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_w)
1002 {
1003 // Use YMM register if VEX.L is set.
1004 pParam->fUse |= DISUSE_REG_YMM;
1005 pParam->Base.idxYmmReg = reg;
1006 }
1007 else
1008 {
1009 pParam->fUse |= DISUSE_REG_XMM;
1010 pParam->Base.idxXmmReg = reg;
1011 }
1012 return offInstr;
1013 }
1014 }
1015 }
1016
1017 /** @todo bound */
1018
1019 if (pDis->uAddrMode != DISCPUMODE_16BIT)
1020 {
1021 Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
1022
1023 /*
1024 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
1025 */
1026 switch (mod)
1027 {
1028 case 0: //effective address
1029 if (rm == 4) /* SIB byte follows ModRM */
1030 UseSIB(pDis, pParam);
1031 else
1032 if (rm == 5)
1033 {
1034 /* 32 bits displacement */
1035 if (pDis->uCpuMode != DISCPUMODE_64BIT)
1036 {
1037 pParam->fUse |= DISUSE_DISPLACEMENT32;
1038 pParam->uDisp.i32 = pDis->i32SibDisp;
1039 }
1040 else
1041 {
1042 pParam->fUse |= DISUSE_RIPDISPLACEMENT32;
1043 pParam->uDisp.i32 = pDis->i32SibDisp;
1044 }
1045 }
1046 else
1047 { //register address
1048 pParam->fUse |= DISUSE_BASE;
1049 disasmModRMReg(rm, pOp, pDis, pParam, 1);
1050 }
1051 break;
1052
1053 case 1: //effective address + 8 bits displacement
1054 if (rm == 4) /* SIB byte follows ModRM */
1055 UseSIB(pDis, pParam);
1056 else
1057 {
1058 pParam->fUse |= DISUSE_BASE;
1059 disasmModRMReg(rm, pOp, pDis, pParam, 1);
1060 }
1061 pParam->uDisp.i8 = pDis->i32SibDisp;
1062 pParam->fUse |= DISUSE_DISPLACEMENT8;
1063 break;
1064
1065 case 2: //effective address + 32 bits displacement
1066 if (rm == 4) /* SIB byte follows ModRM */
1067 UseSIB(pDis, pParam);
1068 else
1069 {
1070 pParam->fUse |= DISUSE_BASE;
1071 disasmModRMReg(rm, pOp, pDis, pParam, 1);
1072 }
1073 pParam->uDisp.i32 = pDis->i32SibDisp;
1074 pParam->fUse |= DISUSE_DISPLACEMENT32;
1075 break;
1076
1077 case 3: //registers
1078 disasmModRMReg(rm, pOp, pDis, pParam, 0);
1079 break;
1080 }
1081 }
1082 else
1083 {//16 bits addressing mode
1084 switch (mod)
1085 {
1086 case 0: //effective address
1087 if (rm == 6)
1088 {//16 bits displacement
1089 pParam->uDisp.i16 = pDis->i32SibDisp;
1090 pParam->fUse |= DISUSE_DISPLACEMENT16;
1091 }
1092 else
1093 {
1094 pParam->fUse |= DISUSE_BASE;
1095 disasmModRMReg16(rm, pOp, pDis, pParam);
1096 }
1097 break;
1098
1099 case 1: //effective address + 8 bits displacement
1100 disasmModRMReg16(rm, pOp, pDis, pParam);
1101 pParam->uDisp.i8 = pDis->i32SibDisp;
1102 pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT8;
1103 break;
1104
1105 case 2: //effective address + 16 bits displacement
1106 disasmModRMReg16(rm, pOp, pDis, pParam);
1107 pParam->uDisp.i16 = pDis->i32SibDisp;
1108 pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT16;
1109 break;
1110
1111 case 3: //registers
1112 disasmModRMReg(rm, pOp, pDis, pParam, 0);
1113 break;
1114 }
1115 }
1116 return offInstr;
1117}
1118//*****************************************************************************
1119// Query the size of the ModRM parameters and fetch the immediate data (if any)
1120//*****************************************************************************
1121static size_t QueryModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1122{
1123 uint8_t mod = pDis->ModRM.Bits.Mod;
1124 uint8_t rm = pDis->ModRM.Bits.Rm;
1125
1126 if (pDis->uAddrMode != DISCPUMODE_16BIT)
1127 {
1128 Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
1129
1130 /*
1131 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
1132 */
1133 if (mod != 3 && rm == 4) /* SIB byte follows ModRM */
1134 offInstr = ParseSIB(offInstr, pOp, pDis, pParam);
1135
1136 switch (mod)
1137 {
1138 case 0: /* Effective address */
1139 if (rm == 5) /* 32 bits displacement */
1140 {
1141 pDis->i32SibDisp = disReadDWord(pDis, offInstr);
1142 offInstr += 4;
1143 }
1144 /* else register address */
1145 break;
1146
1147 case 1: /* Effective address + 8 bits displacement */
1148 pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
1149 offInstr++;
1150 break;
1151
1152 case 2: /* Effective address + 32 bits displacement */
1153 pDis->i32SibDisp = disReadDWord(pDis, offInstr);
1154 offInstr += 4;
1155 break;
1156
1157 case 3: /* registers */
1158 break;
1159 }
1160 }
1161 else
1162 {
1163 /* 16 bits mode */
1164 switch (mod)
1165 {
1166 case 0: /* Effective address */
1167 if (rm == 6)
1168 {
1169 pDis->i32SibDisp = disReadWord(pDis, offInstr);
1170 offInstr += 2;
1171 }
1172 /* else register address */
1173 break;
1174
1175 case 1: /* Effective address + 8 bits displacement */
1176 pDis->i32SibDisp = (int8_t)disReadByte(pDis, offInstr);
1177 offInstr++;
1178 break;
1179
1180 case 2: /* Effective address + 32 bits displacement */
1181 pDis->i32SibDisp = (int16_t)disReadWord(pDis, offInstr);
1182 offInstr += 2;
1183 break;
1184
1185 case 3: /* registers */
1186 break;
1187 }
1188 }
1189 return offInstr;
1190}
1191//*****************************************************************************
1192// Parse the ModRM parameters and fetch the immediate data (if any)
1193//*****************************************************************************
1194static size_t QueryModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1195{
1196 uint8_t mod = pDis->ModRM.Bits.Mod;
1197 uint8_t rm = pDis->ModRM.Bits.Rm;
1198
1199 if (pDis->uAddrMode != DISCPUMODE_16BIT)
1200 {
1201 Assert(pDis->uAddrMode == DISCPUMODE_32BIT || pDis->uAddrMode == DISCPUMODE_64BIT);
1202 /*
1203 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
1204 */
1205 if (mod != 3 && rm == 4)
1206 { /* SIB byte follows ModRM */
1207 offInstr = ParseSIB_SizeOnly(offInstr, pOp, pDis, pParam);
1208 }
1209
1210 switch (mod)
1211 {
1212 case 0: //effective address
1213 if (rm == 5) /* 32 bits displacement */
1214 offInstr += 4;
1215 /* else register address */
1216 break;
1217
1218 case 1: /* Effective address + 8 bits displacement */
1219 offInstr += 1;
1220 break;
1221
1222 case 2: /* Effective address + 32 bits displacement */
1223 offInstr += 4;
1224 break;
1225
1226 case 3: /* registers */
1227 break;
1228 }
1229 }
1230 else
1231 {
1232 /* 16 bits mode */
1233 switch (mod)
1234 {
1235 case 0: //effective address
1236 if (rm == 6)
1237 offInstr += 2;
1238 /* else register address */
1239 break;
1240
1241 case 1: /* Effective address + 8 bits displacement */
1242 offInstr++;
1243 break;
1244
1245 case 2: /* Effective address + 32 bits displacement */
1246 offInstr += 2;
1247 break;
1248
1249 case 3: /* registers */
1250 break;
1251 }
1252 }
1253 return offInstr;
1254}
1255//*****************************************************************************
1256//*****************************************************************************
1257static size_t ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1258{
1259 NOREF(pOp); NOREF(pParam); NOREF(pDis);
1260 AssertFailed();
1261 return offInstr;
1262}
1263//*****************************************************************************
1264//*****************************************************************************
1265static size_t ParseModRM(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1266{
1267 uint8_t ModRM = disReadByte(pDis, offInstr);
1268 offInstr++;
1269
1270 pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
1271 pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1272 pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
1273
1274 /* Disregard the mod bits for certain instructions (mov crx, mov drx).
1275 *
1276 * From the AMD manual:
1277 * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
1278 * encoding of the MOD field in the MODR/M byte.
1279 */
1280 if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
1281 pDis->ModRM.Bits.Mod = 3;
1282
1283 if (pDis->fPrefix & DISPREFIX_REX)
1284 {
1285 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
1286
1287 /* REX.R extends the Reg field. */
1288 pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
1289
1290 /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
1291 if (!( pDis->ModRM.Bits.Mod != 3
1292 && pDis->ModRM.Bits.Rm == 4)
1293 &&
1294 !( pDis->ModRM.Bits.Mod == 0
1295 && pDis->ModRM.Bits.Rm == 5))
1296 {
1297 pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
1298 }
1299 }
1300 offInstr = QueryModRM(offInstr, pOp, pDis, pParam);
1301
1302 return UseModRM(offInstr, pOp, pDis, pParam);
1303}
1304//*****************************************************************************
1305//*****************************************************************************
1306static size_t ParseModRM_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1307{
1308 uint8_t ModRM = disReadByte(pDis, offInstr);
1309 offInstr++;
1310
1311 pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
1312 pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1313 pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
1314
1315 /* Disregard the mod bits for certain instructions (mov crx, mov drx).
1316 *
1317 * From the AMD manual:
1318 * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
1319 * encoding of the MOD field in the MODR/M byte.
1320 */
1321 if (pOp->fOpType & DISOPTYPE_MOD_FIXED_11)
1322 pDis->ModRM.Bits.Mod = 3;
1323
1324 if (pDis->fPrefix & DISPREFIX_REX)
1325 {
1326 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
1327
1328 /* REX.R extends the Reg field. */
1329 pDis->ModRM.Bits.Reg |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
1330
1331 /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
1332 if (!( pDis->ModRM.Bits.Mod != 3
1333 && pDis->ModRM.Bits.Rm == 4)
1334 &&
1335 !( pDis->ModRM.Bits.Mod == 0
1336 && pDis->ModRM.Bits.Rm == 5))
1337 {
1338 pDis->ModRM.Bits.Rm |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
1339 }
1340 }
1341
1342 offInstr = QueryModRM_SizeOnly(offInstr, pOp, pDis, pParam);
1343
1344 /* UseModRM is not necessary here; we're only interested in the opcode size */
1345 return offInstr;
1346}
1347//*****************************************************************************
1348//*****************************************************************************
1349static size_t ParseModFence(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1350{
1351 NOREF(pOp); NOREF(pParam); NOREF(pDis);
1352 /* Note! Only used in group 15, so we must account for the mod/rm byte. */
1353 return offInstr + 1;
1354}
1355//*****************************************************************************
1356//*****************************************************************************
1357static size_t ParseImmByte(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1358{
1359 NOREF(pOp);
1360 uint8_t byte = disReadByte(pDis, offInstr);
1361 if (pParam->fParam == OP_PARM_Lx)
1362 {
1363 pParam->fUse |= (VEXREG_IS256B(pDis->bVexDestReg) ? DISUSE_REG_YMM : DISUSE_REG_XMM);
1364
1365 // Ignore MSB in 32-bit mode.
1366 if (pDis->uCpuMode == DISCPUMODE_32BIT)
1367 byte &= 0x7f;
1368
1369 pParam->Base.idxXmmReg = byte >> 4;
1370 }
1371 else
1372 {
1373 pParam->uValue = byte;
1374 pParam->fUse |= DISUSE_IMMEDIATE8;
1375 pParam->cb = sizeof(uint8_t);
1376 }
1377 return offInstr + 1;
1378}
1379//*****************************************************************************
1380//*****************************************************************************
1381static size_t ParseImmByte_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1382{
1383 NOREF(pOp); NOREF(pParam); NOREF(pDis);
1384 return offInstr + 1;
1385}
1386//*****************************************************************************
1387//*****************************************************************************
1388static size_t ParseImmByteSX(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1389{
1390 NOREF(pOp);
1391 if (pDis->uOpMode == DISCPUMODE_32BIT)
1392 {
1393 pParam->uValue = (uint32_t)(int8_t)disReadByte(pDis, offInstr);
1394 pParam->fUse |= DISUSE_IMMEDIATE32_SX8;
1395 pParam->cb = sizeof(uint32_t);
1396 }
1397 else
1398 if (pDis->uOpMode == DISCPUMODE_64BIT)
1399 {
1400 pParam->uValue = (uint64_t)(int8_t)disReadByte(pDis, offInstr);
1401 pParam->fUse |= DISUSE_IMMEDIATE64_SX8;
1402 pParam->cb = sizeof(uint64_t);
1403 }
1404 else
1405 {
1406 pParam->uValue = (uint16_t)(int8_t)disReadByte(pDis, offInstr);
1407 pParam->fUse |= DISUSE_IMMEDIATE16_SX8;
1408 pParam->cb = sizeof(uint16_t);
1409 }
1410 return offInstr + 1;
1411}
1412//*****************************************************************************
1413//*****************************************************************************
1414static size_t ParseImmByteSX_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1415{
1416 NOREF(pOp); NOREF(pParam); NOREF(pDis);
1417 return offInstr + 1;
1418}
1419//*****************************************************************************
1420//*****************************************************************************
1421static size_t ParseImmUshort(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1422{
1423 NOREF(pOp);
1424 pParam->uValue = disReadWord(pDis, offInstr);
1425 pParam->fUse |= DISUSE_IMMEDIATE16;
1426 pParam->cb = sizeof(uint16_t);
1427 return offInstr + 2;
1428}
1429//*****************************************************************************
1430//*****************************************************************************
1431static size_t ParseImmUshort_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1432{
1433 NOREF(pOp); NOREF(pParam); NOREF(pDis);
1434 return offInstr + 2;
1435}
1436//*****************************************************************************
1437//*****************************************************************************
1438static size_t ParseImmUlong(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1439{
1440 NOREF(pOp);
1441 pParam->uValue = disReadDWord(pDis, offInstr);
1442 pParam->fUse |= DISUSE_IMMEDIATE32;
1443 pParam->cb = sizeof(uint32_t);
1444 return offInstr + 4;
1445}
1446//*****************************************************************************
1447//*****************************************************************************
1448static size_t ParseImmUlong_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1449{
1450 NOREF(pOp); NOREF(pParam); NOREF(pDis);
1451 return offInstr + 4;
1452}
1453//*****************************************************************************
1454//*****************************************************************************
1455static size_t ParseImmQword(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1456{
1457 NOREF(pOp);
1458 pParam->uValue = disReadQWord(pDis, offInstr);
1459 pParam->fUse |= DISUSE_IMMEDIATE64;
1460 pParam->cb = sizeof(uint64_t);
1461 return offInstr + 8;
1462}
1463//*****************************************************************************
1464//*****************************************************************************
1465static size_t ParseImmQword_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1466{
1467 NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
1468 return offInstr + 8;
1469}
1470//*****************************************************************************
1471//*****************************************************************************
1472static size_t ParseImmV(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1473{
1474 NOREF(pOp);
1475 if (pDis->uOpMode == DISCPUMODE_32BIT)
1476 {
1477 pParam->uValue = disReadDWord(pDis, offInstr);
1478 pParam->fUse |= DISUSE_IMMEDIATE32;
1479 pParam->cb = sizeof(uint32_t);
1480 return offInstr + 4;
1481 }
1482
1483 if (pDis->uOpMode == DISCPUMODE_64BIT)
1484 {
1485 pParam->uValue = disReadQWord(pDis, offInstr);
1486 pParam->fUse |= DISUSE_IMMEDIATE64;
1487 pParam->cb = sizeof(uint64_t);
1488 return offInstr + 8;
1489 }
1490
1491 pParam->uValue = disReadWord(pDis, offInstr);
1492 pParam->fUse |= DISUSE_IMMEDIATE16;
1493 pParam->cb = sizeof(uint16_t);
1494 return offInstr + 2;
1495}
1496//*****************************************************************************
1497//*****************************************************************************
1498static size_t ParseImmV_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1499{
1500 NOREF(offInstr); NOREF(pOp); NOREF(pParam);
1501 if (pDis->uOpMode == DISCPUMODE_32BIT)
1502 return offInstr + 4;
1503 if (pDis->uOpMode == DISCPUMODE_64BIT)
1504 return offInstr + 8;
1505 return offInstr + 2;
1506}
1507//*****************************************************************************
1508//*****************************************************************************
1509static size_t ParseImmZ(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1510{
1511 NOREF(pOp);
1512 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1513 if (pDis->uOpMode == DISCPUMODE_16BIT)
1514 {
1515 pParam->uValue = disReadWord(pDis, offInstr);
1516 pParam->fUse |= DISUSE_IMMEDIATE16;
1517 pParam->cb = sizeof(uint16_t);
1518 return offInstr + 2;
1519 }
1520
1521 /* 64 bits op mode means *sign* extend to 64 bits. */
1522 if (pDis->uOpMode == DISCPUMODE_64BIT)
1523 {
1524 pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
1525 pParam->fUse |= DISUSE_IMMEDIATE64;
1526 pParam->cb = sizeof(uint64_t);
1527 }
1528 else
1529 {
1530 pParam->uValue = disReadDWord(pDis, offInstr);
1531 pParam->fUse |= DISUSE_IMMEDIATE32;
1532 pParam->cb = sizeof(uint32_t);
1533 }
1534 return offInstr + 4;
1535}
1536//*****************************************************************************
1537//*****************************************************************************
1538static size_t ParseImmZ_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1539{
1540 NOREF(offInstr); NOREF(pOp); NOREF(pParam);
1541 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1542 if (pDis->uOpMode == DISCPUMODE_16BIT)
1543 return offInstr + 2;
1544 return offInstr + 4;
1545}
1546
1547//*****************************************************************************
1548// Relative displacement for branches (rel. to next instruction)
1549//*****************************************************************************
1550static size_t ParseImmBRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1551{
1552 NOREF(pOp);
1553 pParam->uValue = disReadByte(pDis, offInstr);
1554 pParam->fUse |= DISUSE_IMMEDIATE8_REL;
1555 pParam->cb = sizeof(uint8_t);
1556 return offInstr + 1;
1557}
1558//*****************************************************************************
1559// Relative displacement for branches (rel. to next instruction)
1560//*****************************************************************************
1561static size_t ParseImmBRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1562{
1563 NOREF(offInstr); NOREF(pOp); NOREF(pParam); NOREF(pDis);
1564 return offInstr + 1;
1565}
1566//*****************************************************************************
1567// Relative displacement for branches (rel. to next instruction)
1568//*****************************************************************************
1569static size_t ParseImmVRel(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1570{
1571 NOREF(pOp);
1572 if (pDis->uOpMode == DISCPUMODE_32BIT)
1573 {
1574 pParam->uValue = disReadDWord(pDis, offInstr);
1575 pParam->fUse |= DISUSE_IMMEDIATE32_REL;
1576 pParam->cb = sizeof(int32_t);
1577 return offInstr + 4;
1578 }
1579
1580 if (pDis->uOpMode == DISCPUMODE_64BIT)
1581 {
1582 /* 32 bits relative immediate sign extended to 64 bits. */
1583 pParam->uValue = (uint64_t)(int32_t)disReadDWord(pDis, offInstr);
1584 pParam->fUse |= DISUSE_IMMEDIATE64_REL;
1585 pParam->cb = sizeof(int64_t);
1586 return offInstr + 4;
1587 }
1588
1589 pParam->uValue = disReadWord(pDis, offInstr);
1590 pParam->fUse |= DISUSE_IMMEDIATE16_REL;
1591 pParam->cb = sizeof(int16_t);
1592 return offInstr + 2;
1593}
1594//*****************************************************************************
1595// Relative displacement for branches (rel. to next instruction)
1596//*****************************************************************************
1597static size_t ParseImmVRel_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1598{
1599 NOREF(offInstr); NOREF(pOp); NOREF(pParam);
1600 if (pDis->uOpMode == DISCPUMODE_16BIT)
1601 return offInstr + 2;
1602 /* Both 32 & 64 bits mode use 32 bits relative immediates. */
1603 return offInstr + 4;
1604}
1605//*****************************************************************************
1606//*****************************************************************************
1607static size_t ParseImmAddr(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1608{
1609 NOREF(pOp);
1610 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1611 {
1612 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1613 {
1614 /* far 16:32 pointer */
1615 pParam->uValue = disReadDWord(pDis, offInstr);
1616 *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
1617 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1618 pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1619 return offInstr + 4 + 2;
1620 }
1621
1622 /*
1623 * near 32 bits pointer
1624 *
1625 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1626 * so we treat it like displacement.
1627 */
1628 pParam->uDisp.i32 = disReadDWord(pDis, offInstr);
1629 pParam->fUse |= DISUSE_DISPLACEMENT32;
1630 pParam->cb = sizeof(uint32_t);
1631 return offInstr + 4;
1632 }
1633
1634 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1635 {
1636 /*
1637 * near 64 bits pointer
1638 *
1639 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1640 * so we treat it like displacement.
1641 */
1642 Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
1643 pParam->uDisp.i64 = disReadQWord(pDis, offInstr);
1644 pParam->fUse |= DISUSE_DISPLACEMENT64;
1645 pParam->cb = sizeof(uint64_t);
1646 return offInstr + 8;
1647 }
1648 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1649 {
1650 /* far 16:16 pointer */
1651 pParam->uValue = disReadDWord(pDis, offInstr);
1652 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1653 pParam->cb = 2*sizeof(uint16_t);
1654 return offInstr + 4;
1655 }
1656
1657 /*
1658 * near 16 bits pointer
1659 *
1660 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1661 * so we treat it like displacement.
1662 */
1663 pParam->uDisp.i16 = disReadWord(pDis, offInstr);
1664 pParam->fUse |= DISUSE_DISPLACEMENT16;
1665 pParam->cb = sizeof(uint16_t);
1666 return offInstr + 2;
1667}
1668//*****************************************************************************
1669//*****************************************************************************
1670static size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1671{
1672 NOREF(offInstr); NOREF(pOp);
1673 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1674 {
1675 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1676 return offInstr + 4 + 2; /* far 16:32 pointer */
1677 return offInstr + 4; /* near 32 bits pointer */
1678 }
1679 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1680 {
1681 Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
1682 return offInstr + 8;
1683 }
1684 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1685 return offInstr + 4; /* far 16:16 pointer */
1686 return offInstr + 2; /* near 16 bits pointer */
1687}
1688//*****************************************************************************
1689//*****************************************************************************
1690static size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1691{
1692 NOREF(pOp);
1693 // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
1694 Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
1695 Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1696 if (pDis->uOpMode == DISCPUMODE_32BIT)
1697 {
1698 // far 16:32 pointer
1699 pParam->uValue = disReadDWord(pDis, offInstr);
1700 *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
1701 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1702 pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1703 return offInstr + 4 + 2;
1704 }
1705
1706 // far 16:16 pointer
1707 pParam->uValue = disReadDWord(pDis, offInstr);
1708 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1709 pParam->cb = 2*sizeof(uint16_t);
1710 return offInstr + 2 + 2;
1711}
1712//*****************************************************************************
1713//*****************************************************************************
1714static size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1715{
1716 NOREF(offInstr); NOREF(pOp);
1717 // immediate far pointers - only 16:16 or 16:32
1718 Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
1719 Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1720 if (pDis->uOpMode == DISCPUMODE_32BIT)
1721 return offInstr + 4 + 2; /* far 16:32 pointer */
1722 return offInstr + 2 + 2; /* far 16:16 pointer */
1723}
1724//*****************************************************************************
1725//*****************************************************************************
1726static size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1727{
1728 NOREF(offInstr);
1729
1730 /*
1731 * Sets up flags for stored in OPC fixed registers.
1732 */
1733
1734 if (pParam->fParam == OP_PARM_NONE)
1735 {
1736 /* No parameter at all. */
1737 return offInstr;
1738 }
1739
1740 AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
1741 AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
1742 AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1743 AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
1744
1745 if (pParam->fParam <= OP_PARM_REG_GEN32_END)
1746 {
1747 /* 32-bit EAX..EDI registers. */
1748 if (pDis->uOpMode == DISCPUMODE_32BIT)
1749 {
1750 /* Use 32-bit registers. */
1751 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1752 pParam->fUse |= DISUSE_REG_GEN32;
1753 pParam->cb = 4;
1754 }
1755 else if (pDis->uOpMode == DISCPUMODE_64BIT)
1756 {
1757 /* Use 64-bit registers. */
1758 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1759 pParam->fUse |= DISUSE_REG_GEN64;
1760 pParam->cb = 8;
1761 }
1762 else
1763 {
1764 /* Use 16-bit registers. */
1765 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1766 pParam->fUse |= DISUSE_REG_GEN16;
1767 pParam->cb = 2;
1768 pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1769 }
1770
1771 if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1772 && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1773 && (pDis->fPrefix & DISPREFIX_REX)
1774 && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B))
1775 {
1776 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
1777 pParam->Base.idxGenReg += 8;
1778 }
1779 }
1780 else if (pParam->fParam <= OP_PARM_REG_SEG_END)
1781 {
1782 /* Segment ES..GS registers. */
1783 pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
1784 pParam->fUse |= DISUSE_REG_SEG;
1785 pParam->cb = 2;
1786 }
1787 else if (pParam->fParam <= OP_PARM_REG_GEN16_END)
1788 {
1789 /* 16-bit AX..DI registers. */
1790 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN16_START;
1791 pParam->fUse |= DISUSE_REG_GEN16;
1792 pParam->cb = 2;
1793 }
1794 else if (pParam->fParam <= OP_PARM_REG_GEN8_END)
1795 {
1796 /* 8-bit AL..DL, AH..DH registers. */
1797 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
1798 pParam->fUse |= DISUSE_REG_GEN8;
1799 pParam->cb = 1;
1800
1801 if ( pDis->uCpuMode == DISCPUMODE_64BIT
1802 && (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1803 && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1804 && (pDis->fPrefix & DISPREFIX_REX))
1805 {
1806 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)
1807 pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
1808 else if ( pParam->Base.idxGenReg >= DISGREG_AH
1809 && pParam->Base.idxGenReg <= DISGREG_BH)
1810 pParam->Base.idxGenReg += DISGREG_SPL - DISGREG_AH;
1811 }
1812 }
1813 else if (pParam->fParam <= OP_PARM_REG_FP_END)
1814 {
1815 /* FPU registers. */
1816 pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
1817 pParam->fUse |= DISUSE_REG_FP;
1818 pParam->cb = 10;
1819 }
1820 Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
1821
1822 /* else - not supported for now registers. */
1823
1824 return offInstr;
1825}
1826//*****************************************************************************
1827//*****************************************************************************
1828static size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1829{
1830 NOREF(pOp);
1831
1832 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1833 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1834 {
1835 pParam->Base.idxGenReg = DISGREG_ESI;
1836 pParam->fUse |= DISUSE_REG_GEN32;
1837 }
1838 else
1839 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1840 {
1841 pParam->Base.idxGenReg = DISGREG_RSI;
1842 pParam->fUse |= DISUSE_REG_GEN64;
1843 }
1844 else
1845 {
1846 pParam->Base.idxGenReg = DISGREG_SI;
1847 pParam->fUse |= DISUSE_REG_GEN16;
1848 }
1849 return offInstr;
1850}
1851//*****************************************************************************
1852//*****************************************************************************
1853static size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1854{
1855 NOREF(pOp);
1856
1857 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1858 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1859 {
1860 pParam->Base.idxGenReg = DISGREG_ESI;
1861 pParam->fUse |= DISUSE_REG_GEN32;
1862 }
1863 else
1864 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1865 {
1866 pParam->Base.idxGenReg = DISGREG_RSI;
1867 pParam->fUse |= DISUSE_REG_GEN64;
1868 }
1869 else
1870 {
1871 pParam->Base.idxGenReg = DISGREG_SI;
1872 pParam->fUse |= DISUSE_REG_GEN16;
1873 }
1874 return offInstr;
1875}
1876//*****************************************************************************
1877//*****************************************************************************
1878static size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1879{
1880 NOREF(pOp);
1881
1882 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1883 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1884 {
1885 pParam->Base.idxGenReg = DISGREG_EDI;
1886 pParam->fUse |= DISUSE_REG_GEN32;
1887 }
1888 else
1889 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1890 {
1891 pParam->Base.idxGenReg = DISGREG_RDI;
1892 pParam->fUse |= DISUSE_REG_GEN64;
1893 }
1894 else
1895 {
1896 pParam->Base.idxGenReg = DISGREG_DI;
1897 pParam->fUse |= DISUSE_REG_GEN16;
1898 }
1899 return offInstr;
1900}
1901//*****************************************************************************
1902//*****************************************************************************
1903static size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1904{
1905 NOREF(pOp);
1906
1907 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1908 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1909 {
1910 pParam->Base.idxGenReg = DISGREG_EDI;
1911 pParam->fUse |= DISUSE_REG_GEN32;
1912 }
1913 else
1914 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1915 {
1916 pParam->Base.idxGenReg = DISGREG_RDI;
1917 pParam->fUse |= DISUSE_REG_GEN64;
1918 }
1919 else
1920 {
1921 pParam->Base.idxGenReg = DISGREG_DI;
1922 pParam->fUse |= DISUSE_REG_GEN16;
1923 }
1924 return offInstr;
1925}
1926//*****************************************************************************
1927//*****************************************************************************
1928static size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1929{
1930 NOREF(pOp); NOREF(pDis); NOREF(pParam);
1931 /* This is used to avoid a bunch of special hacks to get the ModRM byte
1932 included when encountering invalid opcodes in groups. */
1933 return offInstr + 1;
1934}
1935//*****************************************************************************
1936//*****************************************************************************
1937static size_t ParseVexDest(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1938{
1939 NOREF(pOp);
1940
1941 unsigned type = OP_PARM_VTYPE(pParam->fParam);
1942
1943 switch (type)
1944 {
1945 case OP_PARM_H: //XMM or YMM register
1946 if (VEXREG_IS256B(pDis->bVexDestReg))
1947 {
1948 pParam->fUse |= DISUSE_REG_YMM;
1949 pParam->Base.idxYmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
1950 }
1951 else
1952 {
1953 pParam->fUse |= DISUSE_REG_XMM;
1954 pParam->Base.idxXmmReg = (pDis->bVexDestReg >> 1) ^ 0xf;
1955 }
1956 break;
1957 case OP_PARM_B: // Always OP_PARM_By. Change if it is not so.
1958 if ((pDis->fPrefix & DISPREFIX_REX) && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W))
1959 pParam->fUse |= DISUSE_REG_GEN64;
1960 else
1961 pParam->fUse |= DISUSE_REG_GEN32;
1962 // TODO: Check if the register number is correct
1963 pParam->Base.idxGenReg = (pDis->bVexDestReg >> 1) ^ 0xf;
1964 break;
1965 }
1966
1967 return offInstr;
1968}
1969//*****************************************************************************
1970//*****************************************************************************
1971static size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1972{
1973 NOREF(pOp); NOREF(pParam);
1974
1975 /* 2nd byte */
1976 pDis->bOpCode = disReadByte(pDis, offInstr);
1977 offInstr++;
1978
1979 /* default to the non-prefixed table. */
1980 PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
1981
1982 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1983 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1984 if (pDis->bLastPrefix)
1985 {
1986 switch (pDis->bLastPrefix)
1987 {
1988 case OP_OPSIZE: /* 0x66 */
1989 if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
1990 {
1991 /* Table entry is valid, so use the extension table. */
1992 pOpcode = &g_aTwoByteMapX86_PF66[pDis->bOpCode];
1993
1994 /* Cancel prefix changes. */
1995 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1996
1997 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1998 {
1999 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
2000 }
2001 else
2002 pDis->uOpMode = pDis->uCpuMode;
2003 }
2004 break;
2005
2006 case OP_REPNE: /* 0xF2 */
2007 if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
2008 {
2009 /* Table entry is valid, so use the extension table. */
2010 pOpcode = &g_aTwoByteMapX86_PFF2[pDis->bOpCode];
2011
2012 /* Cancel prefix changes. */
2013 pDis->fPrefix &= ~DISPREFIX_REPNE;
2014 }
2015 break;
2016
2017 case OP_REPE: /* 0xF3 */
2018 if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
2019 {
2020 /* Table entry is valid, so use the extension table. */
2021 pOpcode = &g_aTwoByteMapX86_PFF3[pDis->bOpCode];
2022
2023 /* Cancel prefix changes. */
2024 pDis->fPrefix &= ~DISPREFIX_REP;
2025 }
2026 break;
2027 }
2028 }
2029
2030 return disParseInstruction(offInstr, pOpcode, pDis);
2031}
2032//*****************************************************************************
2033//*****************************************************************************
2034static size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2035{
2036 NOREF(pOp); NOREF(pParam);
2037
2038 /* 3rd byte */
2039 pDis->bOpCode = disReadByte(pDis, offInstr);
2040 offInstr++;
2041
2042 /* default to the non-prefixed table. */
2043 PCDISOPCODE pOpcode;
2044 if (g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4])
2045 {
2046 pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
2047 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2048 }
2049 else
2050 pOpcode = &g_InvalidOpcode[0];
2051
2052 /* Handle opcode table extensions that rely on the address, repne prefix byte. */
2053 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
2054 switch (pDis->bLastPrefix)
2055 {
2056 case OP_OPSIZE: /* 0x66 */
2057 if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
2058 {
2059 pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
2060 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2061
2062 if (pOpcode->uOpcode != OP_INVALID)
2063 {
2064 /* Table entry is valid, so use the extension table. */
2065
2066 /* Cancel prefix changes. */
2067 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
2068 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2069 {
2070 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
2071 }
2072 else
2073 pDis->uOpMode = pDis->uCpuMode;
2074
2075 }
2076 }
2077 break;
2078
2079 case OP_REPNE: /* 0xF2 */
2080 if ((pDis->fPrefix & DISPREFIX_OPSIZE) && g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4])
2081 {
2082 /* 0x66F2 */
2083 pOpcode = g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4];
2084 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2085
2086 if (pOpcode->uOpcode != OP_INVALID)
2087 {
2088 /* Table entry is valid, so use the extension table. */
2089
2090 /* Cancel prefix changes. */
2091 pDis->fPrefix &= ~DISPREFIX_REPNE;
2092 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
2093 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2094 {
2095 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
2096 }
2097 else
2098 pDis->uOpMode = pDis->uCpuMode;
2099 }
2100 }
2101 else if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
2102 {
2103 pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
2104 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2105
2106 if (pOpcode->uOpcode != OP_INVALID)
2107 {
2108 /* Table entry is valid, so use the extension table. */
2109
2110 /* Cancel prefix changes. */
2111 pDis->fPrefix &= ~DISPREFIX_REPNE;
2112 }
2113 }
2114 break;
2115
2116 case OP_REPE: /* 0xF3 */
2117 if (g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4])
2118 {
2119 pOpcode = g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4];
2120 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2121
2122 if (pOpcode->uOpcode != OP_INVALID)
2123 {
2124 /* Table entry is valid, so use the extension table. */
2125
2126 /* Cancel prefix changes. */
2127 pDis->fPrefix &= ~DISPREFIX_REP;
2128 }
2129 }
2130 }
2131
2132 return disParseInstruction(offInstr, pOpcode, pDis);
2133}
2134//*****************************************************************************
2135//*****************************************************************************
2136static size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2137{
2138 NOREF(pOp); NOREF(pParam);
2139
2140 /* 3rd byte */
2141 pDis->bOpCode = disReadByte(pDis, offInstr);
2142 offInstr++;
2143
2144 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
2145 Assert(pDis->bLastPrefix == OP_OPSIZE);
2146
2147 /* default to the non-prefixed table. */
2148 PCDISOPCODE pOpcode;
2149 if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
2150 {
2151 pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
2152 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2153
2154 if (pOpcode->uOpcode != OP_INVALID)
2155 {
2156 /* Table entry is valid, so use the extension table. */
2157
2158 /* Cancel prefix changes. */
2159 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
2160 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2161 {
2162 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
2163 }
2164 else
2165 pDis->uOpMode = pDis->uCpuMode;
2166
2167 }
2168 }
2169 else
2170 pOpcode = &g_InvalidOpcode[0];
2171
2172 return disParseInstruction(offInstr, pOpcode, pDis);
2173}
2174//*****************************************************************************
2175//*****************************************************************************
2176static size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2177{
2178 NOREF(pParam);
2179
2180 if (pDis->fPrefix & DISPREFIX_REP)
2181 {
2182 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
2183 pDis->fPrefix &= ~DISPREFIX_REP;
2184 }
2185 else
2186 pOp = &g_aMapX86_NopPause[0]; /* NOP */
2187
2188 return disParseInstruction(offInstr, pOp, pDis);
2189}
2190//*****************************************************************************
2191//*****************************************************************************
2192static size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2193{
2194 NOREF(pParam);
2195
2196 uint8_t modrm = disReadByte(pDis, offInstr);
2197 uint8_t reg = MODRM_REG(modrm);
2198 unsigned idx = (pDis->bOpCode - 0x80) * 8;
2199
2200 pOp = &g_aMapX86_Group1[idx+reg];
2201
2202 return disParseInstruction(offInstr, pOp, pDis);
2203}
2204//*****************************************************************************
2205//*****************************************************************************
2206static size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2207{
2208 NOREF(pParam);
2209
2210 unsigned idx;
2211 switch (pDis->bOpCode)
2212 {
2213 case 0xC0:
2214 case 0xC1:
2215 idx = (pDis->bOpCode - 0xC0)*8;
2216 break;
2217
2218 case 0xD0:
2219 case 0xD1:
2220 case 0xD2:
2221 case 0xD3:
2222 idx = (pDis->bOpCode - 0xD0 + 2)*8;
2223 break;
2224
2225 default:
2226 Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
2227 pDis->rc = VERR_DIS_INVALID_OPCODE;
2228 return offInstr;
2229 }
2230
2231 uint8_t modrm = disReadByte(pDis, offInstr);
2232 uint8_t reg = MODRM_REG(modrm);
2233
2234 pOp = &g_aMapX86_Group2[idx+reg];
2235
2236 return disParseInstruction(offInstr, pOp, pDis);
2237}
2238//*****************************************************************************
2239//*****************************************************************************
2240static size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2241{
2242 unsigned idx = (pDis->bOpCode - 0xF6) * 8;
2243 NOREF(pParam);
2244
2245 uint8_t modrm = disReadByte(pDis, offInstr);
2246 uint8_t reg = MODRM_REG(modrm);
2247
2248 pOp = &g_aMapX86_Group3[idx+reg];
2249
2250 return disParseInstruction(offInstr, pOp, pDis);
2251}
2252//*****************************************************************************
2253//*****************************************************************************
2254static size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2255{
2256 NOREF(pParam);
2257
2258 uint8_t modrm = disReadByte(pDis, offInstr);
2259 uint8_t reg = MODRM_REG(modrm);
2260
2261 pOp = &g_aMapX86_Group4[reg];
2262
2263 return disParseInstruction(offInstr, pOp, pDis);
2264}
2265//*****************************************************************************
2266//*****************************************************************************
2267static size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2268{
2269 NOREF(pParam);
2270
2271 uint8_t modrm = disReadByte(pDis, offInstr);
2272 uint8_t reg = MODRM_REG(modrm);
2273
2274 pOp = &g_aMapX86_Group5[reg];
2275
2276 return disParseInstruction(offInstr, pOp, pDis);
2277}
2278//*****************************************************************************
2279// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
2280// It would appear the ModRM byte must always be present. How else can you
2281// determine the offset of the imm8_opcode byte otherwise?
2282//
2283//*****************************************************************************
2284static size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2285{
2286 /** @todo This code needs testing! Esp. wrt invalid opcodes. */
2287
2288 uint8_t ModRM = disReadByte(pDis, offInstr);
2289 pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
2290 pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
2291 pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
2292
2293 size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
2294
2295 uint8_t opcode = disReadByte(pDis, offRet);
2296 offRet++;
2297 pOp = &g_aTwoByteMapX86_3DNow[opcode];
2298
2299 size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
2300
2301 AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
2302 ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
2303 NOREF(offStrict);
2304
2305 return offRet;
2306}
2307//*****************************************************************************
2308//*****************************************************************************
2309static size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2310{
2311 NOREF(pParam);
2312
2313 uint8_t modrm = disReadByte(pDis, offInstr);
2314 uint8_t reg = MODRM_REG(modrm);
2315
2316 pOp = &g_aMapX86_Group6[reg];
2317
2318 return disParseInstruction(offInstr, pOp, pDis);
2319}
2320//*****************************************************************************
2321//*****************************************************************************
2322static size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2323{
2324 NOREF(pParam);
2325
2326 uint8_t modrm = disReadByte(pDis, offInstr);
2327 uint8_t mod = MODRM_MOD(modrm);
2328 uint8_t reg = MODRM_REG(modrm);
2329 uint8_t rm = MODRM_RM(modrm);
2330
2331 if (mod == 3 && rm == 0)
2332 pOp = &g_aMapX86_Group7_mod11_rm000[reg];
2333 else
2334 if (mod == 3 && rm == 1)
2335 pOp = &g_aMapX86_Group7_mod11_rm001[reg];
2336 else
2337 pOp = &g_aMapX86_Group7_mem[reg];
2338
2339 /* Cannot easily skip this hack because of monitor and vmcall! */
2340 //little hack to make sure the ModRM byte is included in the returned size
2341 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2342 offInstr++;
2343
2344 return disParseInstruction(offInstr, pOp, pDis);
2345}
2346//*****************************************************************************
2347//*****************************************************************************
2348static size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2349{
2350 NOREF(pParam);
2351
2352 uint8_t modrm = disReadByte(pDis, offInstr);
2353 uint8_t reg = MODRM_REG(modrm);
2354
2355 pOp = &g_aMapX86_Group8[reg];
2356
2357 return disParseInstruction(offInstr, pOp, pDis);
2358}
2359//*****************************************************************************
2360//*****************************************************************************
2361static size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2362{
2363 NOREF(pParam);
2364
2365 uint8_t modrm = disReadByte(pDis, offInstr);
2366 uint8_t reg = MODRM_REG(modrm);
2367
2368 pOp = &g_aMapX86_Group9[reg];
2369
2370 return disParseInstruction(offInstr, pOp, pDis);
2371}
2372//*****************************************************************************
2373//*****************************************************************************
2374static size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2375{
2376 NOREF(pParam);
2377
2378 uint8_t modrm = disReadByte(pDis, offInstr);
2379 uint8_t reg = MODRM_REG(modrm);
2380
2381 pOp = &g_aMapX86_Group10[reg];
2382
2383 return disParseInstruction(offInstr, pOp, pDis);
2384}
2385//*****************************************************************************
2386//*****************************************************************************
2387static size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2388{
2389 NOREF(pParam);
2390
2391 uint8_t modrm = disReadByte(pDis, offInstr);
2392 uint8_t reg = MODRM_REG(modrm);
2393
2394 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2395 reg += 8; /* 2nd table */
2396
2397 pOp = &g_aMapX86_Group12[reg];
2398
2399 return disParseInstruction(offInstr, pOp, pDis);
2400}
2401//*****************************************************************************
2402//*****************************************************************************
2403static size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2404{
2405 NOREF(pParam);
2406
2407 uint8_t modrm = disReadByte(pDis, offInstr);
2408 uint8_t reg = MODRM_REG(modrm);
2409 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2410 reg += 8; /* 2nd table */
2411
2412 pOp = &g_aMapX86_Group13[reg];
2413
2414 return disParseInstruction(offInstr, pOp, pDis);
2415}
2416//*****************************************************************************
2417//*****************************************************************************
2418static size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2419{
2420 NOREF(pParam);
2421
2422 uint8_t modrm = disReadByte(pDis, offInstr);
2423 uint8_t reg = MODRM_REG(modrm);
2424 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2425 reg += 8; /* 2nd table */
2426
2427 pOp = &g_aMapX86_Group14[reg];
2428
2429 return disParseInstruction(offInstr, pOp, pDis);
2430}
2431//*****************************************************************************
2432//*****************************************************************************
2433static size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2434{
2435 NOREF(pParam);
2436
2437 uint8_t modrm = disReadByte(pDis, offInstr);
2438 uint8_t mod = MODRM_MOD(modrm);
2439 uint8_t reg = MODRM_REG(modrm);
2440 uint8_t rm = MODRM_RM(modrm);
2441
2442 if (mod == 3 && rm == 0)
2443 pOp = &g_aMapX86_Group15_mod11_rm000[reg];
2444 else
2445 pOp = &g_aMapX86_Group15_mem[reg];
2446
2447 return disParseInstruction(offInstr, pOp, pDis);
2448}
2449//*****************************************************************************
2450//*****************************************************************************
2451static size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2452{
2453 NOREF(pParam);
2454
2455 uint8_t modrm = disReadByte(pDis, offInstr);
2456 pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
2457
2458 return disParseInstruction(offInstr, pOp, pDis);
2459}
2460//*****************************************************************************
2461//*****************************************************************************
2462static size_t ParseVex2b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2463{
2464 NOREF(pOp); NOREF(pParam);
2465
2466 PCDISOPCODE pOpCode = &g_InvalidOpcode[0];
2467
2468 uint8_t byte = disReadByte(pDis, offInstr++);
2469 pDis->bOpCode = disReadByte(pDis, offInstr++);
2470
2471 pDis->bVexDestReg = VEX_2B2INT(byte);
2472
2473 // VEX.R (equivalent to REX.R)
2474 if (pDis->uCpuMode == DISCPUMODE_64BIT && !(byte & 0x80))
2475 {
2476 /* REX prefix byte */
2477 pDis->fPrefix |= DISPREFIX_REX;
2478 pDis->fRexPrefix = DISPREFIX_REX_FLAGS_R;
2479 }
2480
2481 switch(byte & 3)
2482 {
2483 case 0:
2484 pOpCode = g_aVexOpcodesMap[0] + pDis->bOpCode;
2485 break;
2486 // OPSIZE 0x66 prefix
2487 case 1:
2488 pOpCode = g_aVexOpcodesMap_66H[0] + pDis->bOpCode;
2489
2490 /* TODO: Check if we need to set this prefix */
2491 pDis->fPrefix |= DISPREFIX_OPSIZE;
2492 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2493 pDis->uOpMode = DISCPUMODE_32BIT;
2494 else
2495 pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2496 break;
2497
2498 // REPE 0xF3 prefix
2499 case 2:
2500 pOpCode = g_aVexOpcodesMap_F3H[0] + pDis->bOpCode;
2501 break;
2502
2503 // REPNE 0xF2 prefix
2504 case 3:
2505 pOpCode = g_aVexOpcodesMap_F2H[0] + pDis->bOpCode;
2506 break;
2507 default:
2508 break;
2509 }
2510
2511 return disParseInstruction(offInstr, pOpCode, pDis);
2512}
2513//*****************************************************************************
2514//*****************************************************************************
2515static size_t ParseVex3b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2516{
2517 NOREF(pOp); NOREF(pParam);
2518
2519 PCDISOPCODE pOpCode = NULL;
2520
2521 uint8_t byte1 = disReadByte(pDis, offInstr++);
2522 uint8_t byte2 = disReadByte(pDis, offInstr++);
2523 pDis->bOpCode = disReadByte(pDis, offInstr++);
2524
2525 pDis->bVexDestReg = VEX_2B2INT(byte2);
2526 uint8_t implOpcode = (byte1 & 0x1f);
2527
2528 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2529 {
2530 // REX.RXB
2531 if (~(byte1 & 0xe0))
2532 {
2533 pDis->fRexPrefix = (byte1 >> 5) ^ 7;
2534 if (pDis->fRexPrefix)
2535 pDis->fPrefix |= DISPREFIX_REX;
2536 }
2537
2538 // REX.W
2539 if (!(byte2 & 0x80))
2540 {
2541 pDis->fRexPrefix |= DISPREFIX_REX_FLAGS_W;
2542 if (pDis->fRexPrefix)
2543 pDis->fPrefix |= DISPREFIX_REX;
2544 }
2545 }
2546
2547 switch(byte2 & 3)
2548 {
2549 case 0:
2550 if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
2551 {
2552 pOpCode = g_aVexOpcodesMap[implOpcode - 1];
2553 if (pOpCode != NULL)
2554 {
2555 switch (implOpcode)
2556 {
2557 case 2:
2558 if (pDis->bOpCode >= 0xf0)
2559 pOpCode = &pOpCode[pDis->bOpCode - 0xf0];
2560 else pOpCode = g_InvalidOpcode;
2561 break;
2562 default:
2563 pOpCode = &pOpCode[pDis->bOpCode];
2564 }
2565 }
2566 }
2567 break;
2568 // OPSIZE 0x66 prefix
2569 case 1:
2570 if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
2571 {
2572 pOpCode = g_aVexOpcodesMap_66H[implOpcode - 1];
2573 if (pOpCode != NULL)
2574 pOpCode = &pOpCode[pDis->bOpCode];
2575 /* TODO: check if we need to set this prefix */
2576 pDis->fPrefix |= DISPREFIX_OPSIZE;
2577 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2578 pDis->uOpMode = DISCPUMODE_32BIT;
2579 else
2580 pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2581 }
2582 break;
2583
2584 // REPE 0xF3 prefix
2585 case 2:
2586 if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
2587 {
2588 pOpCode = g_aVexOpcodesMap_F3H[implOpcode - 1];
2589 if (pOpCode != NULL)
2590 {
2591 switch (implOpcode)
2592 {
2593 case 2:
2594 if (pDis->bOpCode >= 0xf0)
2595 pOpCode = &pOpCode[pDis->bOpCode - 0xf0];
2596 else pOpCode = g_InvalidOpcode;
2597 break;
2598 default:
2599 pOpCode = &pOpCode[pDis->bOpCode];
2600 }
2601 }
2602
2603 }
2604 break;
2605
2606 // REPNE 0xF2 prefix
2607 case 3:
2608 if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
2609 {
2610 pOpCode = g_aVexOpcodesMap_F2H[implOpcode - 1];
2611 if (pOpCode != NULL)
2612 {
2613 switch (implOpcode)
2614 {
2615 case 2:
2616 if (pDis->bOpCode >= 0xf0)
2617 pOpCode = &pOpCode[pDis->bOpCode - 0xf0];
2618 else pOpCode = g_InvalidOpcode;
2619 break;
2620 case 3:
2621 if (pDis->bOpCode != 0xf0)
2622 pOpCode = g_InvalidOpcode;
2623 break;
2624 default:
2625 pOpCode = &pOpCode[pDis->bOpCode];
2626 }
2627 }
2628 }
2629 break;
2630
2631 default:
2632 break;
2633 }
2634
2635 if (pOpCode == NULL)
2636 pOpCode = g_InvalidOpcode;
2637
2638 return disParseInstruction(offInstr, pOpCode, pDis);
2639}
2640
2641
2642/**
2643 * Validates the lock sequence.
2644 *
2645 * The AMD manual lists the following instructions:
2646 * ADC
2647 * ADD
2648 * AND
2649 * BTC
2650 * BTR
2651 * BTS
2652 * CMPXCHG
2653 * CMPXCHG8B
2654 * CMPXCHG16B
2655 * DEC
2656 * INC
2657 * NEG
2658 * NOT
2659 * OR
2660 * SBB
2661 * SUB
2662 * XADD
2663 * XCHG
2664 * XOR
2665 *
2666 * @param pDis Fully disassembled instruction.
2667 */
2668static void disValidateLockSequence(PDISSTATE pDis)
2669{
2670 Assert(pDis->fPrefix & DISPREFIX_LOCK);
2671
2672 /*
2673 * Filter out the valid lock sequences.
2674 */
2675 switch (pDis->pCurInstr->uOpcode)
2676 {
2677 /* simple: no variations */
2678 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2679 return;
2680
2681 /* simple: /r - reject register destination. */
2682 case OP_BTC:
2683 case OP_BTR:
2684 case OP_BTS:
2685 case OP_CMPXCHG:
2686 case OP_XADD:
2687 if (pDis->ModRM.Bits.Mod == 3)
2688 break;
2689 return;
2690
2691 /*
2692 * Lots of variants but its sufficient to check that param 1
2693 * is a memory operand.
2694 */
2695 case OP_ADC:
2696 case OP_ADD:
2697 case OP_AND:
2698 case OP_DEC:
2699 case OP_INC:
2700 case OP_NEG:
2701 case OP_NOT:
2702 case OP_OR:
2703 case OP_SBB:
2704 case OP_SUB:
2705 case OP_XCHG:
2706 case OP_XOR:
2707 if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
2708 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
2709 return;
2710 break;
2711
2712 default:
2713 break;
2714 }
2715
2716 /*
2717 * Invalid lock sequence, make it a OP_ILLUD2.
2718 */
2719 pDis->pCurInstr = &g_aTwoByteMapX86[11];
2720 Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
2721}
2722
2723/**
2724 * Internal worker for DISInstrEx and DISInstrWithPrefetchedBytes.
2725 *
2726 * @returns VBox status code.
2727 * @param pDis Initialized disassembler state.
2728 * @param paOneByteMap The one byte opcode map to use.
2729 * @param pcbInstr Where to store the instruction size. Can be NULL.
2730 */
2731static int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
2732{
2733 /*
2734 * Parse byte by byte.
2735 */
2736 size_t offInstr = 0;
2737 for (;;)
2738 {
2739 uint8_t codebyte = disReadByte(pDis, offInstr++);
2740 uint8_t opcode = paOneByteMap[codebyte].uOpcode;
2741
2742 /* Hardcoded assumption about OP_* values!! */
2743 if (opcode <= OP_LAST_PREFIX)
2744 {
2745 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
2746 if (opcode != OP_REX)
2747 {
2748 /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
2749 pDis->bLastPrefix = opcode;
2750 pDis->fPrefix &= ~DISPREFIX_REX;
2751 }
2752
2753 switch (opcode)
2754 {
2755 case OP_INVALID:
2756 if (pcbInstr)
2757 *pcbInstr = (uint32_t)offInstr;
2758 return pDis->rc = VERR_DIS_INVALID_OPCODE;
2759
2760 // segment override prefix byte
2761 case OP_SEG:
2762 pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
2763#if 0 /* Try be accurate in our reporting, shouldn't break anything... :-) */
2764 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
2765 if ( pDis->uCpuMode != DISCPUMODE_64BIT
2766 || pDis->idxSegPrefix >= DISSELREG_FS)
2767 pDis->fPrefix |= DISPREFIX_SEG;
2768#else
2769 pDis->fPrefix |= DISPREFIX_SEG;
2770#endif
2771 continue; //fetch the next byte
2772
2773 // lock prefix byte
2774 case OP_LOCK:
2775 pDis->fPrefix |= DISPREFIX_LOCK;
2776 continue; //fetch the next byte
2777
2778 // address size override prefix byte
2779 case OP_ADDRSIZE:
2780 pDis->fPrefix |= DISPREFIX_ADDRSIZE;
2781 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2782 pDis->uAddrMode = DISCPUMODE_32BIT;
2783 else
2784 if (pDis->uCpuMode == DISCPUMODE_32BIT)
2785 pDis->uAddrMode = DISCPUMODE_16BIT;
2786 else
2787 pDis->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
2788 continue; //fetch the next byte
2789
2790 // operand size override prefix byte
2791 case OP_OPSIZE:
2792 pDis->fPrefix |= DISPREFIX_OPSIZE;
2793 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2794 pDis->uOpMode = DISCPUMODE_32BIT;
2795 else
2796 pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2797 continue; //fetch the next byte
2798
2799 // rep and repne are not really prefixes, but we'll treat them as such
2800 case OP_REPE:
2801 pDis->fPrefix |= DISPREFIX_REP;
2802 continue; //fetch the next byte
2803
2804 case OP_REPNE:
2805 pDis->fPrefix |= DISPREFIX_REPNE;
2806 continue; //fetch the next byte
2807
2808 case OP_REX:
2809 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
2810 /* REX prefix byte */
2811 pDis->fPrefix |= DISPREFIX_REX;
2812 pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
2813 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
2814 pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
2815 continue; //fetch the next byte
2816 default:
2817 break;
2818 }
2819 }
2820
2821 /* Check if this is a VEX prefix. Not for 32-bit mode. */
2822 if ((opcode == OP_LES || opcode == OP_LDS)
2823 && (disReadByte(pDis, offInstr) & 0xc0) == 0xc0
2824 && (opcode != OP_LES || pDis->uCpuMode == DISCPUMODE_64BIT || !(disReadByte(pDis, offInstr + 1) & 0x80)))
2825 {
2826 paOneByteMap = g_aOneByteMapX64;
2827 }
2828
2829 /* first opcode byte. */
2830 pDis->bOpCode = codebyte;
2831 pDis->cbPrefix = (uint8_t)offInstr - 1;
2832
2833 offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
2834 break;
2835 }
2836
2837 pDis->cbInstr = (uint8_t)offInstr;
2838 if (pcbInstr)
2839 *pcbInstr = (uint32_t)offInstr;
2840
2841 if (pDis->fPrefix & DISPREFIX_LOCK)
2842 disValidateLockSequence(pDis);
2843
2844 return pDis->rc;
2845}
2846
2847
2848/**
2849 * Inlined worker that initializes the disassembler state.
2850 *
2851 * @returns The primary opcode map to use.
2852 * @param pDis The disassembler state.
2853 * @param uInstrAddr The instruction address.
2854 * @param enmCpuMode The CPU mode.
2855 * @param fFilter The instruction filter settings.
2856 * @param pfnReadBytes The byte reader, can be NULL.
2857 * @param pvUser The the user data for the reader.
2858 */
2859DECL_FORCE_INLINE(PCDISOPCODE)
2860disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2861 PFNDISREADBYTES pfnReadBytes, void *pvUser)
2862{
2863 RT_ZERO(*pDis);
2864
2865#ifdef VBOX_STRICT /* poison */
2866 pDis->Param1.Base.idxGenReg = 0xc1;
2867 pDis->Param2.Base.idxGenReg = 0xc2;
2868 pDis->Param3.Base.idxGenReg = 0xc3;
2869 pDis->Param1.Index.idxGenReg = 0xc4;
2870 pDis->Param2.Index.idxGenReg = 0xc5;
2871 pDis->Param3.Index.idxGenReg = 0xc6;
2872 pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
2873 pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
2874 pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
2875 pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
2876 pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
2877 pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
2878 pDis->Param1.uScale = 28;
2879 pDis->Param2.uScale = 29;
2880 pDis->Param3.uScale = 30;
2881#endif
2882
2883 pDis->fPrefix = DISPREFIX_NONE;
2884 pDis->idxSegPrefix = DISSELREG_DS;
2885 pDis->rc = VINF_SUCCESS;
2886 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
2887
2888 pDis->uInstrAddr = uInstrAddr;
2889 pDis->fFilter = fFilter;
2890 pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
2891 pDis->pvUser = pvUser;
2892 pDis->uCpuMode = enmCpuMode;
2893 PCDISOPCODE paOneByteMap;
2894 if (enmCpuMode == DISCPUMODE_64BIT)
2895 {
2896 pDis->uAddrMode = DISCPUMODE_64BIT;
2897 pDis->uOpMode = DISCPUMODE_32BIT;
2898 paOneByteMap = g_aOneByteMapX64;
2899 }
2900 else
2901 {
2902 pDis->uAddrMode = enmCpuMode;
2903 pDis->uOpMode = enmCpuMode;
2904 paOneByteMap = g_aOneByteMapX86;
2905 }
2906 return paOneByteMap;
2907}
2908
2909
2910/**
2911 * Reads some bytes into the cache.
2912 *
2913 * While this will set DISSTATE::rc on failure, the caller should disregard
2914 * this since that is what would happen if we didn't prefetch bytes prior to the
2915 * instruction parsing.
2916 *
2917 * @param pDis The disassembler state.
2918 */
2919DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
2920{
2921 /*
2922 * Read some bytes into the cache. (If this fail we continue as nothing
2923 * has gone wrong since this is what would happen if we didn't precharge
2924 * the cache here.)
2925 */
2926 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
2927 if (RT_SUCCESS(rc))
2928 {
2929 Assert(pDis->cbCachedInstr >= 1);
2930 Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
2931 }
2932 else
2933 {
2934 Log(("Initial read failed with rc=%Rrc!!\n", rc));
2935 pDis->rc = rc;
2936 }
2937}
2938
2939
2940/**
2941 * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
2942 *
2943 * @returns VBox status code.
2944 * @param uInstrAddr Address of the instruction to decode. What this means
2945 * is left to the pfnReadBytes function.
2946 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2947 * @param pfnReadBytes Callback for reading instruction bytes.
2948 * @param fFilter Instruction type filter.
2949 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2950 * @param pDis Pointer to disassembler state (output).
2951 * @param pcbInstr Where to store the size of the instruction. (This
2952 * is also stored in PDISSTATE::cbInstr.) Optional.
2953 */
2954DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2955 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2956 PDISSTATE pDis, uint32_t *pcbInstr)
2957{
2958
2959 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2960 disPrefetchBytes(pDis);
2961 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2962}
2963
2964
2965/**
2966 * Disassembles on instruction partially or fully from prefetched bytes, details
2967 * in @a pDis and length in @a pcbInstr.
2968 *
2969 * @returns VBox status code.
2970 * @param uInstrAddr Address of the instruction to decode. What this means
2971 * is left to the pfnReadBytes function.
2972 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2973 * @param pvPrefetched Pointer to the prefetched bytes.
2974 * @param cbPrefetched The number of valid bytes pointed to by @a
2975 * pbPrefetched.
2976 * @param pfnReadBytes Callback for reading instruction bytes.
2977 * @param fFilter Instruction type filter.
2978 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2979 * @param pDis Pointer to disassembler state (output).
2980 * @param pcbInstr Where to store the size of the instruction. (This
2981 * is also stored in PDISSTATE::cbInstr.) Optional.
2982 */
2983DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2984 void const *pvPrefetched, size_t cbPretched,
2985 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2986 PDISSTATE pDis, uint32_t *pcbInstr)
2987{
2988 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2989
2990 if (!cbPretched)
2991 disPrefetchBytes(pDis);
2992 else
2993 {
2994 if (cbPretched >= sizeof(pDis->abInstr))
2995 {
2996 memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
2997 pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
2998 }
2999 else
3000 {
3001 memcpy(pDis->abInstr, pvPrefetched, cbPretched);
3002 pDis->cbCachedInstr = (uint8_t)cbPretched;
3003 }
3004 }
3005
3006 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
3007}
3008
3009
3010
3011/**
3012 * Parses one guest instruction.
3013 *
3014 * The result is found in pDis and pcbInstr.
3015 *
3016 * @returns VBox status code.
3017 * @param uInstrAddr Address of the instruction to decode. What this means
3018 * is left to the pfnReadBytes function.
3019 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
3020 * @param pfnReadBytes Callback for reading instruction bytes.
3021 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
3022 * @param pDis Pointer to disassembler state (output).
3023 * @param pcbInstr Where to store the size of the instruction.
3024 * NULL is allowed. This is also stored in
3025 * PDISSTATE::cbInstr.
3026 */
3027DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
3028 PDISSTATE pDis, uint32_t *pcbInstr)
3029{
3030 return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
3031}
3032
3033
3034/**
3035 * Parses one guest instruction.
3036 *
3037 * The result is found in pDis and pcbInstr.
3038 *
3039 * @returns VBox status code.
3040 * @param pvInstr Address of the instruction to decode. This is a
3041 * real address in the current context that can be
3042 * accessed without faulting. (Consider
3043 * DISInstrWithReader if this isn't the case.)
3044 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
3045 * @param pfnReadBytes Callback for reading instruction bytes.
3046 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
3047 * @param pDis Pointer to disassembler state (output).
3048 * @param pcbInstr Where to store the size of the instruction.
3049 * NULL is allowed. This is also stored in
3050 * PDISSTATE::cbInstr.
3051 */
3052DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
3053{
3054 return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);
3055}
3056
Note: See TracBrowser for help on using the repository browser.

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