VirtualBox

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

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

DIS: Changed the parsers from returning size to the offset of the next opcode byte, i.e. offInstr+size.

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

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