VirtualBox

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

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

Fixed incorrect 64-bit register handling in ParseFixedReg, affecting mov rXX,imm8/V.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 93.0 KB
Line 
1/* $Id: DisasmCore.cpp 46949 2013-07-03 19:22:34Z 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 = rc;
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 const 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 offInstr + 2;
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 if (pDis->uOpMode == DISCPUMODE_64BIT)
1710 {
1711 /* Use 64-bit registers. */
1712 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1713 pParam->fUse |= DISUSE_REG_GEN64;
1714 pParam->cb = 8;
1715 }
1716 else
1717 {
1718 /* Use 16-bit registers. */
1719 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1720 pParam->fUse |= DISUSE_REG_GEN16;
1721 pParam->cb = 2;
1722 pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1723 }
1724
1725 if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1726 && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1727 && (pDis->fPrefix & DISPREFIX_REX)
1728 && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B))
1729 {
1730 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
1731 pParam->Base.idxGenReg += 8;
1732 }
1733 }
1734 else if (pParam->fParam <= OP_PARM_REG_SEG_END)
1735 {
1736 /* Segment ES..GS registers. */
1737 pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
1738 pParam->fUse |= DISUSE_REG_SEG;
1739 pParam->cb = 2;
1740 }
1741 else 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 if (pParam->fParam <= OP_PARM_REG_GEN8_END)
1749 {
1750 /* 8-bit AL..DL, AH..DH registers. */
1751 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
1752 pParam->fUse |= DISUSE_REG_GEN8;
1753 pParam->cb = 1;
1754
1755 if ( pDis->uCpuMode == DISCPUMODE_64BIT
1756 && (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1757 && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1758 && (pDis->fPrefix & DISPREFIX_REX))
1759 {
1760 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)
1761 pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
1762 else if ( pParam->Base.idxGenReg >= DISGREG_AH
1763 && pParam->Base.idxGenReg <= DISGREG_BH)
1764 pParam->Base.idxGenReg += DISGREG_SPL - DISGREG_AH;
1765 }
1766 }
1767 else if (pParam->fParam <= OP_PARM_REG_FP_END)
1768 {
1769 /* FPU registers. */
1770 pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
1771 pParam->fUse |= DISUSE_REG_FP;
1772 pParam->cb = 10;
1773 }
1774 Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
1775
1776 /* else - not supported for now registers. */
1777
1778 return offInstr;
1779}
1780//*****************************************************************************
1781//*****************************************************************************
1782static size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1783{
1784 NOREF(pOp);
1785
1786 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1787 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1788 {
1789 pParam->Base.idxGenReg = DISGREG_ESI;
1790 pParam->fUse |= DISUSE_REG_GEN32;
1791 }
1792 else
1793 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1794 {
1795 pParam->Base.idxGenReg = DISGREG_RSI;
1796 pParam->fUse |= DISUSE_REG_GEN64;
1797 }
1798 else
1799 {
1800 pParam->Base.idxGenReg = DISGREG_SI;
1801 pParam->fUse |= DISUSE_REG_GEN16;
1802 }
1803 return offInstr;
1804}
1805//*****************************************************************************
1806//*****************************************************************************
1807static size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1808{
1809 NOREF(pOp);
1810
1811 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1812 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1813 {
1814 pParam->Base.idxGenReg = DISGREG_ESI;
1815 pParam->fUse |= DISUSE_REG_GEN32;
1816 }
1817 else
1818 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1819 {
1820 pParam->Base.idxGenReg = DISGREG_RSI;
1821 pParam->fUse |= DISUSE_REG_GEN64;
1822 }
1823 else
1824 {
1825 pParam->Base.idxGenReg = DISGREG_SI;
1826 pParam->fUse |= DISUSE_REG_GEN16;
1827 }
1828 return offInstr;
1829}
1830//*****************************************************************************
1831//*****************************************************************************
1832static size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1833{
1834 NOREF(pOp);
1835
1836 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1837 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1838 {
1839 pParam->Base.idxGenReg = DISGREG_EDI;
1840 pParam->fUse |= DISUSE_REG_GEN32;
1841 }
1842 else
1843 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1844 {
1845 pParam->Base.idxGenReg = DISGREG_RDI;
1846 pParam->fUse |= DISUSE_REG_GEN64;
1847 }
1848 else
1849 {
1850 pParam->Base.idxGenReg = DISGREG_DI;
1851 pParam->fUse |= DISUSE_REG_GEN16;
1852 }
1853 return offInstr;
1854}
1855//*****************************************************************************
1856//*****************************************************************************
1857static size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1858{
1859 NOREF(pOp);
1860
1861 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1862 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1863 {
1864 pParam->Base.idxGenReg = DISGREG_EDI;
1865 pParam->fUse |= DISUSE_REG_GEN32;
1866 }
1867 else
1868 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1869 {
1870 pParam->Base.idxGenReg = DISGREG_RDI;
1871 pParam->fUse |= DISUSE_REG_GEN64;
1872 }
1873 else
1874 {
1875 pParam->Base.idxGenReg = DISGREG_DI;
1876 pParam->fUse |= DISUSE_REG_GEN16;
1877 }
1878 return offInstr;
1879}
1880//*****************************************************************************
1881//*****************************************************************************
1882static size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1883{
1884 /* This is used to avoid a bunch of special hacks to get the ModRM byte
1885 included when encountering invalid opcodes in groups. */
1886 return offInstr + 1;
1887}
1888//*****************************************************************************
1889//*****************************************************************************
1890static size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1891{
1892 NOREF(pOp); NOREF(pParam);
1893
1894 /* 2nd byte */
1895 pDis->bOpCode = disReadByte(pDis, offInstr);
1896 offInstr++;
1897
1898 /* default to the non-prefixed table. */
1899 PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
1900
1901 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1902 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1903 if (pDis->bLastPrefix)
1904 {
1905 switch (pDis->bLastPrefix)
1906 {
1907 case OP_OPSIZE: /* 0x66 */
1908 if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
1909 {
1910 /* Table entry is valid, so use the extension table. */
1911 pOpcode = &g_aTwoByteMapX86_PF66[pDis->bOpCode];
1912
1913 /* Cancel prefix changes. */
1914 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1915 pDis->uOpMode = pDis->uCpuMode;
1916 }
1917 break;
1918
1919 case OP_REPNE: /* 0xF2 */
1920 if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
1921 {
1922 /* Table entry is valid, so use the extension table. */
1923 pOpcode = &g_aTwoByteMapX86_PFF2[pDis->bOpCode];
1924
1925 /* Cancel prefix changes. */
1926 pDis->fPrefix &= ~DISPREFIX_REPNE;
1927 }
1928 break;
1929
1930 case OP_REPE: /* 0xF3 */
1931 if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
1932 {
1933 /* Table entry is valid, so use the extension table. */
1934 pOpcode = &g_aTwoByteMapX86_PFF3[pDis->bOpCode];
1935
1936 /* Cancel prefix changes. */
1937 pDis->fPrefix &= ~DISPREFIX_REP;
1938 }
1939 break;
1940 }
1941 }
1942
1943 return disParseInstruction(offInstr, pOpcode, pDis);
1944}
1945//*****************************************************************************
1946//*****************************************************************************
1947static size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1948{
1949 NOREF(pOp); NOREF(pParam);
1950
1951 /* 3rd byte */
1952 pDis->bOpCode = disReadByte(pDis, offInstr);
1953 offInstr++;
1954
1955 /* default to the non-prefixed table. */
1956 PCDISOPCODE pOpcode;
1957 if (g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4])
1958 {
1959 pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
1960 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1961 }
1962 else
1963 pOpcode = &g_InvalidOpcode[0];
1964
1965 /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1966 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1967 switch (pDis->bLastPrefix)
1968 {
1969 case OP_OPSIZE: /* 0x66 */
1970 if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
1971 {
1972 pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
1973 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1974
1975 if (pOpcode->uOpcode != OP_INVALID)
1976 {
1977 /* Table entry is valid, so use the extension table. */
1978
1979 /* Cancel prefix changes. */
1980 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1981 pDis->uOpMode = pDis->uCpuMode;
1982 }
1983 }
1984 break;
1985
1986 case OP_REPNE: /* 0xF2 */
1987 if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
1988 {
1989 pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
1990 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1991
1992 if (pOpcode->uOpcode != OP_INVALID)
1993 {
1994 /* Table entry is valid, so use the extension table. */
1995
1996 /* Cancel prefix changes. */
1997 pDis->fPrefix &= ~DISPREFIX_REPNE;
1998 }
1999 }
2000 break;
2001 }
2002
2003 return disParseInstruction(offInstr, pOpcode, pDis);
2004}
2005//*****************************************************************************
2006//*****************************************************************************
2007static size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2008{
2009 NOREF(pOp); NOREF(pParam);
2010
2011 /* 3rd byte */
2012 pDis->bOpCode = disReadByte(pDis, offInstr);
2013 offInstr++;
2014
2015 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
2016 Assert(pDis->bLastPrefix == OP_OPSIZE);
2017
2018 /* default to the non-prefixed table. */
2019 PCDISOPCODE pOpcode;
2020 if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
2021 {
2022 pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
2023 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2024
2025 if (pOpcode->uOpcode != OP_INVALID)
2026 {
2027 /* Table entry is valid, so use the extension table. */
2028
2029 /* Cancel prefix changes. */
2030 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
2031 pDis->uOpMode = pDis->uCpuMode;
2032 }
2033 }
2034 else
2035 pOpcode = &g_InvalidOpcode[0];
2036
2037 return disParseInstruction(offInstr, pOpcode, pDis);
2038}
2039//*****************************************************************************
2040//*****************************************************************************
2041static size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2042{
2043 NOREF(pParam);
2044
2045 if (pDis->fPrefix & DISPREFIX_REP)
2046 {
2047 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
2048 pDis->fPrefix &= ~DISPREFIX_REP;
2049 }
2050 else
2051 pOp = &g_aMapX86_NopPause[0]; /* NOP */
2052
2053 return disParseInstruction(offInstr, pOp, pDis);
2054}
2055//*****************************************************************************
2056//*****************************************************************************
2057static size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2058{
2059 NOREF(pParam);
2060
2061 uint8_t modrm = disReadByte(pDis, offInstr);
2062 uint8_t reg = MODRM_REG(modrm);
2063 unsigned idx = (pDis->bOpCode - 0x80) * 8;
2064
2065 pOp = &g_aMapX86_Group1[idx+reg];
2066
2067 return disParseInstruction(offInstr, pOp, pDis);
2068}
2069//*****************************************************************************
2070//*****************************************************************************
2071static size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2072{
2073 NOREF(pParam);
2074
2075 unsigned idx;
2076 switch (pDis->bOpCode)
2077 {
2078 case 0xC0:
2079 case 0xC1:
2080 idx = (pDis->bOpCode - 0xC0)*8;
2081 break;
2082
2083 case 0xD0:
2084 case 0xD1:
2085 case 0xD2:
2086 case 0xD3:
2087 idx = (pDis->bOpCode - 0xD0 + 2)*8;
2088 break;
2089
2090 default:
2091 Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
2092 pDis->rc = VERR_DIS_INVALID_OPCODE;
2093 return offInstr;
2094 }
2095
2096 uint8_t modrm = disReadByte(pDis, offInstr);
2097 uint8_t reg = MODRM_REG(modrm);
2098
2099 pOp = &g_aMapX86_Group2[idx+reg];
2100
2101 return disParseInstruction(offInstr, pOp, pDis);
2102}
2103//*****************************************************************************
2104//*****************************************************************************
2105static size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2106{
2107 unsigned idx = (pDis->bOpCode - 0xF6) * 8;
2108 NOREF(pParam);
2109
2110 uint8_t modrm = disReadByte(pDis, offInstr);
2111 uint8_t reg = MODRM_REG(modrm);
2112
2113 pOp = &g_aMapX86_Group3[idx+reg];
2114
2115 return disParseInstruction(offInstr, pOp, pDis);
2116}
2117//*****************************************************************************
2118//*****************************************************************************
2119static size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2120{
2121 NOREF(pParam);
2122
2123 uint8_t modrm = disReadByte(pDis, offInstr);
2124 uint8_t reg = MODRM_REG(modrm);
2125
2126 pOp = &g_aMapX86_Group4[reg];
2127
2128 return disParseInstruction(offInstr, pOp, pDis);
2129}
2130//*****************************************************************************
2131//*****************************************************************************
2132static size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2133{
2134 NOREF(pParam);
2135
2136 uint8_t modrm = disReadByte(pDis, offInstr);
2137 uint8_t reg = MODRM_REG(modrm);
2138
2139 pOp = &g_aMapX86_Group5[reg];
2140
2141 return disParseInstruction(offInstr, pOp, pDis);
2142}
2143//*****************************************************************************
2144// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
2145// It would appear the ModRM byte must always be present. How else can you
2146// determine the offset of the imm8_opcode byte otherwise?
2147//
2148//*****************************************************************************
2149static size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2150{
2151 /** @todo This code needs testing! Esp. wrt invalid opcodes. */
2152
2153 uint8_t ModRM = disReadByte(pDis, offInstr);
2154 pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
2155 pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
2156 pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
2157
2158 size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
2159
2160 uint8_t opcode = disReadByte(pDis, offRet);
2161 offRet++;
2162 pOp = &g_aTwoByteMapX86_3DNow[opcode];
2163
2164 size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
2165
2166 AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
2167 ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
2168 NOREF(offStrict);
2169
2170 return offRet;
2171}
2172//*****************************************************************************
2173//*****************************************************************************
2174static size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2175{
2176 NOREF(pParam);
2177
2178 uint8_t modrm = disReadByte(pDis, offInstr);
2179 uint8_t reg = MODRM_REG(modrm);
2180
2181 pOp = &g_aMapX86_Group6[reg];
2182
2183 return disParseInstruction(offInstr, pOp, pDis);
2184}
2185//*****************************************************************************
2186//*****************************************************************************
2187static size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2188{
2189 NOREF(pParam);
2190
2191 uint8_t modrm = disReadByte(pDis, offInstr);
2192 uint8_t mod = MODRM_MOD(modrm);
2193 uint8_t reg = MODRM_REG(modrm);
2194 uint8_t rm = MODRM_RM(modrm);
2195
2196 if (mod == 3 && rm == 0)
2197 pOp = &g_aMapX86_Group7_mod11_rm000[reg];
2198 else
2199 if (mod == 3 && rm == 1)
2200 pOp = &g_aMapX86_Group7_mod11_rm001[reg];
2201 else
2202 pOp = &g_aMapX86_Group7_mem[reg];
2203
2204 /* Cannot easily skip this hack because of monitor and vmcall! */
2205 //little hack to make sure the ModRM byte is included in the returned size
2206 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2207 offInstr++;
2208
2209 return disParseInstruction(offInstr, pOp, pDis);
2210}
2211//*****************************************************************************
2212//*****************************************************************************
2213static size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2214{
2215 NOREF(pParam);
2216
2217 uint8_t modrm = disReadByte(pDis, offInstr);
2218 uint8_t reg = MODRM_REG(modrm);
2219
2220 pOp = &g_aMapX86_Group8[reg];
2221
2222 return disParseInstruction(offInstr, pOp, pDis);
2223}
2224//*****************************************************************************
2225//*****************************************************************************
2226static size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2227{
2228 NOREF(pParam);
2229
2230 uint8_t modrm = disReadByte(pDis, offInstr);
2231 uint8_t reg = MODRM_REG(modrm);
2232
2233 pOp = &g_aMapX86_Group9[reg];
2234
2235 return disParseInstruction(offInstr, pOp, pDis);
2236}
2237//*****************************************************************************
2238//*****************************************************************************
2239static size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2240{
2241 NOREF(pParam);
2242
2243 uint8_t modrm = disReadByte(pDis, offInstr);
2244 uint8_t reg = MODRM_REG(modrm);
2245
2246 pOp = &g_aMapX86_Group10[reg];
2247
2248 return disParseInstruction(offInstr, pOp, pDis);
2249}
2250//*****************************************************************************
2251//*****************************************************************************
2252static size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2253{
2254 NOREF(pParam);
2255
2256 uint8_t modrm = disReadByte(pDis, offInstr);
2257 uint8_t reg = MODRM_REG(modrm);
2258
2259 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2260 reg += 8; /* 2nd table */
2261
2262 pOp = &g_aMapX86_Group12[reg];
2263
2264 return disParseInstruction(offInstr, pOp, pDis);
2265}
2266//*****************************************************************************
2267//*****************************************************************************
2268static size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2269{
2270 NOREF(pParam);
2271
2272 uint8_t modrm = disReadByte(pDis, offInstr);
2273 uint8_t reg = MODRM_REG(modrm);
2274 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2275 reg += 8; /* 2nd table */
2276
2277 pOp = &g_aMapX86_Group13[reg];
2278
2279 return disParseInstruction(offInstr, pOp, pDis);
2280}
2281//*****************************************************************************
2282//*****************************************************************************
2283static size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2284{
2285 NOREF(pParam);
2286
2287 uint8_t modrm = disReadByte(pDis, offInstr);
2288 uint8_t reg = MODRM_REG(modrm);
2289 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2290 reg += 8; /* 2nd table */
2291
2292 pOp = &g_aMapX86_Group14[reg];
2293
2294 return disParseInstruction(offInstr, pOp, pDis);
2295}
2296//*****************************************************************************
2297//*****************************************************************************
2298static size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2299{
2300 NOREF(pParam);
2301
2302 uint8_t modrm = disReadByte(pDis, offInstr);
2303 uint8_t mod = MODRM_MOD(modrm);
2304 uint8_t reg = MODRM_REG(modrm);
2305 uint8_t rm = MODRM_RM(modrm);
2306
2307 if (mod == 3 && rm == 0)
2308 pOp = &g_aMapX86_Group15_mod11_rm000[reg];
2309 else
2310 pOp = &g_aMapX86_Group15_mem[reg];
2311
2312 return disParseInstruction(offInstr, pOp, pDis);
2313}
2314//*****************************************************************************
2315//*****************************************************************************
2316static size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2317{
2318 NOREF(pParam);
2319
2320 uint8_t modrm = disReadByte(pDis, offInstr);
2321 pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
2322
2323 return disParseInstruction(offInstr, pOp, pDis);
2324}
2325
2326
2327
2328/**
2329 * Validates the lock sequence.
2330 *
2331 * The AMD manual lists the following instructions:
2332 * ADC
2333 * ADD
2334 * AND
2335 * BTC
2336 * BTR
2337 * BTS
2338 * CMPXCHG
2339 * CMPXCHG8B
2340 * CMPXCHG16B
2341 * DEC
2342 * INC
2343 * NEG
2344 * NOT
2345 * OR
2346 * SBB
2347 * SUB
2348 * XADD
2349 * XCHG
2350 * XOR
2351 *
2352 * @param pDis Fully disassembled instruction.
2353 */
2354static void disValidateLockSequence(PDISSTATE pDis)
2355{
2356 Assert(pDis->fPrefix & DISPREFIX_LOCK);
2357
2358 /*
2359 * Filter out the valid lock sequences.
2360 */
2361 switch (pDis->pCurInstr->uOpcode)
2362 {
2363 /* simple: no variations */
2364 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2365 return;
2366
2367 /* simple: /r - reject register destination. */
2368 case OP_BTC:
2369 case OP_BTR:
2370 case OP_BTS:
2371 case OP_CMPXCHG:
2372 case OP_XADD:
2373 if (pDis->ModRM.Bits.Mod == 3)
2374 break;
2375 return;
2376
2377 /*
2378 * Lots of variants but its sufficient to check that param 1
2379 * is a memory operand.
2380 */
2381 case OP_ADC:
2382 case OP_ADD:
2383 case OP_AND:
2384 case OP_DEC:
2385 case OP_INC:
2386 case OP_NEG:
2387 case OP_NOT:
2388 case OP_OR:
2389 case OP_SBB:
2390 case OP_SUB:
2391 case OP_XCHG:
2392 case OP_XOR:
2393 if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
2394 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
2395 return;
2396 break;
2397
2398 default:
2399 break;
2400 }
2401
2402 /*
2403 * Invalid lock sequence, make it a OP_ILLUD2.
2404 */
2405 pDis->pCurInstr = &g_aTwoByteMapX86[11];
2406 Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
2407}
2408
2409
2410/**
2411 * Internal worker for DISInstrEx and DISInstrWithPrefetchedBytes.
2412 *
2413 * @returns VBox status code.
2414 * @param pDis Initialized disassembler state.
2415 * @param paOneByteMap The one byte opcode map to use.
2416 * @param pcbInstr Where to store the instruction size. Can be NULL.
2417 */
2418static int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
2419{
2420 /*
2421 * Parse byte by byte.
2422 */
2423 size_t offInstr = 0;
2424 for (;;)
2425 {
2426 uint8_t codebyte = disReadByte(pDis, offInstr++);
2427 uint8_t opcode = paOneByteMap[codebyte].uOpcode;
2428
2429 /* Hardcoded assumption about OP_* values!! */
2430 if (opcode <= OP_LAST_PREFIX)
2431 {
2432 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
2433 if (opcode != OP_REX)
2434 {
2435 /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
2436 pDis->bLastPrefix = opcode;
2437 pDis->fPrefix &= ~DISPREFIX_REX;
2438 }
2439
2440 switch (opcode)
2441 {
2442 case OP_INVALID:
2443 if (pcbInstr)
2444 *pcbInstr = (uint32_t)offInstr;
2445 return pDis->rc = VERR_DIS_INVALID_OPCODE;
2446
2447 // segment override prefix byte
2448 case OP_SEG:
2449 pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
2450#if 0 /* Try be accurate in our reporting, shouldn't break anything... :-) */
2451 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
2452 if ( pDis->uCpuMode != DISCPUMODE_64BIT
2453 || pDis->idxSegPrefix >= DISSELREG_FS)
2454 pDis->fPrefix |= DISPREFIX_SEG;
2455#else
2456 pDis->fPrefix |= DISPREFIX_SEG;
2457#endif
2458 continue; //fetch the next byte
2459
2460 // lock prefix byte
2461 case OP_LOCK:
2462 pDis->fPrefix |= DISPREFIX_LOCK;
2463 continue; //fetch the next byte
2464
2465 // address size override prefix byte
2466 case OP_ADDRSIZE:
2467 pDis->fPrefix |= DISPREFIX_ADDRSIZE;
2468 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2469 pDis->uAddrMode = DISCPUMODE_32BIT;
2470 else
2471 if (pDis->uCpuMode == DISCPUMODE_32BIT)
2472 pDis->uAddrMode = DISCPUMODE_16BIT;
2473 else
2474 pDis->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
2475 continue; //fetch the next byte
2476
2477 // operand size override prefix byte
2478 case OP_OPSIZE:
2479 pDis->fPrefix |= DISPREFIX_OPSIZE;
2480 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2481 pDis->uOpMode = DISCPUMODE_32BIT;
2482 else
2483 pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2484 continue; //fetch the next byte
2485
2486 // rep and repne are not really prefixes, but we'll treat them as such
2487 case OP_REPE:
2488 pDis->fPrefix |= DISPREFIX_REP;
2489 continue; //fetch the next byte
2490
2491 case OP_REPNE:
2492 pDis->fPrefix |= DISPREFIX_REPNE;
2493 continue; //fetch the next byte
2494
2495 case OP_REX:
2496 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
2497 /* REX prefix byte */
2498 pDis->fPrefix |= DISPREFIX_REX;
2499 pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
2500 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
2501 pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
2502 continue; //fetch the next byte
2503 }
2504 }
2505
2506 /* first opcode byte. */
2507 pDis->bOpCode = codebyte;
2508 pDis->cbPrefix = (uint8_t)offInstr - 1;
2509 offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
2510 break;
2511 }
2512
2513 pDis->cbInstr = (uint8_t)offInstr;
2514 if (pcbInstr)
2515 *pcbInstr = (uint32_t)offInstr;
2516
2517 if (pDis->fPrefix & DISPREFIX_LOCK)
2518 disValidateLockSequence(pDis);
2519
2520 return pDis->rc;
2521}
2522
2523
2524/**
2525 * Inlined worker that initializes the disassembler state.
2526 *
2527 * @returns The primary opcode map to use.
2528 * @param pDis The disassembler state.
2529 * @param uInstrAddr The instruction address.
2530 * @param enmCpuMode The CPU mode.
2531 * @param fFilter The instruction filter settings.
2532 * @param pfnReadBytes The byte reader, can be NULL.
2533 * @param pvUser The the user data for the reader.
2534 */
2535DECL_FORCE_INLINE(PCDISOPCODE)
2536disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2537 PFNDISREADBYTES pfnReadBytes, void *pvUser)
2538{
2539 RT_ZERO(*pDis);
2540
2541#ifdef VBOX_STRICT /* poison */
2542 pDis->Param1.Base.idxGenReg = 0xc1;
2543 pDis->Param2.Base.idxGenReg = 0xc2;
2544 pDis->Param3.Base.idxGenReg = 0xc3;
2545 pDis->Param1.Index.idxGenReg = 0xc4;
2546 pDis->Param2.Index.idxGenReg = 0xc5;
2547 pDis->Param3.Index.idxGenReg = 0xc6;
2548 pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
2549 pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
2550 pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
2551 pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
2552 pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
2553 pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
2554 pDis->Param1.uScale = 28;
2555 pDis->Param2.uScale = 29;
2556 pDis->Param3.uScale = 30;
2557#endif
2558
2559 pDis->fPrefix = DISPREFIX_NONE;
2560 pDis->idxSegPrefix = DISSELREG_DS;
2561 pDis->rc = VINF_SUCCESS;
2562 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
2563
2564 pDis->uInstrAddr = uInstrAddr;
2565 pDis->fFilter = fFilter;
2566 pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
2567 pDis->pvUser = pvUser;
2568 pDis->uCpuMode = enmCpuMode;
2569 PCDISOPCODE paOneByteMap;
2570 if (enmCpuMode == DISCPUMODE_64BIT)
2571 {
2572 pDis->uAddrMode = DISCPUMODE_64BIT;
2573 pDis->uOpMode = DISCPUMODE_32BIT;
2574 paOneByteMap = g_aOneByteMapX64;
2575 }
2576 else
2577 {
2578 pDis->uAddrMode = enmCpuMode;
2579 pDis->uOpMode = enmCpuMode;
2580 paOneByteMap = g_aOneByteMapX86;
2581 }
2582 return paOneByteMap;
2583}
2584
2585
2586/**
2587 * Reads some bytes into the cache.
2588 *
2589 * While this will set DISSTATE::rc on failure, the caller should disregard
2590 * this since that is what would happen if we didn't prefetch bytes prior to the
2591 * instruction parsing.
2592 *
2593 * @param pDis The disassembler state.
2594 */
2595DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
2596{
2597 /*
2598 * Read some bytes into the cache. (If this fail we continue as nothing
2599 * has gone wrong since this is what would happen if we didn't precharge
2600 * the cache here.)
2601 */
2602 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
2603 if (RT_SUCCESS(rc))
2604 {
2605 Assert(pDis->cbCachedInstr >= 1);
2606 Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
2607 }
2608 else
2609 {
2610 Log(("Initial read failed with rc=%Rrc!!\n", rc));
2611 pDis->rc = rc;
2612 }
2613}
2614
2615
2616/**
2617 * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
2618 *
2619 * @returns VBox status code.
2620 * @param uInstrAddr Address of the instruction to decode. What this means
2621 * is left to the pfnReadBytes function.
2622 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2623 * @param pfnReadBytes Callback for reading instruction bytes.
2624 * @param fFilter Instruction type filter.
2625 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2626 * @param pDis Pointer to disassembler state (output).
2627 * @param pcbInstr Where to store the size of the instruction. (This
2628 * is also stored in PDISSTATE::cbInstr.) Optional.
2629 */
2630DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2631 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2632 PDISSTATE pDis, uint32_t *pcbInstr)
2633{
2634
2635 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2636 disPrefetchBytes(pDis);
2637 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2638}
2639
2640
2641/**
2642 * Disassembles on instruction partially or fully from prefetched bytes, details
2643 * in @a pDis and length in @a pcbInstr.
2644 *
2645 * @returns VBox status code.
2646 * @param uInstrAddr Address of the instruction to decode. What this means
2647 * is left to the pfnReadBytes function.
2648 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2649 * @param pvPrefetched Pointer to the prefetched bytes.
2650 * @param cbPrefetched The number of valid bytes pointed to by @a
2651 * pbPrefetched.
2652 * @param pfnReadBytes Callback for reading instruction bytes.
2653 * @param fFilter Instruction type filter.
2654 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2655 * @param pDis Pointer to disassembler state (output).
2656 * @param pcbInstr Where to store the size of the instruction. (This
2657 * is also stored in PDISSTATE::cbInstr.) Optional.
2658 */
2659DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2660 void const *pvPrefetched, size_t cbPretched,
2661 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2662 PDISSTATE pDis, uint32_t *pcbInstr)
2663{
2664 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2665
2666 if (!cbPretched)
2667 disPrefetchBytes(pDis);
2668 else
2669 {
2670 if (cbPretched >= sizeof(pDis->abInstr))
2671 {
2672 memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
2673 pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
2674 }
2675 else
2676 {
2677 memcpy(pDis->abInstr, pvPrefetched, cbPretched);
2678 pDis->cbCachedInstr = (uint8_t)cbPretched;
2679 }
2680 }
2681
2682 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2683}
2684
2685
2686
2687/**
2688 * Parses one guest instruction.
2689 *
2690 * The result is found in pDis and pcbInstr.
2691 *
2692 * @returns VBox status code.
2693 * @param uInstrAddr Address of the instruction to decode. What this means
2694 * is left to the pfnReadBytes function.
2695 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2696 * @param pfnReadBytes Callback for reading instruction bytes.
2697 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2698 * @param pDis Pointer to disassembler state (output).
2699 * @param pcbInstr Where to store the size of the instruction.
2700 * NULL is allowed. This is also stored in
2701 * PDISSTATE::cbInstr.
2702 */
2703DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
2704 PDISSTATE pDis, uint32_t *pcbInstr)
2705{
2706 return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
2707}
2708
2709
2710/**
2711 * Parses one guest instruction.
2712 *
2713 * The result is found in pDis and pcbInstr.
2714 *
2715 * @returns VBox status code.
2716 * @param pvInstr Address of the instruction to decode. This is a
2717 * real address in the current context that can be
2718 * accessed without faulting. (Consider
2719 * DISInstrWithReader if this isn't the case.)
2720 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2721 * @param pfnReadBytes Callback for reading instruction bytes.
2722 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2723 * @param pDis Pointer to disassembler state (output).
2724 * @param pcbInstr Where to store the size of the instruction.
2725 * NULL is allowed. This is also stored in
2726 * PDISSTATE::cbInstr.
2727 */
2728DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
2729{
2730 return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);
2731}
2732
Note: See TracBrowser for help on using the repository browser.

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