VirtualBox

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

Last change on this file since 41871 was 41869, checked in by vboxsync, 13 years ago

DIS: Moved OP_PARM_Q to the group of 'rare' operands, next to OP_PARAM_P, so that MMX register aren't confused with 64-bit general register (rax, etc).

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

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