VirtualBox

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

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

Encourage keeping things in the same registers across calls.

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

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