VirtualBox

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

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

DIS,CSAM: Drop pvUser2.

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