VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmCore-x86-amd64.cpp@ 103717

Last change on this file since 103717 was 103717, checked in by vboxsync, 8 months ago

DIS: cmpxchg8b/16b fix

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

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