VirtualBox

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

Last change on this file since 46168 was 45428, checked in by vboxsync, 12 years ago

VMM: Propagate errors from PGM through the disassembler. Get rid of VERR_EM_INTERNAL_DISAS_ERROR and dependents.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 92.8 KB
Line 
1/* $Id: DisasmCore.cpp 45428 2013-04-09 12:32:35Z 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
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
2165 AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
2166 ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
2167 NOREF(offStrict);
2168
2169 return offRet;
2170}
2171//*****************************************************************************
2172//*****************************************************************************
2173static size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2174{
2175 NOREF(pParam);
2176
2177 uint8_t modrm = disReadByte(pDis, offInstr);
2178 uint8_t reg = MODRM_REG(modrm);
2179
2180 pOp = &g_aMapX86_Group6[reg];
2181
2182 return disParseInstruction(offInstr, pOp, pDis);
2183}
2184//*****************************************************************************
2185//*****************************************************************************
2186static size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2187{
2188 NOREF(pParam);
2189
2190 uint8_t modrm = disReadByte(pDis, offInstr);
2191 uint8_t mod = MODRM_MOD(modrm);
2192 uint8_t reg = MODRM_REG(modrm);
2193 uint8_t rm = MODRM_RM(modrm);
2194
2195 if (mod == 3 && rm == 0)
2196 pOp = &g_aMapX86_Group7_mod11_rm000[reg];
2197 else
2198 if (mod == 3 && rm == 1)
2199 pOp = &g_aMapX86_Group7_mod11_rm001[reg];
2200 else
2201 pOp = &g_aMapX86_Group7_mem[reg];
2202
2203 /* Cannot easily skip this hack because of monitor and vmcall! */
2204 //little hack to make sure the ModRM byte is included in the returned size
2205 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2206 offInstr++;
2207
2208 return disParseInstruction(offInstr, pOp, pDis);
2209}
2210//*****************************************************************************
2211//*****************************************************************************
2212static size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2213{
2214 NOREF(pParam);
2215
2216 uint8_t modrm = disReadByte(pDis, offInstr);
2217 uint8_t reg = MODRM_REG(modrm);
2218
2219 pOp = &g_aMapX86_Group8[reg];
2220
2221 return disParseInstruction(offInstr, pOp, pDis);
2222}
2223//*****************************************************************************
2224//*****************************************************************************
2225static size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2226{
2227 NOREF(pParam);
2228
2229 uint8_t modrm = disReadByte(pDis, offInstr);
2230 uint8_t reg = MODRM_REG(modrm);
2231
2232 pOp = &g_aMapX86_Group9[reg];
2233
2234 return disParseInstruction(offInstr, pOp, pDis);
2235}
2236//*****************************************************************************
2237//*****************************************************************************
2238static size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2239{
2240 NOREF(pParam);
2241
2242 uint8_t modrm = disReadByte(pDis, offInstr);
2243 uint8_t reg = MODRM_REG(modrm);
2244
2245 pOp = &g_aMapX86_Group10[reg];
2246
2247 return disParseInstruction(offInstr, pOp, pDis);
2248}
2249//*****************************************************************************
2250//*****************************************************************************
2251static size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2252{
2253 NOREF(pParam);
2254
2255 uint8_t modrm = disReadByte(pDis, offInstr);
2256 uint8_t reg = MODRM_REG(modrm);
2257
2258 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2259 reg += 8; /* 2nd table */
2260
2261 pOp = &g_aMapX86_Group12[reg];
2262
2263 return disParseInstruction(offInstr, pOp, pDis);
2264}
2265//*****************************************************************************
2266//*****************************************************************************
2267static size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2268{
2269 NOREF(pParam);
2270
2271 uint8_t modrm = disReadByte(pDis, offInstr);
2272 uint8_t reg = MODRM_REG(modrm);
2273 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2274 reg += 8; /* 2nd table */
2275
2276 pOp = &g_aMapX86_Group13[reg];
2277
2278 return disParseInstruction(offInstr, pOp, pDis);
2279}
2280//*****************************************************************************
2281//*****************************************************************************
2282static size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2283{
2284 NOREF(pParam);
2285
2286 uint8_t modrm = disReadByte(pDis, offInstr);
2287 uint8_t reg = MODRM_REG(modrm);
2288 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2289 reg += 8; /* 2nd table */
2290
2291 pOp = &g_aMapX86_Group14[reg];
2292
2293 return disParseInstruction(offInstr, pOp, pDis);
2294}
2295//*****************************************************************************
2296//*****************************************************************************
2297static size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2298{
2299 NOREF(pParam);
2300
2301 uint8_t modrm = disReadByte(pDis, offInstr);
2302 uint8_t mod = MODRM_MOD(modrm);
2303 uint8_t reg = MODRM_REG(modrm);
2304 uint8_t rm = MODRM_RM(modrm);
2305
2306 if (mod == 3 && rm == 0)
2307 pOp = &g_aMapX86_Group15_mod11_rm000[reg];
2308 else
2309 pOp = &g_aMapX86_Group15_mem[reg];
2310
2311 return disParseInstruction(offInstr, pOp, pDis);
2312}
2313//*****************************************************************************
2314//*****************************************************************************
2315static size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2316{
2317 NOREF(pParam);
2318
2319 uint8_t modrm = disReadByte(pDis, offInstr);
2320 pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
2321
2322 return disParseInstruction(offInstr, pOp, pDis);
2323}
2324
2325
2326
2327/**
2328 * Validates the lock sequence.
2329 *
2330 * The AMD manual lists the following instructions:
2331 * ADC
2332 * ADD
2333 * AND
2334 * BTC
2335 * BTR
2336 * BTS
2337 * CMPXCHG
2338 * CMPXCHG8B
2339 * CMPXCHG16B
2340 * DEC
2341 * INC
2342 * NEG
2343 * NOT
2344 * OR
2345 * SBB
2346 * SUB
2347 * XADD
2348 * XCHG
2349 * XOR
2350 *
2351 * @param pDis Fully disassembled instruction.
2352 */
2353static void disValidateLockSequence(PDISSTATE pDis)
2354{
2355 Assert(pDis->fPrefix & DISPREFIX_LOCK);
2356
2357 /*
2358 * Filter out the valid lock sequences.
2359 */
2360 switch (pDis->pCurInstr->uOpcode)
2361 {
2362 /* simple: no variations */
2363 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2364 return;
2365
2366 /* simple: /r - reject register destination. */
2367 case OP_BTC:
2368 case OP_BTR:
2369 case OP_BTS:
2370 case OP_CMPXCHG:
2371 case OP_XADD:
2372 if (pDis->ModRM.Bits.Mod == 3)
2373 break;
2374 return;
2375
2376 /*
2377 * Lots of variants but its sufficient to check that param 1
2378 * is a memory operand.
2379 */
2380 case OP_ADC:
2381 case OP_ADD:
2382 case OP_AND:
2383 case OP_DEC:
2384 case OP_INC:
2385 case OP_NEG:
2386 case OP_NOT:
2387 case OP_OR:
2388 case OP_SBB:
2389 case OP_SUB:
2390 case OP_XCHG:
2391 case OP_XOR:
2392 if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
2393 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
2394 return;
2395 break;
2396
2397 default:
2398 break;
2399 }
2400
2401 /*
2402 * Invalid lock sequence, make it a OP_ILLUD2.
2403 */
2404 pDis->pCurInstr = &g_aTwoByteMapX86[11];
2405 Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
2406}
2407
2408
2409/**
2410 * Internal worker for DISInstrEx and DISInstrWithPrefetchedBytes.
2411 *
2412 * @returns VBox status code.
2413 * @param pDis Initialized disassembler state.
2414 * @param paOneByteMap The one byte opcode map to use.
2415 * @param pcbInstr Where to store the instruction size. Can be NULL.
2416 */
2417static int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
2418{
2419 /*
2420 * Parse byte by byte.
2421 */
2422 size_t offInstr = 0;
2423 for (;;)
2424 {
2425 uint8_t codebyte = disReadByte(pDis, offInstr++);
2426 uint8_t opcode = paOneByteMap[codebyte].uOpcode;
2427
2428 /* Hardcoded assumption about OP_* values!! */
2429 if (opcode <= OP_LAST_PREFIX)
2430 {
2431 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
2432 if (opcode != OP_REX)
2433 {
2434 /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
2435 pDis->bLastPrefix = opcode;
2436 pDis->fPrefix &= ~DISPREFIX_REX;
2437 }
2438
2439 switch (opcode)
2440 {
2441 case OP_INVALID:
2442 if (pcbInstr)
2443 *pcbInstr = (uint32_t)offInstr;
2444 return pDis->rc = VERR_DIS_INVALID_OPCODE;
2445
2446 // segment override prefix byte
2447 case OP_SEG:
2448 pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
2449#if 0 /* Try be accurate in our reporting, shouldn't break anything... :-) */
2450 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
2451 if ( pDis->uCpuMode != DISCPUMODE_64BIT
2452 || pDis->idxSegPrefix >= DISSELREG_FS)
2453 pDis->fPrefix |= DISPREFIX_SEG;
2454#else
2455 pDis->fPrefix |= DISPREFIX_SEG;
2456#endif
2457 continue; //fetch the next byte
2458
2459 // lock prefix byte
2460 case OP_LOCK:
2461 pDis->fPrefix |= DISPREFIX_LOCK;
2462 continue; //fetch the next byte
2463
2464 // address size override prefix byte
2465 case OP_ADDRSIZE:
2466 pDis->fPrefix |= DISPREFIX_ADDRSIZE;
2467 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2468 pDis->uAddrMode = DISCPUMODE_32BIT;
2469 else
2470 if (pDis->uCpuMode == DISCPUMODE_32BIT)
2471 pDis->uAddrMode = DISCPUMODE_16BIT;
2472 else
2473 pDis->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
2474 continue; //fetch the next byte
2475
2476 // operand size override prefix byte
2477 case OP_OPSIZE:
2478 pDis->fPrefix |= DISPREFIX_OPSIZE;
2479 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2480 pDis->uOpMode = DISCPUMODE_32BIT;
2481 else
2482 pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2483 continue; //fetch the next byte
2484
2485 // rep and repne are not really prefixes, but we'll treat them as such
2486 case OP_REPE:
2487 pDis->fPrefix |= DISPREFIX_REP;
2488 continue; //fetch the next byte
2489
2490 case OP_REPNE:
2491 pDis->fPrefix |= DISPREFIX_REPNE;
2492 continue; //fetch the next byte
2493
2494 case OP_REX:
2495 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
2496 /* REX prefix byte */
2497 pDis->fPrefix |= DISPREFIX_REX;
2498 pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
2499 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
2500 pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
2501 continue; //fetch the next byte
2502 }
2503 }
2504
2505 /* first opcode byte. */
2506 pDis->bOpCode = codebyte;
2507 pDis->cbPrefix = (uint8_t)offInstr - 1;
2508 offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
2509 break;
2510 }
2511
2512 pDis->cbInstr = (uint8_t)offInstr;
2513 if (pcbInstr)
2514 *pcbInstr = (uint32_t)offInstr;
2515
2516 if (pDis->fPrefix & DISPREFIX_LOCK)
2517 disValidateLockSequence(pDis);
2518
2519 return pDis->rc;
2520}
2521
2522
2523/**
2524 * Inlined worker that initializes the disassembler state.
2525 *
2526 * @returns The primary opcode map to use.
2527 * @param pDis The disassembler state.
2528 * @param uInstrAddr The instruction address.
2529 * @param enmCpuMode The CPU mode.
2530 * @param fFilter The instruction filter settings.
2531 * @param pfnReadBytes The byte reader, can be NULL.
2532 * @param pvUser The the user data for the reader.
2533 */
2534DECL_FORCE_INLINE(PCDISOPCODE)
2535disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2536 PFNDISREADBYTES pfnReadBytes, void *pvUser)
2537{
2538 RT_ZERO(*pDis);
2539
2540#ifdef VBOX_STRICT /* poison */
2541 pDis->Param1.Base.idxGenReg = 0xc1;
2542 pDis->Param2.Base.idxGenReg = 0xc2;
2543 pDis->Param3.Base.idxGenReg = 0xc3;
2544 pDis->Param1.Index.idxGenReg = 0xc4;
2545 pDis->Param2.Index.idxGenReg = 0xc5;
2546 pDis->Param3.Index.idxGenReg = 0xc6;
2547 pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
2548 pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
2549 pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
2550 pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
2551 pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
2552 pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
2553 pDis->Param1.uScale = 28;
2554 pDis->Param2.uScale = 29;
2555 pDis->Param3.uScale = 30;
2556#endif
2557
2558 pDis->fPrefix = DISPREFIX_NONE;
2559 pDis->idxSegPrefix = DISSELREG_DS;
2560 pDis->rc = VINF_SUCCESS;
2561 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
2562
2563 pDis->uInstrAddr = uInstrAddr;
2564 pDis->fFilter = fFilter;
2565 pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
2566 pDis->pvUser = pvUser;
2567 pDis->uCpuMode = enmCpuMode;
2568 PCDISOPCODE paOneByteMap;
2569 if (enmCpuMode == DISCPUMODE_64BIT)
2570 {
2571 pDis->uAddrMode = DISCPUMODE_64BIT;
2572 pDis->uOpMode = DISCPUMODE_32BIT;
2573 paOneByteMap = g_aOneByteMapX64;
2574 }
2575 else
2576 {
2577 pDis->uAddrMode = enmCpuMode;
2578 pDis->uOpMode = enmCpuMode;
2579 paOneByteMap = g_aOneByteMapX86;
2580 }
2581 return paOneByteMap;
2582}
2583
2584
2585/**
2586 * Reads some bytes into the cache.
2587 *
2588 * While this will set DISSTATE::rc on failure, the caller should disregard
2589 * this since that is what would happen if we didn't prefetch bytes prior to the
2590 * instruction parsing.
2591 *
2592 * @param pDis The disassembler state.
2593 */
2594DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
2595{
2596 /*
2597 * Read some bytes into the cache. (If this fail we continue as nothing
2598 * has gone wrong since this is what would happen if we didn't precharge
2599 * the cache here.)
2600 */
2601 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
2602 if (RT_SUCCESS(rc))
2603 {
2604 Assert(pDis->cbCachedInstr >= 1);
2605 Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
2606 }
2607 else
2608 {
2609 Log(("Initial read failed with rc=%Rrc!!\n", rc));
2610 pDis->rc = rc;
2611 }
2612}
2613
2614
2615/**
2616 * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
2617 *
2618 * @returns VBox status code.
2619 * @param uInstrAddr Address of the instruction to decode. What this means
2620 * is left to the pfnReadBytes function.
2621 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2622 * @param pfnReadBytes Callback for reading instruction bytes.
2623 * @param fFilter Instruction type filter.
2624 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2625 * @param pDis Pointer to disassembler state (output).
2626 * @param pcbInstr Where to store the size of the instruction. (This
2627 * is also stored in PDISSTATE::cbInstr.) Optional.
2628 */
2629DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2630 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2631 PDISSTATE pDis, uint32_t *pcbInstr)
2632{
2633
2634 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2635 disPrefetchBytes(pDis);
2636 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2637}
2638
2639
2640/**
2641 * Disassembles on instruction partially or fully from prefetched bytes, details
2642 * in @a pDis and length in @a pcbInstr.
2643 *
2644 * @returns VBox status code.
2645 * @param uInstrAddr Address of the instruction to decode. What this means
2646 * is left to the pfnReadBytes function.
2647 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2648 * @param pvPrefetched Pointer to the prefetched bytes.
2649 * @param cbPrefetched The number of valid bytes pointed to by @a
2650 * pbPrefetched.
2651 * @param pfnReadBytes Callback for reading instruction bytes.
2652 * @param fFilter Instruction type filter.
2653 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2654 * @param pDis Pointer to disassembler state (output).
2655 * @param pcbInstr Where to store the size of the instruction. (This
2656 * is also stored in PDISSTATE::cbInstr.) Optional.
2657 */
2658DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2659 void const *pvPrefetched, size_t cbPretched,
2660 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2661 PDISSTATE pDis, uint32_t *pcbInstr)
2662{
2663 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2664
2665 if (!cbPretched)
2666 disPrefetchBytes(pDis);
2667 else
2668 {
2669 if (cbPretched >= sizeof(pDis->abInstr))
2670 {
2671 memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
2672 pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
2673 }
2674 else
2675 {
2676 memcpy(pDis->abInstr, pvPrefetched, cbPretched);
2677 pDis->cbCachedInstr = (uint8_t)cbPretched;
2678 }
2679 }
2680
2681 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2682}
2683
2684
2685
2686/**
2687 * Parses one guest instruction.
2688 *
2689 * The result is found in pDis and pcbInstr.
2690 *
2691 * @returns VBox status code.
2692 * @param uInstrAddr Address of the instruction to decode. What this means
2693 * is left to the pfnReadBytes function.
2694 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2695 * @param pfnReadBytes Callback for reading instruction bytes.
2696 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2697 * @param pDis Pointer to disassembler state (output).
2698 * @param pcbInstr Where to store the size of the instruction.
2699 * NULL is allowed. This is also stored in
2700 * PDISSTATE::cbInstr.
2701 */
2702DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
2703 PDISSTATE pDis, uint32_t *pcbInstr)
2704{
2705 return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
2706}
2707
2708
2709/**
2710 * Parses one guest instruction.
2711 *
2712 * The result is found in pDis and pcbInstr.
2713 *
2714 * @returns VBox status code.
2715 * @param pvInstr Address of the instruction to decode. This is a
2716 * real address in the current context that can be
2717 * accessed without faulting. (Consider
2718 * DISInstrWithReader if this isn't the case.)
2719 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2720 * @param pfnReadBytes Callback for reading instruction bytes.
2721 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2722 * @param pDis Pointer to disassembler state (output).
2723 * @param pcbInstr Where to store the size of the instruction.
2724 * NULL is allowed. This is also stored in
2725 * PDISSTATE::cbInstr.
2726 */
2727DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
2728{
2729 return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);
2730}
2731
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