VirtualBox

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

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

DIS: #6249: Some bug fixes and new testcases. Enabled 0F3A instructions which were accidentally disabled. Added support for 0F3A instruction without prefix.

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

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