VirtualBox

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

Last change on this file since 63001 was 62594, checked in by vboxsync, 8 years ago

warnings

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