VirtualBox

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

Last change on this file since 57358 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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

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