VirtualBox

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

Last change on this file since 53032 was 53032, checked in by vboxsync, 10 years ago

DIS: #6249: Added crc32 Gy, Ew support (with word as operand 2)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 95.1 KB
Line 
1/* $Id: DisasmCore.cpp 53032 2014-10-10 16:18:37Z vboxsync $ */
2/** @file
3 * VBox Disassembler - Core Components.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DIS
23#include <VBox/dis.h>
24#include <VBox/disopcode.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/param.h>
29#include <iprt/string.h>
30#include <iprt/stdarg.h>
31#include "DisasmInternal.h"
32
33
34/*******************************************************************************
35* Defined Constants And Macros *
36*******************************************************************************/
37/** This must be less or equal to DISSTATE::abInstr.
38 * See Vol3A/Table 6-2 and Vol3B/Section22.25 for instance. */
39#define DIS_MAX_INSTR_LENGTH 15
40
41/** Whether we can do unaligned access. */
42#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
43# define DIS_HOST_UNALIGNED_ACCESS_OK
44#endif
45
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50/** @name Parsers
51 * @{ */
52static FNDISPARSE ParseIllegal;
53static FNDISPARSE ParseModRM;
54static FNDISPARSE ParseModRM_SizeOnly;
55static FNDISPARSE UseModRM;
56static FNDISPARSE ParseImmByte;
57static FNDISPARSE ParseImmByte_SizeOnly;
58static FNDISPARSE ParseImmByteSX;
59static FNDISPARSE ParseImmByteSX_SizeOnly;
60static FNDISPARSE ParseImmBRel;
61static FNDISPARSE ParseImmBRel_SizeOnly;
62static FNDISPARSE ParseImmUshort;
63static FNDISPARSE ParseImmUshort_SizeOnly;
64static FNDISPARSE ParseImmV;
65static FNDISPARSE ParseImmV_SizeOnly;
66static FNDISPARSE ParseImmVRel;
67static FNDISPARSE ParseImmVRel_SizeOnly;
68static FNDISPARSE ParseImmZ;
69static FNDISPARSE ParseImmZ_SizeOnly;
70
71static FNDISPARSE ParseImmAddr;
72static FNDISPARSE ParseImmAddr_SizeOnly;
73static FNDISPARSE ParseImmAddrF;
74static FNDISPARSE ParseImmAddrF_SizeOnly;
75static FNDISPARSE ParseFixedReg;
76static FNDISPARSE ParseImmUlong;
77static FNDISPARSE ParseImmUlong_SizeOnly;
78static FNDISPARSE ParseImmQword;
79static FNDISPARSE ParseImmQword_SizeOnly;
80static FNDISPARSE ParseInvOpModRm;
81
82static FNDISPARSE ParseTwoByteEsc;
83static FNDISPARSE ParseThreeByteEsc4;
84static FNDISPARSE ParseThreeByteEsc5;
85static FNDISPARSE ParseImmGrpl;
86static FNDISPARSE ParseShiftGrp2;
87static FNDISPARSE ParseGrp3;
88static FNDISPARSE ParseGrp4;
89static FNDISPARSE ParseGrp5;
90static FNDISPARSE Parse3DNow;
91static FNDISPARSE ParseGrp6;
92static FNDISPARSE ParseGrp7;
93static FNDISPARSE ParseGrp8;
94static FNDISPARSE ParseGrp9;
95static FNDISPARSE ParseGrp10;
96static FNDISPARSE ParseGrp12;
97static FNDISPARSE ParseGrp13;
98static FNDISPARSE ParseGrp14;
99static FNDISPARSE ParseGrp15;
100static FNDISPARSE ParseGrp16;
101static FNDISPARSE ParseModFence;
102static FNDISPARSE ParseNopPause;
103
104static FNDISPARSE ParseYv;
105static FNDISPARSE ParseYb;
106static FNDISPARSE ParseXv;
107static FNDISPARSE ParseXb;
108
109/** Floating point parsing */
110static FNDISPARSE ParseEscFP;
111/** @} */
112
113
114/*******************************************************************************
115* Global Variables *
116*******************************************************************************/
117/** Parser opcode table for full disassembly. */
118static PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
119{
120 ParseIllegal,
121 ParseModRM,
122 UseModRM,
123 ParseImmByte,
124 ParseImmBRel,
125 ParseImmUshort,
126 ParseImmV,
127 ParseImmVRel,
128 ParseImmAddr,
129 ParseFixedReg,
130 ParseImmUlong,
131 ParseImmQword,
132 ParseTwoByteEsc,
133 ParseImmGrpl,
134 ParseShiftGrp2,
135 ParseGrp3,
136 ParseGrp4,
137 ParseGrp5,
138 Parse3DNow,
139 ParseGrp6,
140 ParseGrp7,
141 ParseGrp8,
142 ParseGrp9,
143 ParseGrp10,
144 ParseGrp12,
145 ParseGrp13,
146 ParseGrp14,
147 ParseGrp15,
148 ParseGrp16,
149 ParseModFence,
150 ParseYv,
151 ParseYb,
152 ParseXv,
153 ParseXb,
154 ParseEscFP,
155 ParseNopPause,
156 ParseImmByteSX,
157 ParseImmZ,
158 ParseThreeByteEsc4,
159 ParseThreeByteEsc5,
160 ParseImmAddrF,
161 ParseInvOpModRm
162};
163
164/** Parser opcode table for only calculating instruction size. */
165static PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
166{
167 ParseIllegal,
168 ParseModRM_SizeOnly,
169 UseModRM,
170 ParseImmByte_SizeOnly,
171 ParseImmBRel_SizeOnly,
172 ParseImmUshort_SizeOnly,
173 ParseImmV_SizeOnly,
174 ParseImmVRel_SizeOnly,
175 ParseImmAddr_SizeOnly,
176 ParseFixedReg,
177 ParseImmUlong_SizeOnly,
178 ParseImmQword_SizeOnly,
179 ParseTwoByteEsc,
180 ParseImmGrpl,
181 ParseShiftGrp2,
182 ParseGrp3,
183 ParseGrp4,
184 ParseGrp5,
185 Parse3DNow,
186 ParseGrp6,
187 ParseGrp7,
188 ParseGrp8,
189 ParseGrp9,
190 ParseGrp10,
191 ParseGrp12,
192 ParseGrp13,
193 ParseGrp14,
194 ParseGrp15,
195 ParseGrp16,
196 ParseModFence,
197 ParseYv,
198 ParseYb,
199 ParseXv,
200 ParseXb,
201 ParseEscFP,
202 ParseNopPause,
203 ParseImmByteSX_SizeOnly,
204 ParseImmZ_SizeOnly,
205 ParseThreeByteEsc4,
206 ParseThreeByteEsc5,
207 ParseImmAddrF_SizeOnly,
208 ParseInvOpModRm
209};
210
211
212
213
214
215/********************************************************************************************************************************
216 *
217 *
218 * Read functions for getting the opcode bytes
219 *
220 *
221 ********************************************************************************************************************************/
222
223/**
224 * @interface_method_impl{FNDISREADBYTES, The default byte reader callber.}
225 */
226static DECLCALLBACK(int) disReadBytesDefault(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
227{
228#ifdef IN_RING0
229 NOREF(cbMinRead);
230 AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));
231 RT_BZERO(&pDis->abInstr[offInstr], cbMaxRead);
232 pDis->cbCachedInstr = offInstr + cbMaxRead;
233 return VERR_DIS_NO_READ_CALLBACK;
234#else
235 uint8_t const *pbSrc = (uint8_t const *)(uintptr_t)pDis->uInstrAddr + offInstr;
236 size_t cbLeftOnPage = (uintptr_t)pbSrc & PAGE_OFFSET_MASK;
237 uint8_t cbToRead = cbLeftOnPage >= cbMaxRead
238 ? cbMaxRead
239 : cbLeftOnPage <= cbMinRead
240 ? cbMinRead
241 : (uint8_t)cbLeftOnPage;
242 memcpy(&pDis->abInstr[offInstr], pbSrc, cbToRead);
243 pDis->cbCachedInstr = offInstr + cbToRead;
244 return VINF_SUCCESS;
245#endif
246}
247
248
249/**
250 * Read more bytes into the DISSTATE::abInstr buffer, advance
251 * DISSTATE::cbCachedInstr.
252 *
253 * Will set DISSTATE::rc on failure, but still advance cbCachedInstr.
254 *
255 * The caller shall fend off reads beyond the DISSTATE::abInstr buffer.
256 *
257 * @param pDis The disassembler state.
258 * @param offInstr The offset of the read request.
259 * @param cbMin The size of the read request that needs to be
260 * satisfied.
261 */
262DECL_NO_INLINE(static, void) disReadMore(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMin)
263{
264 Assert(cbMin + offInstr <= sizeof(pDis->abInstr));
265
266 /*
267 * Adjust the incoming request to not overlap with bytes that has already
268 * been read and to make sure we don't leave unread gaps.
269 */
270 if (offInstr < pDis->cbCachedInstr)
271 {
272 Assert(offInstr + cbMin > pDis->cbCachedInstr);
273 cbMin -= pDis->cbCachedInstr - offInstr;
274 offInstr = pDis->cbCachedInstr;
275 }
276 else if (offInstr > pDis->cbCachedInstr)
277 {
278 cbMin += offInstr - pDis->cbCachedInstr;
279 offInstr = pDis->cbCachedInstr;
280 }
281
282 /*
283 * Do the read.
284 * (No need to zero anything on failure as abInstr is already zeroed by the
285 * DISInstrEx API.)
286 */
287 int rc = pDis->pfnReadBytes(pDis, offInstr, cbMin, sizeof(pDis->abInstr) - offInstr);
288 if (RT_SUCCESS(rc))
289 {
290 Assert(pDis->cbCachedInstr >= offInstr + cbMin);
291 Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
292 }
293 else
294 {
295 Log(("disReadMore failed with rc=%Rrc!!\n", rc));
296 pDis->rc = rc;
297 }
298}
299
300
301/**
302 * Function for handling a 8-bit cache miss.
303 *
304 * @returns The requested byte.
305 * @param pDis The disassembler state.
306 * @param offInstr The offset of the byte relative to the
307 * instruction.
308 */
309DECL_NO_INLINE(static, uint8_t) disReadByteSlow(PDISSTATE pDis, size_t offInstr)
310{
311 if (RT_UNLIKELY(offInstr >= DIS_MAX_INSTR_LENGTH))
312 {
313 Log(("disReadByte: too long instruction...\n"));
314 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
315 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
316 if (cbLeft > 0)
317 return pDis->abInstr[offInstr];
318 return 0;
319 }
320
321 disReadMore(pDis, (uint8_t)offInstr, 1);
322 return pDis->abInstr[offInstr];
323}
324
325
326/**
327 * Read a byte (8-bit) instruction.
328 *
329 * @returns The requested byte.
330 * @param pDis The disassembler state.
331 * @param uAddress The address.
332 */
333DECLINLINE(uint8_t) disReadByte(PDISSTATE pDis, size_t offInstr)
334{
335 if (RT_UNLIKELY(offInstr >= pDis->cbCachedInstr))
336 return disReadByteSlow(pDis, offInstr);
337
338 return pDis->abInstr[offInstr];
339}
340
341
342/**
343 * Function for handling a 16-bit cache miss.
344 *
345 * @returns The requested word.
346 * @param pDis The disassembler state.
347 * @param offInstr The offset of the word relative to the
348 * instruction.
349 */
350DECL_NO_INLINE(static, uint16_t) disReadWordSlow(PDISSTATE pDis, size_t offInstr)
351{
352 if (RT_UNLIKELY(offInstr + 2 > DIS_MAX_INSTR_LENGTH))
353 {
354 Log(("disReadWord: too long instruction...\n"));
355 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
356 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
357 switch (cbLeft)
358 {
359 case 1:
360 return pDis->abInstr[offInstr];
361 default:
362 if (cbLeft >= 2)
363 return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
364 return 0;
365 }
366 }
367
368 disReadMore(pDis, (uint8_t)offInstr, 2);
369#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
370 return *(uint16_t const *)&pDis->abInstr[offInstr];
371#else
372 return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
373#endif
374}
375
376
377/**
378 * Read a word (16-bit) instruction.
379 *
380 * @returns The requested word.
381 * @param pDis The disassembler state.
382 * @param offInstr The offset of the qword relative to the
383 * instruction.
384 */
385DECLINLINE(uint16_t) disReadWord(PDISSTATE pDis, size_t offInstr)
386{
387 if (RT_UNLIKELY(offInstr + 2 > pDis->cbCachedInstr))
388 return disReadWordSlow(pDis, offInstr);
389
390#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
391 return *(uint16_t const *)&pDis->abInstr[offInstr];
392#else
393 return RT_MAKE_U16(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1]);
394#endif
395}
396
397
398/**
399 * Function for handling a 32-bit cache miss.
400 *
401 * @returns The requested dword.
402 * @param pDis The disassembler state.
403 * @param offInstr The offset of the dword relative to the
404 * instruction.
405 */
406DECL_NO_INLINE(static, uint32_t) disReadDWordSlow(PDISSTATE pDis, size_t offInstr)
407{
408 if (RT_UNLIKELY(offInstr + 4 > DIS_MAX_INSTR_LENGTH))
409 {
410 Log(("disReadDWord: too long instruction...\n"));
411 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
412 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
413 switch (cbLeft)
414 {
415 case 1:
416 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0);
417 case 2:
418 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0);
419 case 3:
420 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], pDis->abInstr[offInstr + 2], 0);
421 default:
422 if (cbLeft >= 4)
423 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
424 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
425 return 0;
426 }
427 }
428
429 disReadMore(pDis, (uint8_t)offInstr, 4);
430#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
431 return *(uint32_t const *)&pDis->abInstr[offInstr];
432#else
433 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
434 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
435#endif
436}
437
438
439/**
440 * Read a dword (32-bit) instruction.
441 *
442 * @returns The requested dword.
443 * @param pDis The disassembler state.
444 * @param offInstr The offset of the qword relative to the
445 * instruction.
446 */
447DECLINLINE(uint32_t) disReadDWord(PDISSTATE pDis, size_t offInstr)
448{
449 if (RT_UNLIKELY(offInstr + 4 > pDis->cbCachedInstr))
450 return disReadDWordSlow(pDis, offInstr);
451
452#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
453 return *(uint32_t const *)&pDis->abInstr[offInstr];
454#else
455 return RT_MAKE_U32_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
456 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3]);
457#endif
458}
459
460
461/**
462 * Function for handling a 64-bit cache miss.
463 *
464 * @returns The requested qword.
465 * @param pDis The disassembler state.
466 * @param offInstr The offset of the qword relative to the
467 * instruction.
468 */
469DECL_NO_INLINE(static, uint64_t) disReadQWordSlow(PDISSTATE pDis, size_t offInstr)
470{
471 if (RT_UNLIKELY(offInstr + 8 > DIS_MAX_INSTR_LENGTH))
472 {
473 Log(("disReadQWord: too long instruction...\n"));
474 pDis->rc = VERR_DIS_TOO_LONG_INSTR;
475 RTINTPTR cbLeft = sizeof(pDis->abInstr) - offInstr;
476 switch (cbLeft)
477 {
478 case 1:
479 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], 0, 0, 0, 0, 0, 0, 0);
480 case 2:
481 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr], pDis->abInstr[offInstr + 1], 0, 0, 0, 0, 0, 0);
482 case 3:
483 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
484 pDis->abInstr[offInstr + 2], 0, 0, 0, 0, 0);
485 case 4:
486 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
487 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
488 0, 0, 0, 0);
489 case 5:
490 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
491 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
492 pDis->abInstr[offInstr + 4], 0, 0, 0);
493 case 6:
494 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
495 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
496 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
497 0, 0);
498 case 7:
499 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
500 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
501 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
502 pDis->abInstr[offInstr + 6], 0);
503 default:
504 if (cbLeft >= 8)
505 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
506 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
507 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
508 pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
509 return 0;
510 }
511 }
512
513 disReadMore(pDis, (uint8_t)offInstr, 8);
514#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
515 return *(uint64_t const *)&pDis->abInstr[offInstr];
516#else
517 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
518 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
519 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
520 pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
521#endif
522}
523
524
525/**
526 * Read a qword (64-bit) instruction.
527 *
528 * @returns The requested qword.
529 * @param pDis The disassembler state.
530 * @param uAddress The address.
531 */
532DECLINLINE(uint64_t) disReadQWord(PDISSTATE pDis, size_t offInstr)
533{
534 if (RT_UNLIKELY(offInstr + 8 > pDis->cbCachedInstr))
535 return disReadQWordSlow(pDis, offInstr);
536
537#ifdef DIS_HOST_UNALIGNED_ACCESS_OK
538 return *(uint64_t const *)&pDis->abInstr[offInstr];
539#else
540 return RT_MAKE_U64_FROM_U8(pDis->abInstr[offInstr ], pDis->abInstr[offInstr + 1],
541 pDis->abInstr[offInstr + 2], pDis->abInstr[offInstr + 3],
542 pDis->abInstr[offInstr + 4], pDis->abInstr[offInstr + 5],
543 pDis->abInstr[offInstr + 6], pDis->abInstr[offInstr + 7]);
544#endif
545}
546
547
548
549//*****************************************************************************
550//*****************************************************************************
551static size_t disParseInstruction(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis)
552{
553 Assert(pOp); Assert(pDis);
554
555 // Store the opcode format string for disasmPrintf
556 pDis->pCurInstr = pOp;
557
558 /*
559 * Apply filter to instruction type to determine if a full disassembly is required.
560 * Note! Multibyte opcodes are always marked harmless until the final byte.
561 */
562 bool fFiltered;
563 if ((pOp->fOpType & pDis->fFilter) == 0)
564 {
565 fFiltered = true;
566 pDis->pfnDisasmFnTable = g_apfnCalcSize;
567 }
568 else
569 {
570 /* Not filtered out -> full disassembly */
571 fFiltered = false;
572 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
573 }
574
575 // Should contain the parameter type on input
576 pDis->Param1.fParam = pOp->fParam1;
577 pDis->Param2.fParam = pOp->fParam2;
578 pDis->Param3.fParam = pOp->fParam3;
579
580 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
581 if (pDis->uCpuMode == DISCPUMODE_64BIT)
582 {
583 if (pOp->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
584 pDis->uOpMode = DISCPUMODE_64BIT;
585 else
586 if ( (pOp->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
587 && !(pDis->fPrefix & DISPREFIX_OPSIZE))
588 pDis->uOpMode = DISCPUMODE_64BIT;
589 }
590 else
591 if (pOp->fOpType & DISOPTYPE_FORCED_32_OP_SIZE_X86)
592 {
593 /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
594 Assert(pDis->uCpuMode != DISCPUMODE_64BIT);
595 pDis->uOpMode = DISCPUMODE_32BIT;
596 }
597
598 if (pOp->idxParse1 != IDX_ParseNop)
599 {
600 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse1](offInstr, pOp, pDis, &pDis->Param1);
601 if (fFiltered == false) pDis->Param1.cb = DISGetParamSize(pDis, &pDis->Param1);
602 }
603
604 if (pOp->idxParse2 != IDX_ParseNop)
605 {
606 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse2](offInstr, pOp, pDis, &pDis->Param2);
607 if (fFiltered == false) pDis->Param2.cb = DISGetParamSize(pDis, &pDis->Param2);
608 }
609
610 if (pOp->idxParse3 != IDX_ParseNop)
611 {
612 offInstr = pDis->pfnDisasmFnTable[pOp->idxParse3](offInstr, pOp, pDis, &pDis->Param3);
613 if (fFiltered == false) pDis->Param3.cb = DISGetParamSize(pDis, &pDis->Param3);
614 }
615 // else simple one byte instruction
616
617 return offInstr;
618}
619//*****************************************************************************
620/* Floating point opcode parsing */
621//*****************************************************************************
622static size_t ParseEscFP(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
623{
624 PCDISOPCODE fpop;
625 NOREF(pOp);
626
627 uint8_t ModRM = disReadByte(pDis, offInstr);
628 uint8_t index = pDis->bOpCode - 0xD8;
629 if (ModRM <= 0xBF)
630 {
631 fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
632 pDis->pCurInstr = fpop;
633
634 // Should contain the parameter type on input
635 pDis->Param1.fParam = fpop->fParam1;
636 pDis->Param2.fParam = fpop->fParam2;
637 }
638 else
639 {
640 fpop = &(g_apMapX86_FP_High[index])[ModRM - 0xC0];
641 pDis->pCurInstr = fpop;
642 }
643
644 /*
645 * Apply filter to instruction type to determine if a full disassembly is required.
646 * @note Multibyte opcodes are always marked harmless until the final byte.
647 */
648 if ((fpop->fOpType & pDis->fFilter) == 0)
649 pDis->pfnDisasmFnTable = g_apfnCalcSize;
650 else
651 /* Not filtered out -> full disassembly */
652 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
653
654 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
655 if (pDis->uCpuMode == DISCPUMODE_64BIT)
656 {
657 /* Note: redundant, but just in case this ever changes */
658 if (fpop->fOpType & DISOPTYPE_FORCED_64_OP_SIZE)
659 pDis->uOpMode = DISCPUMODE_64BIT;
660 else
661 if ( (fpop->fOpType & DISOPTYPE_DEFAULT_64_OP_SIZE)
662 && !(pDis->fPrefix & DISPREFIX_OPSIZE))
663 pDis->uOpMode = DISCPUMODE_64BIT;
664 }
665
666 // Little hack to make sure the ModRM byte is included in the returned size
667 if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
668 offInstr++; //ModRM byte
669
670 if (fpop->idxParse1 != IDX_ParseNop)
671 offInstr = pDis->pfnDisasmFnTable[fpop->idxParse1](offInstr, fpop, pDis, pParam);
672
673 if (fpop->idxParse2 != IDX_ParseNop)
674 offInstr = pDis->pfnDisasmFnTable[fpop->idxParse2](offInstr, fpop, pDis, pParam);
675
676 return offInstr;
677}
678
679
680/********************************************************************************************************************************
681 *
682 *
683 * SIB byte: (not 16-bit mode)
684 * 7 - 6 5 - 3 2-0
685 * Scale Index Base
686 *
687 *
688 ********************************************************************************************************************************/
689static void UseSIB(PDISSTATE pDis, PDISOPPARAM pParam)
690{
691 unsigned scale = pDis->SIB.Bits.Scale;
692 unsigned base = pDis->SIB.Bits.Base;
693 unsigned index = pDis->SIB.Bits.Index;
694
695 unsigned regtype;
696 if (pDis->uAddrMode == DISCPUMODE_32BIT)
697 regtype = DISUSE_REG_GEN32;
698 else
699 regtype = DISUSE_REG_GEN64;
700
701 if (index != 4)
702 {
703 pParam->fUse |= DISUSE_INDEX | regtype;
704 pParam->Index.idxGenReg = index;
705
706 if (scale != 0)
707 {
708 pParam->fUse |= DISUSE_SCALE;
709 pParam->uScale = (1<<scale);
710 }
711 }
712
713 if (base == 5 && pDis->ModRM.Bits.Mod == 0)
714 {
715 // [scaled index] + disp32
716 if (pDis->uAddrMode == DISCPUMODE_32BIT)
717 {
718 pParam->fUse |= DISUSE_DISPLACEMENT32;
719 pParam->uDisp.i32 = pDis->i32SibDisp;
720 }
721 else
722 { /* sign-extend to 64 bits */
723 pParam->fUse |= DISUSE_DISPLACEMENT64;
724 pParam->uDisp.i64 = pDis->i32SibDisp;
725 }
726 }
727 else
728 {
729 pParam->fUse |= DISUSE_BASE | regtype;
730 pParam->Base.idxGenReg = base;
731 }
732 return; /* Already fetched everything in ParseSIB; no size returned */
733}
734
735
736static size_t ParseSIB(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
737{
738 NOREF(pOp); NOREF(pParam);
739
740 uint8_t SIB = disReadByte(pDis, offInstr);
741 offInstr++;
742
743 pDis->SIB.Bits.Base = SIB_BASE(SIB);
744 pDis->SIB.Bits.Index = SIB_INDEX(SIB);
745 pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
746
747 if (pDis->fPrefix & DISPREFIX_REX)
748 {
749 /* REX.B extends the Base field if not scaled index + disp32 */
750 if (!(pDis->SIB.Bits.Base == 5 && pDis->ModRM.Bits.Mod == 0))
751 pDis->SIB.Bits.Base |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
752
753 pDis->SIB.Bits.Index |= (!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3;
754 }
755
756 if ( pDis->SIB.Bits.Base == 5
757 && pDis->ModRM.Bits.Mod == 0)
758 {
759 /* Additional 32 bits displacement. No change in long mode. */
760 pDis->i32SibDisp = disReadDWord(pDis, offInstr);
761 offInstr += 4;
762 }
763 return offInstr;
764}
765
766
767static size_t ParseSIB_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
768{
769 NOREF(pOp); NOREF(pParam);
770
771 uint8_t SIB = disReadByte(pDis, offInstr);
772 offInstr++;
773
774 pDis->SIB.Bits.Base = SIB_BASE(SIB);
775 pDis->SIB.Bits.Index = SIB_INDEX(SIB);
776 pDis->SIB.Bits.Scale = SIB_SCALE(SIB);
777
778 if (pDis->fPrefix & DISPREFIX_REX)
779 {
780 /* REX.B extends the Base field. */
781 pDis->SIB.Bits.Base |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
782 /* REX.X extends the Index field. */
783 pDis->SIB.Bits.Index |= ((!!(pDis->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
784 }
785
786 if ( pDis->SIB.Bits.Base == 5
787 && pDis->ModRM.Bits.Mod == 0)
788 {
789 /* Additional 32 bits displacement. No change in long mode. */
790 offInstr += 4;
791 }
792 return offInstr;
793}
794
795
796
797/********************************************************************************************************************************
798 *
799 *
800 * ModR/M byte:
801 * 7 - 6 5 - 3 2-0
802 * Mod Reg/Opcode R/M
803 *
804 *
805 ********************************************************************************************************************************/
806static void disasmModRMReg(unsigned idx, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, int fRegAddr)
807{
808 NOREF(pOp); NOREF(pDis);
809
810 unsigned type = OP_PARM_VTYPE(pParam->fParam);
811 unsigned subtype = OP_PARM_VSUBTYPE(pParam->fParam);
812 if (fRegAddr)
813 subtype = (pDis->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
814 else
815 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE || subtype == OP_PARM_y)
816 {
817 switch (pDis->uOpMode)
818 {
819 case DISCPUMODE_32BIT:
820 subtype = OP_PARM_d;
821 break;
822 case DISCPUMODE_64BIT:
823 subtype = OP_PARM_q;
824 break;
825 case DISCPUMODE_16BIT:
826 if (subtype != OP_PARM_y)
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 NOREF(pOp);
1566 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1567 {
1568 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1569 {
1570 /* far 16:32 pointer */
1571 pParam->uValue = disReadDWord(pDis, offInstr);
1572 *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
1573 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1574 pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1575 return offInstr + 4 + 2;
1576 }
1577
1578 /*
1579 * near 32 bits pointer
1580 *
1581 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1582 * so we treat it like displacement.
1583 */
1584 pParam->uDisp.i32 = disReadDWord(pDis, offInstr);
1585 pParam->fUse |= DISUSE_DISPLACEMENT32;
1586 pParam->cb = sizeof(uint32_t);
1587 return offInstr + 4;
1588 }
1589
1590 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1591 {
1592 /*
1593 * near 64 bits pointer
1594 *
1595 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1596 * so we treat it like displacement.
1597 */
1598 Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
1599 pParam->uDisp.i64 = disReadQWord(pDis, offInstr);
1600 pParam->fUse |= DISUSE_DISPLACEMENT64;
1601 pParam->cb = sizeof(uint64_t);
1602 return offInstr + 8;
1603 }
1604 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1605 {
1606 /* far 16:16 pointer */
1607 pParam->uValue = disReadDWord(pDis, offInstr);
1608 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1609 pParam->cb = 2*sizeof(uint16_t);
1610 return offInstr + 4;
1611 }
1612
1613 /*
1614 * near 16 bits pointer
1615 *
1616 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1617 * so we treat it like displacement.
1618 */
1619 pParam->uDisp.i16 = disReadWord(pDis, offInstr);
1620 pParam->fUse |= DISUSE_DISPLACEMENT16;
1621 pParam->cb = sizeof(uint16_t);
1622 return offInstr + 2;
1623}
1624//*****************************************************************************
1625//*****************************************************************************
1626static size_t ParseImmAddr_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1627{
1628 NOREF(offInstr); NOREF(pOp);
1629 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1630 {
1631 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1632 return offInstr + 4 + 2; /* far 16:32 pointer */
1633 return offInstr + 4; /* near 32 bits pointer */
1634 }
1635 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1636 {
1637 Assert(OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_p);
1638 return offInstr + 8;
1639 }
1640 if (OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p)
1641 return offInstr + 4; /* far 16:16 pointer */
1642 return offInstr + 2; /* near 16 bits pointer */
1643}
1644//*****************************************************************************
1645//*****************************************************************************
1646static size_t ParseImmAddrF(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1647{
1648 NOREF(pOp);
1649 // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
1650 Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
1651 Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1652 if (pDis->uOpMode == DISCPUMODE_32BIT)
1653 {
1654 // far 16:32 pointer
1655 pParam->uValue = disReadDWord(pDis, offInstr);
1656 *((uint32_t*)&pParam->uValue+1) = disReadWord(pDis, offInstr+sizeof(uint32_t));
1657 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1658 pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1659 return offInstr + 4 + 2;
1660 }
1661
1662 // far 16:16 pointer
1663 pParam->uValue = disReadDWord(pDis, offInstr);
1664 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1665 pParam->cb = 2*sizeof(uint16_t);
1666 return offInstr + 2 + 2;
1667}
1668//*****************************************************************************
1669//*****************************************************************************
1670static size_t ParseImmAddrF_SizeOnly(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1671{
1672 NOREF(offInstr); NOREF(pOp);
1673 // immediate far pointers - only 16:16 or 16:32
1674 Assert(pDis->uOpMode == DISCPUMODE_16BIT || pDis->uOpMode == DISCPUMODE_32BIT);
1675 Assert(OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p);
1676 if (pDis->uOpMode == DISCPUMODE_32BIT)
1677 return offInstr + 4 + 2; /* far 16:32 pointer */
1678 return offInstr + 2 + 2; /* far 16:16 pointer */
1679}
1680//*****************************************************************************
1681//*****************************************************************************
1682static size_t ParseFixedReg(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1683{
1684 NOREF(offInstr);
1685
1686 /*
1687 * Sets up flags for stored in OPC fixed registers.
1688 */
1689
1690 if (pParam->fParam == OP_PARM_NONE)
1691 {
1692 /* No parameter at all. */
1693 return offInstr;
1694 }
1695
1696 AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
1697 AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
1698 AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1699 AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
1700
1701 if (pParam->fParam <= OP_PARM_REG_GEN32_END)
1702 {
1703 /* 32-bit EAX..EDI registers. */
1704 if (pDis->uOpMode == DISCPUMODE_32BIT)
1705 {
1706 /* Use 32-bit registers. */
1707 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1708 pParam->fUse |= DISUSE_REG_GEN32;
1709 pParam->cb = 4;
1710 }
1711 else if (pDis->uOpMode == DISCPUMODE_64BIT)
1712 {
1713 /* Use 64-bit registers. */
1714 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1715 pParam->fUse |= DISUSE_REG_GEN64;
1716 pParam->cb = 8;
1717 }
1718 else
1719 {
1720 /* Use 16-bit registers. */
1721 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN32_START;
1722 pParam->fUse |= DISUSE_REG_GEN16;
1723 pParam->cb = 2;
1724 pParam->fParam = pParam->fParam - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1725 }
1726
1727 if ( (pOp->fOpType & DISOPTYPE_REXB_EXTENDS_OPREG)
1728 && pParam == &pDis->Param1 /* ugly assumption that it only applies to the first parameter */
1729 && (pDis->fPrefix & DISPREFIX_REX)
1730 && (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B))
1731 {
1732 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
1733 pParam->Base.idxGenReg += 8;
1734 }
1735 }
1736 else if (pParam->fParam <= OP_PARM_REG_SEG_END)
1737 {
1738 /* Segment ES..GS registers. */
1739 pParam->Base.idxSegReg = (DISSELREG)(pParam->fParam - OP_PARM_REG_SEG_START);
1740 pParam->fUse |= DISUSE_REG_SEG;
1741 pParam->cb = 2;
1742 }
1743 else if (pParam->fParam <= OP_PARM_REG_GEN16_END)
1744 {
1745 /* 16-bit AX..DI registers. */
1746 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN16_START;
1747 pParam->fUse |= DISUSE_REG_GEN16;
1748 pParam->cb = 2;
1749 }
1750 else if (pParam->fParam <= OP_PARM_REG_GEN8_END)
1751 {
1752 /* 8-bit AL..DL, AH..DH registers. */
1753 pParam->Base.idxGenReg = pParam->fParam - OP_PARM_REG_GEN8_START;
1754 pParam->fUse |= DISUSE_REG_GEN8;
1755 pParam->cb = 1;
1756
1757 if ( pDis->uCpuMode == DISCPUMODE_64BIT
1758 && (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 {
1762 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_B)
1763 pParam->Base.idxGenReg += 8; /* least significant byte of R8-R15 */
1764 else if ( pParam->Base.idxGenReg >= DISGREG_AH
1765 && pParam->Base.idxGenReg <= DISGREG_BH)
1766 pParam->Base.idxGenReg += DISGREG_SPL - DISGREG_AH;
1767 }
1768 }
1769 else if (pParam->fParam <= OP_PARM_REG_FP_END)
1770 {
1771 /* FPU registers. */
1772 pParam->Base.idxFpuReg = pParam->fParam - OP_PARM_REG_FP_START;
1773 pParam->fUse |= DISUSE_REG_FP;
1774 pParam->cb = 10;
1775 }
1776 Assert(!(pParam->fParam >= OP_PARM_REG_GEN64_START && pParam->fParam <= OP_PARM_REG_GEN64_END));
1777
1778 /* else - not supported for now registers. */
1779
1780 return offInstr;
1781}
1782//*****************************************************************************
1783//*****************************************************************************
1784static size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1785{
1786 NOREF(pOp);
1787
1788 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1789 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1790 {
1791 pParam->Base.idxGenReg = DISGREG_ESI;
1792 pParam->fUse |= DISUSE_REG_GEN32;
1793 }
1794 else
1795 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1796 {
1797 pParam->Base.idxGenReg = DISGREG_RSI;
1798 pParam->fUse |= DISUSE_REG_GEN64;
1799 }
1800 else
1801 {
1802 pParam->Base.idxGenReg = DISGREG_SI;
1803 pParam->fUse |= DISUSE_REG_GEN16;
1804 }
1805 return offInstr;
1806}
1807//*****************************************************************************
1808//*****************************************************************************
1809static size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1810{
1811 NOREF(pOp);
1812
1813 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1814 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1815 {
1816 pParam->Base.idxGenReg = DISGREG_ESI;
1817 pParam->fUse |= DISUSE_REG_GEN32;
1818 }
1819 else
1820 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1821 {
1822 pParam->Base.idxGenReg = DISGREG_RSI;
1823 pParam->fUse |= DISUSE_REG_GEN64;
1824 }
1825 else
1826 {
1827 pParam->Base.idxGenReg = DISGREG_SI;
1828 pParam->fUse |= DISUSE_REG_GEN16;
1829 }
1830 return offInstr;
1831}
1832//*****************************************************************************
1833//*****************************************************************************
1834static size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1835{
1836 NOREF(pOp);
1837
1838 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1839 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1840 {
1841 pParam->Base.idxGenReg = DISGREG_EDI;
1842 pParam->fUse |= DISUSE_REG_GEN32;
1843 }
1844 else
1845 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1846 {
1847 pParam->Base.idxGenReg = DISGREG_RDI;
1848 pParam->fUse |= DISUSE_REG_GEN64;
1849 }
1850 else
1851 {
1852 pParam->Base.idxGenReg = DISGREG_DI;
1853 pParam->fUse |= DISUSE_REG_GEN16;
1854 }
1855 return offInstr;
1856}
1857//*****************************************************************************
1858//*****************************************************************************
1859static size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1860{
1861 NOREF(pOp);
1862
1863 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1864 if (pDis->uAddrMode == DISCPUMODE_32BIT)
1865 {
1866 pParam->Base.idxGenReg = DISGREG_EDI;
1867 pParam->fUse |= DISUSE_REG_GEN32;
1868 }
1869 else
1870 if (pDis->uAddrMode == DISCPUMODE_64BIT)
1871 {
1872 pParam->Base.idxGenReg = DISGREG_RDI;
1873 pParam->fUse |= DISUSE_REG_GEN64;
1874 }
1875 else
1876 {
1877 pParam->Base.idxGenReg = DISGREG_DI;
1878 pParam->fUse |= DISUSE_REG_GEN16;
1879 }
1880 return offInstr;
1881}
1882//*****************************************************************************
1883//*****************************************************************************
1884static size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1885{
1886 NOREF(pOp); NOREF(pDis); NOREF(pParam);
1887 /* This is used to avoid a bunch of special hacks to get the ModRM byte
1888 included when encountering invalid opcodes in groups. */
1889 return offInstr + 1;
1890}
1891//*****************************************************************************
1892//*****************************************************************************
1893static size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1894{
1895 NOREF(pOp); NOREF(pParam);
1896
1897 /* 2nd byte */
1898 pDis->bOpCode = disReadByte(pDis, offInstr);
1899 offInstr++;
1900
1901 /* default to the non-prefixed table. */
1902 PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->bOpCode];
1903
1904 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1905 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1906 if (pDis->bLastPrefix)
1907 {
1908 switch (pDis->bLastPrefix)
1909 {
1910 case OP_OPSIZE: /* 0x66 */
1911 if (g_aTwoByteMapX86_PF66[pDis->bOpCode].uOpcode != OP_INVALID)
1912 {
1913 /* Table entry is valid, so use the extension table. */
1914 pOpcode = &g_aTwoByteMapX86_PF66[pDis->bOpCode];
1915
1916 /* Cancel prefix changes. */
1917 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1918
1919 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1920 {
1921 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
1922 }
1923 else
1924 pDis->uOpMode = pDis->uCpuMode;
1925 }
1926 break;
1927
1928 case OP_REPNE: /* 0xF2 */
1929 if (g_aTwoByteMapX86_PFF2[pDis->bOpCode].uOpcode != OP_INVALID)
1930 {
1931 /* Table entry is valid, so use the extension table. */
1932 pOpcode = &g_aTwoByteMapX86_PFF2[pDis->bOpCode];
1933
1934 /* Cancel prefix changes. */
1935 pDis->fPrefix &= ~DISPREFIX_REPNE;
1936 }
1937 break;
1938
1939 case OP_REPE: /* 0xF3 */
1940 if (g_aTwoByteMapX86_PFF3[pDis->bOpCode].uOpcode != OP_INVALID)
1941 {
1942 /* Table entry is valid, so use the extension table. */
1943 pOpcode = &g_aTwoByteMapX86_PFF3[pDis->bOpCode];
1944
1945 /* Cancel prefix changes. */
1946 pDis->fPrefix &= ~DISPREFIX_REP;
1947 }
1948 break;
1949 }
1950 }
1951
1952 return disParseInstruction(offInstr, pOpcode, pDis);
1953}
1954//*****************************************************************************
1955//*****************************************************************************
1956static size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1957{
1958 NOREF(pOp); NOREF(pParam);
1959
1960 /* 3rd byte */
1961 pDis->bOpCode = disReadByte(pDis, offInstr);
1962 offInstr++;
1963
1964 /* default to the non-prefixed table. */
1965 PCDISOPCODE pOpcode;
1966 if (g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4])
1967 {
1968 pOpcode = g_apThreeByteMapX86_0F38[pDis->bOpCode >> 4];
1969 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1970 }
1971 else
1972 pOpcode = &g_InvalidOpcode[0];
1973
1974 /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1975 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1976 switch (pDis->bLastPrefix)
1977 {
1978 case OP_OPSIZE: /* 0x66 */
1979 if (g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4])
1980 {
1981 pOpcode = g_apThreeByteMapX86_660F38[pDis->bOpCode >> 4];
1982 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
1983
1984 if (pOpcode->uOpcode != OP_INVALID)
1985 {
1986 /* Table entry is valid, so use the extension table. */
1987
1988 /* Cancel prefix changes. */
1989 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
1990 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1991 {
1992 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
1993 }
1994 else
1995 pDis->uOpMode = pDis->uCpuMode;
1996
1997 }
1998 }
1999 break;
2000
2001 case OP_REPNE: /* 0xF2 */
2002 if ((pDis->fPrefix & DISPREFIX_OPSIZE) && g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4])
2003 {
2004 /* 0x66F2 */
2005 pOpcode = g_apThreeByteMapX86_66F20F38[pDis->bOpCode >> 4];
2006 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2007
2008 if (pOpcode->uOpcode != OP_INVALID)
2009 {
2010 /* Table entry is valid, so use the extension table. */
2011
2012 /* Cancel prefix changes. */
2013 pDis->fPrefix &= ~DISPREFIX_REPNE;
2014 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
2015 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2016 {
2017 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
2018 }
2019 else
2020 pDis->uOpMode = pDis->uCpuMode;
2021 }
2022 }
2023 else if (g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4])
2024 {
2025 pOpcode = g_apThreeByteMapX86_F20F38[pDis->bOpCode >> 4];
2026 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2027
2028 if (pOpcode->uOpcode != OP_INVALID)
2029 {
2030 /* Table entry is valid, so use the extension table. */
2031
2032 /* Cancel prefix changes. */
2033 pDis->fPrefix &= ~DISPREFIX_REPNE;
2034 }
2035 }
2036 break;
2037
2038 case OP_REPE: /* 0xF3 */
2039 if (g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4])
2040 {
2041 pOpcode = g_apThreeByteMapX86_F30F38[pDis->bOpCode >> 4];
2042 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2043
2044 if (pOpcode->uOpcode != OP_INVALID)
2045 {
2046 /* Table entry is valid, so use the extension table. */
2047
2048 /* Cancel prefix changes. */
2049 pDis->fPrefix &= ~DISPREFIX_REP;
2050 }
2051 }
2052 }
2053
2054 return disParseInstruction(offInstr, pOpcode, pDis);
2055}
2056//*****************************************************************************
2057//*****************************************************************************
2058static size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2059{
2060 NOREF(pOp); NOREF(pParam);
2061
2062 /* 3rd byte */
2063 pDis->bOpCode = disReadByte(pDis, offInstr);
2064 offInstr++;
2065
2066 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
2067 Assert(pDis->bLastPrefix == OP_OPSIZE);
2068
2069 /* default to the non-prefixed table. */
2070 PCDISOPCODE pOpcode;
2071 if (g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4])
2072 {
2073 pOpcode = g_apThreeByteMapX86_660F3A[pDis->bOpCode >> 4];
2074 pOpcode = &pOpcode[pDis->bOpCode & 0xf];
2075
2076 if (pOpcode->uOpcode != OP_INVALID)
2077 {
2078 /* Table entry is valid, so use the extension table. */
2079
2080 /* Cancel prefix changes. */
2081 pDis->fPrefix &= ~DISPREFIX_OPSIZE;
2082 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2083 {
2084 pDis->uOpMode = (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
2085 }
2086 else
2087 pDis->uOpMode = pDis->uCpuMode;
2088
2089 }
2090 }
2091 else
2092 pOpcode = &g_InvalidOpcode[0];
2093
2094 return disParseInstruction(offInstr, pOpcode, pDis);
2095}
2096//*****************************************************************************
2097//*****************************************************************************
2098static size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2099{
2100 NOREF(pParam);
2101
2102 if (pDis->fPrefix & DISPREFIX_REP)
2103 {
2104 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
2105 pDis->fPrefix &= ~DISPREFIX_REP;
2106 }
2107 else
2108 pOp = &g_aMapX86_NopPause[0]; /* NOP */
2109
2110 return disParseInstruction(offInstr, pOp, pDis);
2111}
2112//*****************************************************************************
2113//*****************************************************************************
2114static size_t ParseImmGrpl(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2115{
2116 NOREF(pParam);
2117
2118 uint8_t modrm = disReadByte(pDis, offInstr);
2119 uint8_t reg = MODRM_REG(modrm);
2120 unsigned idx = (pDis->bOpCode - 0x80) * 8;
2121
2122 pOp = &g_aMapX86_Group1[idx+reg];
2123
2124 return disParseInstruction(offInstr, pOp, pDis);
2125}
2126//*****************************************************************************
2127//*****************************************************************************
2128static size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2129{
2130 NOREF(pParam);
2131
2132 unsigned idx;
2133 switch (pDis->bOpCode)
2134 {
2135 case 0xC0:
2136 case 0xC1:
2137 idx = (pDis->bOpCode - 0xC0)*8;
2138 break;
2139
2140 case 0xD0:
2141 case 0xD1:
2142 case 0xD2:
2143 case 0xD3:
2144 idx = (pDis->bOpCode - 0xD0 + 2)*8;
2145 break;
2146
2147 default:
2148 Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->bOpCode));
2149 pDis->rc = VERR_DIS_INVALID_OPCODE;
2150 return offInstr;
2151 }
2152
2153 uint8_t modrm = disReadByte(pDis, offInstr);
2154 uint8_t reg = MODRM_REG(modrm);
2155
2156 pOp = &g_aMapX86_Group2[idx+reg];
2157
2158 return disParseInstruction(offInstr, pOp, pDis);
2159}
2160//*****************************************************************************
2161//*****************************************************************************
2162static size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2163{
2164 unsigned idx = (pDis->bOpCode - 0xF6) * 8;
2165 NOREF(pParam);
2166
2167 uint8_t modrm = disReadByte(pDis, offInstr);
2168 uint8_t reg = MODRM_REG(modrm);
2169
2170 pOp = &g_aMapX86_Group3[idx+reg];
2171
2172 return disParseInstruction(offInstr, pOp, pDis);
2173}
2174//*****************************************************************************
2175//*****************************************************************************
2176static size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2177{
2178 NOREF(pParam);
2179
2180 uint8_t modrm = disReadByte(pDis, offInstr);
2181 uint8_t reg = MODRM_REG(modrm);
2182
2183 pOp = &g_aMapX86_Group4[reg];
2184
2185 return disParseInstruction(offInstr, pOp, pDis);
2186}
2187//*****************************************************************************
2188//*****************************************************************************
2189static size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2190{
2191 NOREF(pParam);
2192
2193 uint8_t modrm = disReadByte(pDis, offInstr);
2194 uint8_t reg = MODRM_REG(modrm);
2195
2196 pOp = &g_aMapX86_Group5[reg];
2197
2198 return disParseInstruction(offInstr, pOp, pDis);
2199}
2200//*****************************************************************************
2201// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
2202// It would appear the ModRM byte must always be present. How else can you
2203// determine the offset of the imm8_opcode byte otherwise?
2204//
2205//*****************************************************************************
2206static size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2207{
2208 /** @todo This code needs testing! Esp. wrt invalid opcodes. */
2209
2210 uint8_t ModRM = disReadByte(pDis, offInstr);
2211 pDis->ModRM.Bits.Rm = MODRM_RM(ModRM);
2212 pDis->ModRM.Bits.Mod = MODRM_MOD(ModRM);
2213 pDis->ModRM.Bits.Reg = MODRM_REG(ModRM);
2214
2215 size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
2216
2217 uint8_t opcode = disReadByte(pDis, offRet);
2218 offRet++;
2219 pOp = &g_aTwoByteMapX86_3DNow[opcode];
2220
2221 size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
2222
2223 AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
2224 ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
2225 NOREF(offStrict);
2226
2227 return offRet;
2228}
2229//*****************************************************************************
2230//*****************************************************************************
2231static size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2232{
2233 NOREF(pParam);
2234
2235 uint8_t modrm = disReadByte(pDis, offInstr);
2236 uint8_t reg = MODRM_REG(modrm);
2237
2238 pOp = &g_aMapX86_Group6[reg];
2239
2240 return disParseInstruction(offInstr, pOp, pDis);
2241}
2242//*****************************************************************************
2243//*****************************************************************************
2244static size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2245{
2246 NOREF(pParam);
2247
2248 uint8_t modrm = disReadByte(pDis, offInstr);
2249 uint8_t mod = MODRM_MOD(modrm);
2250 uint8_t reg = MODRM_REG(modrm);
2251 uint8_t rm = MODRM_RM(modrm);
2252
2253 if (mod == 3 && rm == 0)
2254 pOp = &g_aMapX86_Group7_mod11_rm000[reg];
2255 else
2256 if (mod == 3 && rm == 1)
2257 pOp = &g_aMapX86_Group7_mod11_rm001[reg];
2258 else
2259 pOp = &g_aMapX86_Group7_mem[reg];
2260
2261 /* Cannot easily skip this hack because of monitor and vmcall! */
2262 //little hack to make sure the ModRM byte is included in the returned size
2263 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2264 offInstr++;
2265
2266 return disParseInstruction(offInstr, pOp, pDis);
2267}
2268//*****************************************************************************
2269//*****************************************************************************
2270static size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2271{
2272 NOREF(pParam);
2273
2274 uint8_t modrm = disReadByte(pDis, offInstr);
2275 uint8_t reg = MODRM_REG(modrm);
2276
2277 pOp = &g_aMapX86_Group8[reg];
2278
2279 return disParseInstruction(offInstr, pOp, pDis);
2280}
2281//*****************************************************************************
2282//*****************************************************************************
2283static size_t ParseGrp9(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
2290 pOp = &g_aMapX86_Group9[reg];
2291
2292 return disParseInstruction(offInstr, pOp, pDis);
2293}
2294//*****************************************************************************
2295//*****************************************************************************
2296static size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2297{
2298 NOREF(pParam);
2299
2300 uint8_t modrm = disReadByte(pDis, offInstr);
2301 uint8_t reg = MODRM_REG(modrm);
2302
2303 pOp = &g_aMapX86_Group10[reg];
2304
2305 return disParseInstruction(offInstr, pOp, pDis);
2306}
2307//*****************************************************************************
2308//*****************************************************************************
2309static size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2310{
2311 NOREF(pParam);
2312
2313 uint8_t modrm = disReadByte(pDis, offInstr);
2314 uint8_t reg = MODRM_REG(modrm);
2315
2316 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2317 reg += 8; /* 2nd table */
2318
2319 pOp = &g_aMapX86_Group12[reg];
2320
2321 return disParseInstruction(offInstr, pOp, pDis);
2322}
2323//*****************************************************************************
2324//*****************************************************************************
2325static size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2326{
2327 NOREF(pParam);
2328
2329 uint8_t modrm = disReadByte(pDis, offInstr);
2330 uint8_t reg = MODRM_REG(modrm);
2331 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2332 reg += 8; /* 2nd table */
2333
2334 pOp = &g_aMapX86_Group13[reg];
2335
2336 return disParseInstruction(offInstr, pOp, pDis);
2337}
2338//*****************************************************************************
2339//*****************************************************************************
2340static size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2341{
2342 NOREF(pParam);
2343
2344 uint8_t modrm = disReadByte(pDis, offInstr);
2345 uint8_t reg = MODRM_REG(modrm);
2346 if (pDis->fPrefix & DISPREFIX_OPSIZE)
2347 reg += 8; /* 2nd table */
2348
2349 pOp = &g_aMapX86_Group14[reg];
2350
2351 return disParseInstruction(offInstr, pOp, pDis);
2352}
2353//*****************************************************************************
2354//*****************************************************************************
2355static size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2356{
2357 NOREF(pParam);
2358
2359 uint8_t modrm = disReadByte(pDis, offInstr);
2360 uint8_t mod = MODRM_MOD(modrm);
2361 uint8_t reg = MODRM_REG(modrm);
2362 uint8_t rm = MODRM_RM(modrm);
2363
2364 if (mod == 3 && rm == 0)
2365 pOp = &g_aMapX86_Group15_mod11_rm000[reg];
2366 else
2367 pOp = &g_aMapX86_Group15_mem[reg];
2368
2369 return disParseInstruction(offInstr, pOp, pDis);
2370}
2371//*****************************************************************************
2372//*****************************************************************************
2373static size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2374{
2375 NOREF(pParam);
2376
2377 uint8_t modrm = disReadByte(pDis, offInstr);
2378 pOp = &g_aMapX86_Group16[MODRM_REG(modrm)];
2379
2380 return disParseInstruction(offInstr, pOp, pDis);
2381}
2382
2383
2384
2385/**
2386 * Validates the lock sequence.
2387 *
2388 * The AMD manual lists the following instructions:
2389 * ADC
2390 * ADD
2391 * AND
2392 * BTC
2393 * BTR
2394 * BTS
2395 * CMPXCHG
2396 * CMPXCHG8B
2397 * CMPXCHG16B
2398 * DEC
2399 * INC
2400 * NEG
2401 * NOT
2402 * OR
2403 * SBB
2404 * SUB
2405 * XADD
2406 * XCHG
2407 * XOR
2408 *
2409 * @param pDis Fully disassembled instruction.
2410 */
2411static void disValidateLockSequence(PDISSTATE pDis)
2412{
2413 Assert(pDis->fPrefix & DISPREFIX_LOCK);
2414
2415 /*
2416 * Filter out the valid lock sequences.
2417 */
2418 switch (pDis->pCurInstr->uOpcode)
2419 {
2420 /* simple: no variations */
2421 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2422 return;
2423
2424 /* simple: /r - reject register destination. */
2425 case OP_BTC:
2426 case OP_BTR:
2427 case OP_BTS:
2428 case OP_CMPXCHG:
2429 case OP_XADD:
2430 if (pDis->ModRM.Bits.Mod == 3)
2431 break;
2432 return;
2433
2434 /*
2435 * Lots of variants but its sufficient to check that param 1
2436 * is a memory operand.
2437 */
2438 case OP_ADC:
2439 case OP_ADD:
2440 case OP_AND:
2441 case OP_DEC:
2442 case OP_INC:
2443 case OP_NEG:
2444 case OP_NOT:
2445 case OP_OR:
2446 case OP_SBB:
2447 case OP_SUB:
2448 case OP_XCHG:
2449 case OP_XOR:
2450 if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
2451 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
2452 return;
2453 break;
2454
2455 default:
2456 break;
2457 }
2458
2459 /*
2460 * Invalid lock sequence, make it a OP_ILLUD2.
2461 */
2462 pDis->pCurInstr = &g_aTwoByteMapX86[11];
2463 Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
2464}
2465
2466
2467/**
2468 * Internal worker for DISInstrEx and DISInstrWithPrefetchedBytes.
2469 *
2470 * @returns VBox status code.
2471 * @param pDis Initialized disassembler state.
2472 * @param paOneByteMap The one byte opcode map to use.
2473 * @param pcbInstr Where to store the instruction size. Can be NULL.
2474 */
2475static int disInstrWorker(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
2476{
2477 /*
2478 * Parse byte by byte.
2479 */
2480 size_t offInstr = 0;
2481 for (;;)
2482 {
2483 uint8_t codebyte = disReadByte(pDis, offInstr++);
2484 uint8_t opcode = paOneByteMap[codebyte].uOpcode;
2485
2486 /* Hardcoded assumption about OP_* values!! */
2487 if (opcode <= OP_LAST_PREFIX)
2488 {
2489 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
2490 if (opcode != OP_REX)
2491 {
2492 /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
2493 pDis->bLastPrefix = opcode;
2494 pDis->fPrefix &= ~DISPREFIX_REX;
2495 }
2496
2497 switch (opcode)
2498 {
2499 case OP_INVALID:
2500 if (pcbInstr)
2501 *pcbInstr = (uint32_t)offInstr;
2502 return pDis->rc = VERR_DIS_INVALID_OPCODE;
2503
2504 // segment override prefix byte
2505 case OP_SEG:
2506 pDis->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].fParam1 - OP_PARM_REG_SEG_START);
2507#if 0 /* Try be accurate in our reporting, shouldn't break anything... :-) */
2508 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
2509 if ( pDis->uCpuMode != DISCPUMODE_64BIT
2510 || pDis->idxSegPrefix >= DISSELREG_FS)
2511 pDis->fPrefix |= DISPREFIX_SEG;
2512#else
2513 pDis->fPrefix |= DISPREFIX_SEG;
2514#endif
2515 continue; //fetch the next byte
2516
2517 // lock prefix byte
2518 case OP_LOCK:
2519 pDis->fPrefix |= DISPREFIX_LOCK;
2520 continue; //fetch the next byte
2521
2522 // address size override prefix byte
2523 case OP_ADDRSIZE:
2524 pDis->fPrefix |= DISPREFIX_ADDRSIZE;
2525 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2526 pDis->uAddrMode = DISCPUMODE_32BIT;
2527 else
2528 if (pDis->uCpuMode == DISCPUMODE_32BIT)
2529 pDis->uAddrMode = DISCPUMODE_16BIT;
2530 else
2531 pDis->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
2532 continue; //fetch the next byte
2533
2534 // operand size override prefix byte
2535 case OP_OPSIZE:
2536 pDis->fPrefix |= DISPREFIX_OPSIZE;
2537 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2538 pDis->uOpMode = DISCPUMODE_32BIT;
2539 else
2540 pDis->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2541 continue; //fetch the next byte
2542
2543 // rep and repne are not really prefixes, but we'll treat them as such
2544 case OP_REPE:
2545 pDis->fPrefix |= DISPREFIX_REP;
2546 continue; //fetch the next byte
2547
2548 case OP_REPNE:
2549 pDis->fPrefix |= DISPREFIX_REPNE;
2550 continue; //fetch the next byte
2551
2552 case OP_REX:
2553 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
2554 /* REX prefix byte */
2555 pDis->fPrefix |= DISPREFIX_REX;
2556 pDis->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].fParam1);
2557 if (pDis->fRexPrefix & DISPREFIX_REX_FLAGS_W)
2558 pDis->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
2559 continue; //fetch the next byte
2560 }
2561 }
2562
2563 /* first opcode byte. */
2564 pDis->bOpCode = codebyte;
2565 pDis->cbPrefix = (uint8_t)offInstr - 1;
2566 offInstr = disParseInstruction(offInstr, &paOneByteMap[pDis->bOpCode], pDis);
2567 break;
2568 }
2569
2570 pDis->cbInstr = (uint8_t)offInstr;
2571 if (pcbInstr)
2572 *pcbInstr = (uint32_t)offInstr;
2573
2574 if (pDis->fPrefix & DISPREFIX_LOCK)
2575 disValidateLockSequence(pDis);
2576
2577 return pDis->rc;
2578}
2579
2580
2581/**
2582 * Inlined worker that initializes the disassembler state.
2583 *
2584 * @returns The primary opcode map to use.
2585 * @param pDis The disassembler state.
2586 * @param uInstrAddr The instruction address.
2587 * @param enmCpuMode The CPU mode.
2588 * @param fFilter The instruction filter settings.
2589 * @param pfnReadBytes The byte reader, can be NULL.
2590 * @param pvUser The the user data for the reader.
2591 */
2592DECL_FORCE_INLINE(PCDISOPCODE)
2593disInitializeState(PDISSTATE pDis, RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2594 PFNDISREADBYTES pfnReadBytes, void *pvUser)
2595{
2596 RT_ZERO(*pDis);
2597
2598#ifdef VBOX_STRICT /* poison */
2599 pDis->Param1.Base.idxGenReg = 0xc1;
2600 pDis->Param2.Base.idxGenReg = 0xc2;
2601 pDis->Param3.Base.idxGenReg = 0xc3;
2602 pDis->Param1.Index.idxGenReg = 0xc4;
2603 pDis->Param2.Index.idxGenReg = 0xc5;
2604 pDis->Param3.Index.idxGenReg = 0xc6;
2605 pDis->Param1.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
2606 pDis->Param2.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
2607 pDis->Param3.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
2608 pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
2609 pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
2610 pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
2611 pDis->Param1.uScale = 28;
2612 pDis->Param2.uScale = 29;
2613 pDis->Param3.uScale = 30;
2614#endif
2615
2616 pDis->fPrefix = DISPREFIX_NONE;
2617 pDis->idxSegPrefix = DISSELREG_DS;
2618 pDis->rc = VINF_SUCCESS;
2619 pDis->pfnDisasmFnTable = g_apfnFullDisasm;
2620
2621 pDis->uInstrAddr = uInstrAddr;
2622 pDis->fFilter = fFilter;
2623 pDis->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
2624 pDis->pvUser = pvUser;
2625 pDis->uCpuMode = enmCpuMode;
2626 PCDISOPCODE paOneByteMap;
2627 if (enmCpuMode == DISCPUMODE_64BIT)
2628 {
2629 pDis->uAddrMode = DISCPUMODE_64BIT;
2630 pDis->uOpMode = DISCPUMODE_32BIT;
2631 paOneByteMap = g_aOneByteMapX64;
2632 }
2633 else
2634 {
2635 pDis->uAddrMode = enmCpuMode;
2636 pDis->uOpMode = enmCpuMode;
2637 paOneByteMap = g_aOneByteMapX86;
2638 }
2639 return paOneByteMap;
2640}
2641
2642
2643/**
2644 * Reads some bytes into the cache.
2645 *
2646 * While this will set DISSTATE::rc on failure, the caller should disregard
2647 * this since that is what would happen if we didn't prefetch bytes prior to the
2648 * instruction parsing.
2649 *
2650 * @param pDis The disassembler state.
2651 */
2652DECL_FORCE_INLINE(void) disPrefetchBytes(PDISSTATE pDis)
2653{
2654 /*
2655 * Read some bytes into the cache. (If this fail we continue as nothing
2656 * has gone wrong since this is what would happen if we didn't precharge
2657 * the cache here.)
2658 */
2659 int rc = pDis->pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
2660 if (RT_SUCCESS(rc))
2661 {
2662 Assert(pDis->cbCachedInstr >= 1);
2663 Assert(pDis->cbCachedInstr <= sizeof(pDis->abInstr));
2664 }
2665 else
2666 {
2667 Log(("Initial read failed with rc=%Rrc!!\n", rc));
2668 pDis->rc = rc;
2669 }
2670}
2671
2672
2673/**
2674 * Disassembles on instruction, details in @a pDis and length in @a pcbInstr.
2675 *
2676 * @returns VBox status code.
2677 * @param uInstrAddr Address of the instruction to decode. What this means
2678 * is left to the pfnReadBytes function.
2679 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2680 * @param pfnReadBytes Callback for reading instruction bytes.
2681 * @param fFilter Instruction type filter.
2682 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2683 * @param pDis Pointer to disassembler state (output).
2684 * @param pcbInstr Where to store the size of the instruction. (This
2685 * is also stored in PDISSTATE::cbInstr.) Optional.
2686 */
2687DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2688 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2689 PDISSTATE pDis, uint32_t *pcbInstr)
2690{
2691
2692 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2693 disPrefetchBytes(pDis);
2694 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2695}
2696
2697
2698/**
2699 * Disassembles on instruction partially or fully from prefetched bytes, details
2700 * in @a pDis and length in @a pcbInstr.
2701 *
2702 * @returns VBox status code.
2703 * @param uInstrAddr Address of the instruction to decode. What this means
2704 * is left to the pfnReadBytes function.
2705 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2706 * @param pvPrefetched Pointer to the prefetched bytes.
2707 * @param cbPrefetched The number of valid bytes pointed to by @a
2708 * pbPrefetched.
2709 * @param pfnReadBytes Callback for reading instruction bytes.
2710 * @param fFilter Instruction type filter.
2711 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2712 * @param pDis Pointer to disassembler state (output).
2713 * @param pcbInstr Where to store the size of the instruction. (This
2714 * is also stored in PDISSTATE::cbInstr.) Optional.
2715 */
2716DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
2717 void const *pvPrefetched, size_t cbPretched,
2718 PFNDISREADBYTES pfnReadBytes, void *pvUser,
2719 PDISSTATE pDis, uint32_t *pcbInstr)
2720{
2721 PCDISOPCODE paOneByteMap = disInitializeState(pDis, uInstrAddr, enmCpuMode, fFilter, pfnReadBytes, pvUser);
2722
2723 if (!cbPretched)
2724 disPrefetchBytes(pDis);
2725 else
2726 {
2727 if (cbPretched >= sizeof(pDis->abInstr))
2728 {
2729 memcpy(pDis->abInstr, pvPrefetched, sizeof(pDis->abInstr));
2730 pDis->cbCachedInstr = (uint8_t)sizeof(pDis->abInstr);
2731 }
2732 else
2733 {
2734 memcpy(pDis->abInstr, pvPrefetched, cbPretched);
2735 pDis->cbCachedInstr = (uint8_t)cbPretched;
2736 }
2737 }
2738
2739 return disInstrWorker(pDis, paOneByteMap, pcbInstr);
2740}
2741
2742
2743
2744/**
2745 * Parses one guest instruction.
2746 *
2747 * The result is found in pDis and pcbInstr.
2748 *
2749 * @returns VBox status code.
2750 * @param uInstrAddr Address of the instruction to decode. What this means
2751 * is left to the pfnReadBytes function.
2752 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2753 * @param pfnReadBytes Callback for reading instruction bytes.
2754 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2755 * @param pDis Pointer to disassembler state (output).
2756 * @param pcbInstr Where to store the size of the instruction.
2757 * NULL is allowed. This is also stored in
2758 * PDISSTATE::cbInstr.
2759 */
2760DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
2761 PDISSTATE pDis, uint32_t *pcbInstr)
2762{
2763 return DISInstrEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pDis, pcbInstr);
2764}
2765
2766
2767/**
2768 * Parses one guest instruction.
2769 *
2770 * The result is found in pDis and pcbInstr.
2771 *
2772 * @returns VBox status code.
2773 * @param pvInstr Address of the instruction to decode. This is a
2774 * real address in the current context that can be
2775 * accessed without faulting. (Consider
2776 * DISInstrWithReader if this isn't the case.)
2777 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
2778 * @param pfnReadBytes Callback for reading instruction bytes.
2779 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
2780 * @param pDis Pointer to disassembler state (output).
2781 * @param pcbInstr Where to store the size of the instruction.
2782 * NULL is allowed. This is also stored in
2783 * PDISSTATE::cbInstr.
2784 */
2785DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr)
2786{
2787 return DISInstrEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pDis, pcbInstr);
2788}
2789
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