VirtualBox

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

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

Fixed g_aTwoByteMapX86_3DNow bug and relaxed assertion in Parse3DNow.

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