VirtualBox

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

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

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

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

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