VirtualBox

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

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

Runtime, Devices, Disassembler R0: warnings.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use