VirtualBox

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

Last change on this file was 103927, checked in by vboxsync, 8 weeks ago

VMM/IEM,DIS: Some disassembly corrections for pblendvb, blendvps and blendvpd. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.4 KB
Line 
1/* $Id: DisasmCore-x86-amd64.cpp 103927 2024-03-19 21:16:27Z 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 else if (pParam->x86.fParam <= OP_PARM_REG_SSE_END)
1530 {
1531 /* SSE registers. */
1532 pParam->x86.Base.idxFpuReg = (uint8_t)(pParam->x86.fParam - OP_PARM_REG_SSE_END);
1533 pParam->fUse |= DISUSE_REG_XMM;
1534 pParam->x86.cb = 16;
1535 }
1536 Assert(!(pParam->x86.fParam >= OP_PARM_REG_GEN64_START && pParam->x86.fParam <= OP_PARM_REG_GEN64_END));
1537
1538 /* else - not supported for now registers. */
1539
1540 return offInstr;
1541}
1542//*****************************************************************************
1543//*****************************************************************************
1544static size_t ParseXv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1545{
1546 RT_NOREF_PV(pOp);
1547
1548 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1549 if (pDis->x86.uAddrMode == DISCPUMODE_32BIT)
1550 {
1551 pParam->x86.Base.idxGenReg = DISGREG_ESI;
1552 pParam->fUse |= DISUSE_REG_GEN32;
1553 }
1554 else
1555 if (pDis->x86.uAddrMode == DISCPUMODE_64BIT)
1556 {
1557 pParam->x86.Base.idxGenReg = DISGREG_RSI;
1558 pParam->fUse |= DISUSE_REG_GEN64;
1559 }
1560 else
1561 {
1562 pParam->x86.Base.idxGenReg = DISGREG_SI;
1563 pParam->fUse |= DISUSE_REG_GEN16;
1564 }
1565 return offInstr;
1566}
1567//*****************************************************************************
1568//*****************************************************************************
1569static size_t ParseXb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1570{
1571 RT_NOREF_PV(pOp);
1572
1573 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1574 if (pDis->x86.uAddrMode == DISCPUMODE_32BIT)
1575 {
1576 pParam->x86.Base.idxGenReg = DISGREG_ESI;
1577 pParam->fUse |= DISUSE_REG_GEN32;
1578 }
1579 else
1580 if (pDis->x86.uAddrMode == DISCPUMODE_64BIT)
1581 {
1582 pParam->x86.Base.idxGenReg = DISGREG_RSI;
1583 pParam->fUse |= DISUSE_REG_GEN64;
1584 }
1585 else
1586 {
1587 pParam->x86.Base.idxGenReg = DISGREG_SI;
1588 pParam->fUse |= DISUSE_REG_GEN16;
1589 }
1590 return offInstr;
1591}
1592//*****************************************************************************
1593//*****************************************************************************
1594static size_t ParseYv(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1595{
1596 RT_NOREF_PV(pOp);
1597
1598 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1599 if (pDis->x86.uAddrMode == DISCPUMODE_32BIT)
1600 {
1601 pParam->x86.Base.idxGenReg = DISGREG_EDI;
1602 pParam->fUse |= DISUSE_REG_GEN32;
1603 }
1604 else
1605 if (pDis->x86.uAddrMode == DISCPUMODE_64BIT)
1606 {
1607 pParam->x86.Base.idxGenReg = DISGREG_RDI;
1608 pParam->fUse |= DISUSE_REG_GEN64;
1609 }
1610 else
1611 {
1612 pParam->x86.Base.idxGenReg = DISGREG_DI;
1613 pParam->fUse |= DISUSE_REG_GEN16;
1614 }
1615 return offInstr;
1616}
1617//*****************************************************************************
1618//*****************************************************************************
1619static size_t ParseYb(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1620{
1621 RT_NOREF_PV(pOp);
1622
1623 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1624 if (pDis->x86.uAddrMode == DISCPUMODE_32BIT)
1625 {
1626 pParam->x86.Base.idxGenReg = DISGREG_EDI;
1627 pParam->fUse |= DISUSE_REG_GEN32;
1628 }
1629 else
1630 if (pDis->x86.uAddrMode == DISCPUMODE_64BIT)
1631 {
1632 pParam->x86.Base.idxGenReg = DISGREG_RDI;
1633 pParam->fUse |= DISUSE_REG_GEN64;
1634 }
1635 else
1636 {
1637 pParam->x86.Base.idxGenReg = DISGREG_DI;
1638 pParam->fUse |= DISUSE_REG_GEN16;
1639 }
1640 return offInstr;
1641}
1642//*****************************************************************************
1643//*****************************************************************************
1644static size_t ParseInvOpModRm(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1645{
1646 RT_NOREF_PV(pOp); RT_NOREF_PV(pDis); RT_NOREF_PV(pParam);
1647 /* This is used to avoid a bunch of special hacks to get the ModRM byte
1648 included when encountering invalid opcodes in groups. */
1649 return offInstr + 1;
1650}
1651//*****************************************************************************
1652//*****************************************************************************
1653static size_t ParseVexDest(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1654{
1655 RT_NOREF_PV(pOp);
1656
1657 unsigned type = OP_PARM_VTYPE(pParam->x86.fParam);
1658 switch (type)
1659 {
1660 case OP_PARM_H: //XMM or YMM register
1661 if (VEXREG_IS256B(pDis->x86.bVexDestReg))
1662 {
1663 pParam->fUse |= DISUSE_REG_YMM;
1664 pParam->x86.Base.idxYmmReg = (pDis->x86.bVexDestReg >> 1) ^ 0xf;
1665 }
1666 else
1667 {
1668 pParam->fUse |= DISUSE_REG_XMM;
1669 pParam->x86.Base.idxXmmReg = (pDis->x86.bVexDestReg >> 1) ^ 0xf;
1670 }
1671 break;
1672
1673 case OP_PARM_B: // Always OP_PARM_By. Change if it is not so.
1674 if ((pDis->x86.bVexByte2 & DISPREFIX_VEX_F_W) && pDis->uCpuMode == DISCPUMODE_64BIT)
1675 pParam->fUse |= DISUSE_REG_GEN64;
1676 else
1677 pParam->fUse |= DISUSE_REG_GEN32;
1678 /// @todo Check if the register number is correct
1679 pParam->x86.Base.idxGenReg = (pDis->x86.bVexDestReg >> 1) ^ 0xf;
1680 break;
1681 }
1682
1683 return offInstr;
1684}
1685//*****************************************************************************
1686//*****************************************************************************
1687static size_t ParseTwoByteEsc(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1688{
1689 RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
1690
1691 /* 2nd byte */
1692 pDis->x86.bOpCode = disReadByte(pDis, offInstr);
1693 offInstr++;
1694
1695 /* default to the non-prefixed table. */
1696 PCDISOPCODE pOpcode = &g_aTwoByteMapX86[pDis->x86.bOpCode];
1697
1698 /* Handle opcode table extensions that rely on the opsize, repe or repne prefix byte. */
1699 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1700 if (pDis->x86.bLastPrefix)
1701 {
1702 switch (pDis->x86.bLastPrefix)
1703 {
1704 case OP_OPSIZE: /* 0x66 */
1705 if (g_aTwoByteMapX86_PF66[pDis->x86.bOpCode].uOpcode != OP_INVALID)
1706 {
1707 /* Table entry is valid, so use the extension table. */
1708 pOpcode = &g_aTwoByteMapX86_PF66[pDis->x86.bOpCode];
1709
1710 /* Cancel prefix changes. */
1711 pDis->x86.fPrefix &= ~DISPREFIX_OPSIZE;
1712
1713 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1714 pDis->x86.uOpMode = (pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
1715 else
1716 pDis->x86.uOpMode = pDis->uCpuMode;
1717 }
1718 break;
1719
1720 case OP_REPNE: /* 0xF2 */
1721 if (g_aTwoByteMapX86_PFF2[pDis->x86.bOpCode].uOpcode != OP_INVALID)
1722 {
1723 /* Table entry is valid, so use the extension table. */
1724 pOpcode = &g_aTwoByteMapX86_PFF2[pDis->x86.bOpCode];
1725
1726 /* Cancel prefix changes. */
1727 pDis->x86.fPrefix &= ~DISPREFIX_REPNE;
1728 }
1729 break;
1730
1731 case OP_REPE: /* 0xF3 */
1732 if (g_aTwoByteMapX86_PFF3[pDis->x86.bOpCode].uOpcode != OP_INVALID)
1733 {
1734 /* Table entry is valid, so use the extension table. */
1735 pOpcode = &g_aTwoByteMapX86_PFF3[pDis->x86.bOpCode];
1736
1737 /* Cancel prefix changes. */
1738 pDis->x86.fPrefix &= ~DISPREFIX_REP;
1739 }
1740 break;
1741 }
1742 }
1743
1744 return disParseInstruction(offInstr, pOpcode, pDis);
1745}
1746//*****************************************************************************
1747//*****************************************************************************
1748static size_t ParseThreeByteEsc4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1749{
1750 RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
1751
1752 /* 3rd byte */
1753 pDis->x86.bOpCode = disReadByte(pDis, offInstr);
1754 offInstr++;
1755
1756 /* default to the non-prefixed table. */
1757 PCDISOPCODE pOpcode;
1758 if (g_apThreeByteMapX86_0F38[pDis->x86.bOpCode >> 4])
1759 {
1760 pOpcode = g_apThreeByteMapX86_0F38[pDis->x86.bOpCode >> 4];
1761 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1762 }
1763 else
1764 pOpcode = &g_InvalidOpcode[0];
1765
1766 /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1767 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1768 switch (pDis->x86.bLastPrefix)
1769 {
1770 case OP_OPSIZE: /* 0x66 */
1771 if (g_apThreeByteMapX86_660F38[pDis->x86.bOpCode >> 4])
1772 {
1773 pOpcode = g_apThreeByteMapX86_660F38[pDis->x86.bOpCode >> 4];
1774 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1775
1776 if (pOpcode->uOpcode != OP_INVALID)
1777 {
1778 /* Table entry is valid, so use the extension table. */
1779
1780 /* Cancel prefix changes. */
1781 pDis->x86.fPrefix &= ~DISPREFIX_OPSIZE;
1782 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1783 pDis->x86.uOpMode = (pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
1784 else
1785 pDis->x86.uOpMode = pDis->uCpuMode;
1786
1787 }
1788 }
1789 break;
1790
1791 case OP_REPNE: /* 0xF2 */
1792 if ((pDis->x86.fPrefix & DISPREFIX_OPSIZE) && g_apThreeByteMapX86_66F20F38[pDis->x86.bOpCode >> 4])
1793 {
1794 /* 0x66F2 */
1795 pOpcode = g_apThreeByteMapX86_66F20F38[pDis->x86.bOpCode >> 4];
1796 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1797
1798 if (pOpcode->uOpcode != OP_INVALID)
1799 {
1800 /* Table entry is valid, so use the extension table. */
1801
1802 /* Cancel prefix changes. */
1803 pDis->x86.fPrefix &= ~DISPREFIX_REPNE;
1804 pDis->x86.fPrefix &= ~DISPREFIX_OPSIZE;
1805 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1806 pDis->x86.uOpMode = (pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
1807 else
1808 pDis->x86.uOpMode = pDis->uCpuMode;
1809 }
1810 }
1811 else if (g_apThreeByteMapX86_F20F38[pDis->x86.bOpCode >> 4])
1812 {
1813 pOpcode = g_apThreeByteMapX86_F20F38[pDis->x86.bOpCode >> 4];
1814 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1815
1816 if (pOpcode->uOpcode != OP_INVALID)
1817 {
1818 /* Table entry is valid, so use the extension table. */
1819
1820 /* Cancel prefix changes. */
1821 pDis->x86.fPrefix &= ~DISPREFIX_REPNE;
1822 }
1823 }
1824 break;
1825
1826 case OP_REPE: /* 0xF3 */
1827 if (g_apThreeByteMapX86_F30F38[pDis->x86.bOpCode >> 4])
1828 {
1829 pOpcode = g_apThreeByteMapX86_F30F38[pDis->x86.bOpCode >> 4];
1830 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1831
1832 if (pOpcode->uOpcode != OP_INVALID)
1833 {
1834 /* Table entry is valid, so use the extension table. */
1835
1836 /* Cancel prefix changes. */
1837 pDis->x86.fPrefix &= ~DISPREFIX_REP;
1838 }
1839 }
1840 }
1841
1842 return disParseInstruction(offInstr, pOpcode, pDis);
1843}
1844//*****************************************************************************
1845//*****************************************************************************
1846static size_t ParseThreeByteEsc5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1847{
1848 RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
1849
1850 /* 3rd byte */
1851 pDis->x86.bOpCode = disReadByte(pDis, offInstr);
1852 offInstr++;
1853
1854 /* default to the non-prefixed table. */
1855 PCDISOPCODE pOpcode;
1856 if (g_apThreeByteMapX86_0F3A[pDis->x86.bOpCode >> 4])
1857 {
1858 pOpcode = g_apThreeByteMapX86_0F3A[pDis->x86.bOpCode >> 4];
1859 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1860 }
1861 else
1862 pOpcode = &g_InvalidOpcode[0];
1863
1864 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1865 if (pDis->x86.bLastPrefix == OP_OPSIZE && g_apThreeByteMapX86_660F3A[pDis->x86.bOpCode >> 4])
1866 {
1867 pOpcode = g_apThreeByteMapX86_660F3A[pDis->x86.bOpCode >> 4];
1868 pOpcode = &pOpcode[pDis->x86.bOpCode & 0xf];
1869
1870 if (pOpcode->uOpcode != OP_INVALID)
1871 {
1872 /* Table entry is valid, so use the extension table. */
1873
1874 /* Cancel prefix changes. */
1875 pDis->x86.fPrefix &= ~DISPREFIX_OPSIZE;
1876 if (pDis->uCpuMode == DISCPUMODE_64BIT)
1877 pDis->x86.uOpMode = (pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_W ? DISCPUMODE_64BIT : DISCPUMODE_32BIT);
1878 else
1879 pDis->x86.uOpMode = pDis->uCpuMode;
1880 }
1881 }
1882
1883 return disParseInstruction(offInstr, pOpcode, pDis);
1884}
1885//*****************************************************************************
1886//*****************************************************************************
1887static size_t ParseNopPause(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1888{
1889 RT_NOREF_PV(pParam);
1890
1891 if (pDis->x86.fPrefix & DISPREFIX_REP)
1892 {
1893 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1894 pDis->x86.fPrefix &= ~DISPREFIX_REP;
1895 }
1896 else
1897 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1898
1899 return disParseInstruction(offInstr, pOp, pDis);
1900}
1901//*****************************************************************************
1902//*****************************************************************************
1903static size_t ParseGrp1(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1904{
1905 RT_NOREF_PV(pParam);
1906
1907 uint8_t modrm = disReadByte(pDis, offInstr);
1908 uint8_t reg = MODRM_REG(modrm);
1909 unsigned idx = (pDis->x86.bOpCode - 0x80) * 8;
1910
1911 pOp = &g_aMapX86_Group1[idx+reg];
1912
1913 return disParseInstruction(offInstr, pOp, pDis);
1914}
1915//*****************************************************************************
1916//*****************************************************************************
1917static size_t ParseShiftGrp2(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1918{
1919 RT_NOREF_PV(pParam);
1920
1921 unsigned idx;
1922 switch (pDis->x86.bOpCode)
1923 {
1924 case 0xC0:
1925 case 0xC1:
1926 idx = (pDis->x86.bOpCode - 0xC0)*8;
1927 break;
1928
1929 case 0xD0:
1930 case 0xD1:
1931 case 0xD2:
1932 case 0xD3:
1933 idx = (pDis->x86.bOpCode - 0xD0 + 2)*8;
1934 break;
1935
1936 default:
1937 Log(("ParseShiftGrp2: bOpCode=%#x\n", pDis->x86.bOpCode));
1938 pDis->rc = VERR_DIS_INVALID_OPCODE;
1939 return offInstr;
1940 }
1941
1942 uint8_t modrm = disReadByte(pDis, offInstr);
1943 uint8_t reg = MODRM_REG(modrm);
1944
1945 pOp = &g_aMapX86_Group2[idx+reg];
1946
1947 return disParseInstruction(offInstr, pOp, pDis);
1948}
1949//*****************************************************************************
1950//*****************************************************************************
1951static size_t ParseGrp3(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1952{
1953 unsigned idx = (pDis->x86.bOpCode - 0xF6) * 8;
1954 RT_NOREF_PV(pParam);
1955
1956 uint8_t modrm = disReadByte(pDis, offInstr);
1957 uint8_t reg = MODRM_REG(modrm);
1958
1959 pOp = &g_aMapX86_Group3[idx+reg];
1960
1961 return disParseInstruction(offInstr, pOp, pDis);
1962}
1963//*****************************************************************************
1964//*****************************************************************************
1965static size_t ParseGrp4(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1966{
1967 RT_NOREF_PV(pParam);
1968
1969 uint8_t modrm = disReadByte(pDis, offInstr);
1970 uint8_t reg = MODRM_REG(modrm);
1971
1972 pOp = &g_aMapX86_Group4[reg];
1973
1974 return disParseInstruction(offInstr, pOp, pDis);
1975}
1976//*****************************************************************************
1977//*****************************************************************************
1978static size_t ParseGrp5(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1979{
1980 RT_NOREF_PV(pParam);
1981
1982 uint8_t modrm = disReadByte(pDis, offInstr);
1983 uint8_t reg = MODRM_REG(modrm);
1984
1985 pOp = &g_aMapX86_Group5[reg];
1986
1987 return disParseInstruction(offInstr, pOp, pDis);
1988}
1989//*****************************************************************************
1990// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
1991// It would appear the ModRM byte must always be present. How else can you
1992// determine the offset of the imm8_opcode byte otherwise?
1993//
1994//*****************************************************************************
1995static size_t Parse3DNow(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
1996{
1997 /** @todo This code needs testing! Esp. wrt invalid opcodes. */
1998
1999 uint8_t ModRM = disReadByte(pDis, offInstr);
2000 pDis->x86.ModRM.Bits.Rm = MODRM_RM(ModRM);
2001 pDis->x86.ModRM.Bits.Mod = MODRM_MOD(ModRM);
2002 pDis->x86.ModRM.Bits.Reg = MODRM_REG(ModRM);
2003
2004 size_t offRet = QueryModRM(offInstr + 1, pOp, pDis, pParam);
2005
2006 uint8_t opcode = disReadByte(pDis, offRet);
2007 offRet++;
2008 pOp = &g_aTwoByteMapX86_3DNow[opcode];
2009
2010 size_t offStrict = disParseInstruction(offInstr, pOp, pDis);
2011
2012 AssertMsg(offStrict == offRet - 1 /* the imm8_opcode */ || pOp->uOpcode == OP_INVALID,
2013 ("offStrict=%#x offRet=%#x uOpCode=%u\n", offStrict, offRet, pOp->uOpcode));
2014 RT_NOREF_PV(offStrict);
2015
2016 return offRet;
2017}
2018//*****************************************************************************
2019//*****************************************************************************
2020static size_t ParseGrp6(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2021{
2022 RT_NOREF_PV(pParam);
2023
2024 uint8_t modrm = disReadByte(pDis, offInstr);
2025 uint8_t reg = MODRM_REG(modrm);
2026
2027 pOp = &g_aMapX86_Group6[reg];
2028
2029 return disParseInstruction(offInstr, pOp, pDis);
2030}
2031//*****************************************************************************
2032//*****************************************************************************
2033static size_t ParseGrp7(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2034{
2035 RT_NOREF_PV(pParam);
2036
2037 uint8_t modrm = disReadByte(pDis, offInstr);
2038 uint8_t mod = MODRM_MOD(modrm);
2039 uint8_t reg = MODRM_REG(modrm);
2040 uint8_t rm = MODRM_RM(modrm);
2041
2042 if (mod != 3)
2043 pOp = &g_aMapX86_Group7_mem[reg];
2044 else if (reg == 0)
2045 pOp = &g_aMapX86_Group7_mod11_reg000[rm];
2046 else if (reg == 1)
2047 pOp = &g_aMapX86_Group7_mod11_reg001[rm];
2048 else if (reg == 2)
2049 pOp = &g_aMapX86_Group7_mod11_reg010[rm];
2050 else if (reg == 7)
2051 pOp = &g_aMapX86_Group7_mod11_reg111[rm];
2052 else if (reg == 4 || reg == 6)
2053 pOp = &g_aMapX86_Group7_mem[reg];
2054 else
2055 pOp = &g_InvalidOpcode[0];
2056
2057 /* Cannot easily skip this hack because of monitor and vmcall! */
2058 //little hack to make sure the ModRM byte is included in the returned size
2059 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2060 offInstr++;
2061
2062 return disParseInstruction(offInstr, pOp, pDis);
2063}
2064//*****************************************************************************
2065//*****************************************************************************
2066static size_t ParseGrp8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2067{
2068 RT_NOREF_PV(pParam);
2069
2070 uint8_t modrm = disReadByte(pDis, offInstr);
2071 uint8_t reg = MODRM_REG(modrm);
2072
2073 pOp = &g_aMapX86_Group8[reg];
2074
2075 return disParseInstruction(offInstr, pOp, pDis);
2076}
2077//*****************************************************************************
2078//*****************************************************************************
2079static size_t ParseGrp9(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2080{
2081 RT_NOREF_PV(pParam);
2082
2083 uint8_t const bRm = disReadByte(pDis, offInstr);
2084 uint8_t idx = MODRM_REG(bRm);
2085 if (MODRM_MOD(bRm) != X86_MOD_REG)
2086 {
2087 if (pDis->x86.bLastPrefix == OP_OPSIZE /*0xf3*/)
2088 pOp = &g_aMapX86_Group9_mem_66[idx];
2089 else if (pDis->x86.bLastPrefix == OP_REPE /*0xf3*/)
2090 {
2091 pDis->x86.fPrefix &= ~DISPREFIX_REP;
2092 pOp = &g_aMapX86_Group9_mem_f3[idx];
2093 }
2094 /** @todo bLastPrefix is also set for OP_SEG & OP_ADDRSIZE which aren't relevant here or to any other of the table */
2095 else if (pDis->x86.bLastPrefix != OP_REPNE && (pDis->x86.bLastPrefix != OP_LOCK || idx == 1 /*cmpxchg8/16b*/))
2096 {
2097 if ((pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_W) && (pDis->x86.fPrefix & DISPREFIX_REX))
2098 idx += 8;
2099 pOp = &g_aMapX86_Group9_mem_none[idx];
2100 }
2101 else
2102 pOp = &g_InvalidOpcode[0];
2103 }
2104 else
2105 {
2106 if (pDis->x86.bLastPrefix == OP_REPE /*0xf3*/)
2107 {
2108 pDis->x86.fPrefix &= ~DISPREFIX_REP;
2109 pOp = &g_aMapX86_Group9_mod11_f3[idx];
2110 }
2111 /** @todo bLastPrefix is also set for OP_SEG & OP_ADDRSIZE which aren't relevant here or to any other of the table */
2112 else if (pDis->x86.bLastPrefix != OP_LOCK && pDis->x86.bLastPrefix != OP_REPNE)
2113 pOp = &g_aMapX86_Group9_mod11_none[idx];
2114 else
2115 pOp = &g_InvalidOpcode[0];
2116 }
2117
2118 return disParseInstruction(offInstr, pOp, pDis);
2119}
2120//*****************************************************************************
2121//*****************************************************************************
2122static size_t ParseGrp10(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2123{
2124 RT_NOREF_PV(pParam);
2125
2126 uint8_t modrm = disReadByte(pDis, offInstr);
2127 uint8_t reg = MODRM_REG(modrm);
2128
2129 pOp = &g_aMapX86_Group10[reg];
2130
2131 return disParseInstruction(offInstr, pOp, pDis);
2132}
2133
2134
2135/**
2136 * Parses non-vex group 12.
2137 */
2138static size_t ParseGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2139{
2140 RT_NOREF_PV(pParam);
2141
2142 uint8_t const bRm = disReadByte(pDis, offInstr);
2143 uint8_t idx = MODRM_REG(bRm);
2144 if (pDis->x86.fPrefix & DISPREFIX_OPSIZE)
2145 idx += 8; /* 2nd table */
2146 pOp = &g_aMapX86_Group12[idx];
2147
2148 return disParseInstruction(offInstr, pOp, pDis);
2149}
2150
2151
2152/**
2153 * Parses vex group 12.
2154 */
2155static size_t ParseVGrp12(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2156{
2157 RT_NOREF_PV(pParam);
2158
2159 uint8_t const bRm = disReadByte(pDis, offInstr);
2160 if ((pDis->x86.bVexByte2 & DISPREFIX_VEX_F_PP_MASK) == DISPREFIX_VEX_F_PP_66)
2161 pOp = &g_aMapX86_VGroup12[MODRM_REG(bRm)];
2162 else
2163 pOp = &g_InvalidOpcode[0];
2164
2165 return disParseInstruction(offInstr, pOp, pDis);
2166}
2167
2168
2169/**
2170 * Parses non-vex group 13.
2171 */
2172static size_t ParseGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2173{
2174 RT_NOREF_PV(pParam);
2175
2176 uint8_t const bRm = disReadByte(pDis, offInstr);
2177 uint8_t idx = MODRM_REG(bRm);
2178 if (pDis->x86.fPrefix & DISPREFIX_OPSIZE)
2179 idx += 8; /* 2nd table */
2180 pOp = &g_aMapX86_Group13[idx];
2181
2182 return disParseInstruction(offInstr, pOp, pDis);
2183}
2184
2185
2186/**
2187 * Parses vex group 13.
2188 */
2189static size_t ParseVGrp13(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2190{
2191 RT_NOREF_PV(pParam);
2192
2193 uint8_t const bRm = disReadByte(pDis, offInstr);
2194 if ((pDis->x86.bVexByte2 & DISPREFIX_VEX_F_PP_MASK) == DISPREFIX_VEX_F_PP_66)
2195 pOp = &g_aMapX86_VGroup13[MODRM_REG(bRm)];
2196 else
2197 pOp = &g_InvalidOpcode[0];
2198
2199 return disParseInstruction(offInstr, pOp, pDis);
2200}
2201
2202
2203/**
2204 * Parses non-vex group 14.
2205 */
2206static size_t ParseGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2207{
2208 RT_NOREF_PV(pParam);
2209
2210 uint8_t const bRm = disReadByte(pDis, offInstr);
2211 uint8_t idx = MODRM_REG(bRm);
2212 if (pDis->x86.fPrefix & DISPREFIX_OPSIZE)
2213 idx += 8; /* 2nd table */
2214 pOp = &g_aMapX86_Group14[idx];
2215
2216 return disParseInstruction(offInstr, pOp, pDis);
2217}
2218
2219
2220/**
2221 * Parses vex group 14.
2222 */
2223static size_t ParseVGrp14(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2224{
2225 RT_NOREF_PV(pParam);
2226
2227 uint8_t const bRm = disReadByte(pDis, offInstr);
2228 if ((pDis->x86.bVexByte2 & DISPREFIX_VEX_F_PP_MASK) == DISPREFIX_VEX_F_PP_66)
2229 pOp = &g_aMapX86_VGroup14[MODRM_REG(bRm)];
2230 else
2231 pOp = &g_InvalidOpcode[0];
2232
2233 return disParseInstruction(offInstr, pOp, pDis);
2234}
2235
2236
2237/**
2238 * Parses non-vex group 15.
2239 */
2240static size_t ParseGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2241{
2242 RT_NOREF_PV(pParam);
2243
2244 uint8_t const bRm = disReadByte(pDis, offInstr);
2245 uint8_t idx = MODRM_REG(bRm);
2246 if (MODRM_MOD(bRm) != X86_MOD_REG)
2247 pOp = &g_aMapX86_Group15_mem[idx];
2248 else if (pDis->x86.bLastPrefix == OP_REPE /*0xf3*/)
2249 {
2250 pDis->x86.fPrefix &= ~DISPREFIX_REP;
2251 pOp = &g_aMapX86_Group15_mod11[idx + 8];
2252 }
2253 /** @todo bLastPrefix is also set for OP_SEG & OP_ADDRSIZE which aren't relevant here or to any other of the table */
2254 else if (pDis->x86.bLastPrefix != OP_LOCK && pDis->x86.bLastPrefix != OP_REPNE && pDis->x86.bLastPrefix != OP_OPSIZE)
2255 pOp = &g_aMapX86_Group15_mod11[idx];
2256 else
2257 pOp = &g_InvalidOpcode[0];
2258
2259 return disParseInstruction(offInstr, pOp, pDis);
2260}
2261
2262
2263/**
2264 * Parses vex group 15.
2265 */
2266static size_t ParseVGrp15(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2267{
2268 RT_NOREF_PV(pParam);
2269
2270 uint8_t const bRm = disReadByte(pDis, offInstr);
2271 if ((pDis->x86.bVexByte2 & DISPREFIX_VEX_F_PP_MASK) == DISPREFIX_VEX_F_PP_NONE)
2272 pOp = &g_aMapX86_VGroup15[MODRM_REG(bRm)];
2273 else
2274 pOp = &g_InvalidOpcode[0];
2275
2276 return disParseInstruction(offInstr, pOp, pDis);
2277}
2278
2279
2280/**
2281 * Parses group 16.
2282 */
2283static size_t ParseGrp16(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2284{
2285 RT_NOREF_PV(pParam);
2286
2287 uint8_t const bRm = disReadByte(pDis, offInstr);
2288 pOp = &g_aMapX86_Group16[MODRM_REG(bRm)];
2289
2290 return disParseInstruction(offInstr, pOp, pDis);
2291}
2292
2293
2294/**
2295 * Parses (vex) group 17.
2296 */
2297static size_t ParseVGrp17(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2298{
2299 RT_NOREF_PV(pParam);
2300
2301 uint8_t const bRm = disReadByte(pDis, offInstr);
2302 pOp = &g_aMapX86_VGroup17[(MODRM_REG(bRm) << 1) | (pDis->x86.bVexDestReg & 1)];
2303
2304 return disParseInstruction(offInstr, pOp, pDis);
2305}
2306
2307
2308//*****************************************************************************
2309//*****************************************************************************
2310static size_t ParseVex2b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2311{
2312 RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
2313
2314 uint8_t const bVexByte = disReadByte(pDis, offInstr++);
2315 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2316 {
2317 // VEX.~R => REX.R
2318 if (!(bVexByte & 0x80))
2319 {
2320 pDis->x86.fPrefix |= DISPREFIX_REX;
2321 pDis->x86.fRexPrefix = DISPREFIX_REX_FLAGS_R;
2322 }
2323 }
2324 else if ((bVexByte & X86_MODRM_MOD_MASK) != (X86_MOD_REG << X86_MODRM_MOD_SHIFT))
2325 return disParseInstruction(offInstr - 1, &g_OpcodeLDS, pDis); /* LDS r,mem */
2326
2327 /* VEX2.byte1 is the same as VEX3.byte2 with the exception of the 7th bit (~R vs W). */
2328 pDis->x86.bVexByte2 = bVexByte & (DISPREFIX_VEX_F_PP_MASK | DISPREFIX_VEX_F_L | DISPREFIX_VEX_F_VVVV);
2329 pDis->x86.bVexDestReg = VEX_2B2INT(bVexByte);
2330 pDis->x86.bOpCode = disReadByte(pDis, offInstr++);
2331 pDis->x86.fPrefix |= DISPREFIX_VEX;
2332
2333 PCDISOPMAPDESC const pRange = g_aapVexOpcodesMapRanges[bVexByte & 3][1];
2334 unsigned const idxOpcode = pDis->x86.bOpCode - pRange->idxFirst;
2335 PCDISOPCODE pOpCode;
2336 if (idxOpcode < pRange->cOpcodes)
2337 pOpCode = &pRange->papOpcodes[idxOpcode];
2338 else
2339 pOpCode = &g_InvalidOpcode[0];
2340
2341 return disParseInstruction(offInstr, pOpCode, pDis);
2342}
2343//*****************************************************************************
2344//*****************************************************************************
2345static size_t ParseVex3b(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam)
2346{
2347 RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
2348
2349 uint8_t const bVexByte1 = disReadByte(pDis, offInstr++);
2350 if (pDis->uCpuMode == DISCPUMODE_64BIT)
2351 {
2352 // VEX.~R~X~B => REX.RXB
2353 pDis->x86.fRexPrefix |= (bVexByte1 >> 5) ^ 7;
2354 if (pDis->x86.fRexPrefix)
2355 pDis->x86.fPrefix |= DISPREFIX_REX;
2356 }
2357 else if ((bVexByte1 & X86_MODRM_MOD_MASK) != (X86_MOD_REG << X86_MODRM_MOD_SHIFT))
2358 return disParseInstruction(offInstr - 1, &g_OpcodeLES, pDis); /* LES r,mem */
2359
2360 uint8_t const bVexByte2 = disReadByte(pDis, offInstr++);
2361 pDis->x86.fPrefix |= DISPREFIX_VEX;
2362 pDis->x86.bVexByte2 = bVexByte2;
2363 pDis->x86.bOpCode = disReadByte(pDis, offInstr++);
2364 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! */
2365
2366 /* Hack alert! Assume VEX.W rules over any 66h prefix and that no VEX
2367 encoded instructions ever uses the regular x86.uOpMode w/o VEX.W. */
2368 pDis->x86.uOpMode = (bVexByte2 & 0x80) && pDis->uCpuMode == DISCPUMODE_64BIT ? DISCPUMODE_64BIT : DISCPUMODE_32BIT;
2369
2370 PCDISOPCODE pOpCode;
2371 uint8_t const idxVexMap = bVexByte1 & 0x1f;
2372 if (idxVexMap < RT_ELEMENTS(g_aapVexOpcodesMapRanges[bVexByte2 & 3]))
2373 {
2374 PCDISOPMAPDESC const pRange = g_aapVexOpcodesMapRanges[bVexByte2 & 3][idxVexMap];
2375 unsigned const idxOpcode = pDis->x86.bOpCode - pRange->idxFirst;
2376 if (idxOpcode < pRange->cOpcodes)
2377 pOpCode = &pRange->papOpcodes[idxOpcode];
2378 else
2379 pOpCode = &g_InvalidOpcode[0];
2380 }
2381 else
2382 pOpCode = &g_InvalidOpcode[0];
2383
2384 return disParseInstruction(offInstr, pOpCode, pDis);
2385}
2386
2387
2388/**
2389 * Validates the lock sequence.
2390 *
2391 * The AMD manual lists the following instructions:
2392 * ADC
2393 * ADD
2394 * AND
2395 * BTC
2396 * BTR
2397 * BTS
2398 * CMPXCHG
2399 * CMPXCHG8B
2400 * CMPXCHG16B
2401 * DEC
2402 * INC
2403 * NEG
2404 * NOT
2405 * OR
2406 * SBB
2407 * SUB
2408 * XADD
2409 * XCHG
2410 * XOR
2411 *
2412 * @param pDis Fully disassembled instruction.
2413 */
2414static void disValidateLockSequence(PDISSTATE pDis)
2415{
2416 Assert(pDis->x86.fPrefix & DISPREFIX_LOCK);
2417
2418 /*
2419 * Filter out the valid lock sequences.
2420 */
2421 switch (pDis->pCurInstr->uOpcode)
2422 {
2423 /* simple: no variations */
2424 case OP_CMPXCHG8B:
2425 case OP_CMPXCHG16B:
2426 return;
2427
2428 /* simple: /r - reject register destination. */
2429 case OP_BTC:
2430 case OP_BTR:
2431 case OP_BTS:
2432 case OP_CMPXCHG:
2433 case OP_XADD:
2434 if (pDis->x86.ModRM.Bits.Mod == 3)
2435 break;
2436 return;
2437
2438 /*
2439 * Lots of variants but its sufficient to check that param 1
2440 * is a memory operand.
2441 */
2442 case OP_ADC:
2443 case OP_ADD:
2444 case OP_AND:
2445 case OP_DEC:
2446 case OP_INC:
2447 case OP_NEG:
2448 case OP_NOT:
2449 case OP_OR:
2450 case OP_SBB:
2451 case OP_SUB:
2452 case OP_XCHG:
2453 case OP_XOR:
2454 if (pDis->Param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
2455 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
2456 return;
2457 break;
2458
2459 default:
2460 break;
2461 }
2462
2463 /*
2464 * Invalid lock sequence, make it a OP_ILLUD2.
2465 */
2466 pDis->pCurInstr = &g_aTwoByteMapX86[11];
2467 Assert(pDis->pCurInstr->uOpcode == OP_ILLUD2);
2468}
2469
2470/**
2471 * Internal worker for DISInstrEx and DISInstrWithPrefetchedBytes.
2472 *
2473 * @returns VBox status code.
2474 * @param pDis Initialized disassembler state.
2475 * @param paOneByteMap The one byte opcode map to use.
2476 * @param pcbInstr Where to store the instruction size. Can be NULL.
2477 */
2478DECLHIDDEN(int) disInstrWorkerX86(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
2479{
2480 /*
2481 * Parse byte by byte.
2482 */
2483 size_t offInstr = 0;
2484 for (;;)
2485 {
2486 uint8_t const bCode = disReadByte(pDis, offInstr++);
2487 enum OPCODESX86 const enmOpcode = (enum OPCODESX86)paOneByteMap[bCode].uOpcode;
2488
2489 /* Hardcoded assumption about OP_* values!! */
2490 if (enmOpcode <= OP_LAST_PREFIX)
2491 {
2492 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
2493 if (enmOpcode != OP_REX)
2494 {
2495 /* Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
2496 pDis->x86.bLastPrefix = (uint8_t)enmOpcode;
2497 pDis->x86.fPrefix &= ~DISPREFIX_REX;
2498 }
2499
2500 switch (enmOpcode)
2501 {
2502 case OP_INVALID:
2503 if (pcbInstr)
2504 *pcbInstr = (uint32_t)offInstr;
2505 return pDis->rc = VERR_DIS_INVALID_OPCODE;
2506
2507 // segment override prefix byte
2508 case OP_SEG:
2509 pDis->x86.idxSegPrefix = (uint8_t)(paOneByteMap[bCode].fParam1 - OP_PARM_REG_SEG_START);
2510#if 0 /* Try be accurate in our reporting, shouldn't break anything... :-) */
2511 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
2512 if ( pDis->uCpuMode != DISCPUMODE_64BIT
2513 || pDis->idxSegPrefix >= DISSELREG_FS)
2514 pDis->x86.fPrefix |= DISPREFIX_SEG;
2515#else
2516 pDis->x86.fPrefix |= DISPREFIX_SEG;
2517#endif
2518 continue; //fetch the next byte
2519
2520 // lock prefix byte
2521 case OP_LOCK:
2522 pDis->x86.fPrefix |= DISPREFIX_LOCK;
2523 continue; //fetch the next byte
2524
2525 // address size override prefix byte
2526 case OP_ADDRSIZE:
2527 pDis->x86.fPrefix |= DISPREFIX_ADDRSIZE;
2528 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2529 pDis->x86.uAddrMode = DISCPUMODE_32BIT;
2530 else
2531 if (pDis->uCpuMode == DISCPUMODE_32BIT)
2532 pDis->x86.uAddrMode = DISCPUMODE_16BIT;
2533 else
2534 pDis->x86.uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
2535 continue; //fetch the next byte
2536
2537 // operand size override prefix byte
2538 case OP_OPSIZE:
2539 pDis->x86.fPrefix |= DISPREFIX_OPSIZE;
2540 if (pDis->uCpuMode == DISCPUMODE_16BIT)
2541 pDis->x86.uOpMode = DISCPUMODE_32BIT;
2542 else
2543 pDis->x86.uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
2544 continue; //fetch the next byte
2545
2546 // rep and repne are not really prefixes, but we'll treat them as such
2547 case OP_REPE:
2548 pDis->x86.fPrefix |= DISPREFIX_REP;
2549 continue; //fetch the next byte
2550
2551 case OP_REPNE:
2552 pDis->x86.fPrefix |= DISPREFIX_REPNE;
2553 continue; //fetch the next byte
2554
2555 case OP_REX:
2556 Assert(pDis->uCpuMode == DISCPUMODE_64BIT);
2557 /* REX prefix byte */
2558 pDis->x86.fPrefix |= DISPREFIX_REX;
2559 pDis->x86.fRexPrefix = (uint8_t)DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[bCode].fParam1);
2560 if (pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_W)
2561 pDis->x86.uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
2562 continue; //fetch the next byte
2563 default:
2564 AssertFailed();
2565 break;
2566 }
2567 }
2568
2569 /* first opcode byte. */
2570 pDis->x86.bOpCode = bCode;
2571 pDis->x86.cbPrefix = (uint8_t)offInstr - 1;
2572
2573 offInstr = disParseInstruction(offInstr, &paOneByteMap[bCode], pDis);
2574 break;
2575 }
2576
2577 pDis->cbInstr = (uint8_t)offInstr;
2578 if (pcbInstr)
2579 *pcbInstr = (uint32_t)offInstr;
2580
2581 if (pDis->x86.fPrefix & DISPREFIX_LOCK)
2582 disValidateLockSequence(pDis);
2583
2584 return pDis->rc;
2585}
2586
2587
2588/**
2589 * Inlined worker that initializes the disassembler state.
2590 *
2591 * @returns The primary opcode map to use.
2592 * @param pDis The disassembler state.
2593 * @param uInstrAddr The instruction address.
2594 * @param enmCpuMode The CPU mode.
2595 * @param fFilter The instruction filter settings.
2596 * @param pfnReadBytes The byte reader, can be NULL.
2597 * @param pvUser The user data for the reader.
2598 */
2599DECLHIDDEN(PCDISOPCODE) disInitializeStateX86(PDISSTATE pDis, DISCPUMODE enmCpuMode, uint32_t fFilter)
2600{
2601#ifdef VBOX_STRICT /* poison */
2602 pDis->Param1.x86.Base.idxGenReg = 0xc1;
2603 pDis->Param2.x86.Base.idxGenReg = 0xc2;
2604 pDis->Param3.x86.Base.idxGenReg = 0xc3;
2605 pDis->Param1.x86.Index.idxGenReg = 0xc4;
2606 pDis->Param2.x86.Index.idxGenReg = 0xc5;
2607 pDis->Param3.x86.Index.idxGenReg = 0xc6;
2608 pDis->Param1.x86.uDisp.u64 = UINT64_C(0xd1d1d1d1d1d1d1d1);
2609 pDis->Param2.x86.uDisp.u64 = UINT64_C(0xd2d2d2d2d2d2d2d2);
2610 pDis->Param3.x86.uDisp.u64 = UINT64_C(0xd3d3d3d3d3d3d3d3);
2611 pDis->Param1.uValue = UINT64_C(0xb1b1b1b1b1b1b1b1);
2612 pDis->Param2.uValue = UINT64_C(0xb2b2b2b2b2b2b2b2);
2613 pDis->Param3.uValue = UINT64_C(0xb3b3b3b3b3b3b3b3);
2614 pDis->Param1.x86.uScale = 28;
2615 pDis->Param2.x86.uScale = 29;
2616 pDis->Param3.x86.uScale = 30;
2617#endif
2618
2619 pDis->x86.fPrefix = DISPREFIX_NONE;
2620 pDis->x86.idxSegPrefix = DISSELREG_DS;
2621 pDis->x86.pfnDisasmFnTable = g_apfnFullDisasm;
2622 pDis->x86.fFilter = fFilter;
2623
2624 PCDISOPCODE paOneByteMap;
2625 if (enmCpuMode == DISCPUMODE_64BIT)
2626 {
2627 pDis->x86.uAddrMode = DISCPUMODE_64BIT;
2628 pDis->x86.uOpMode = DISCPUMODE_32BIT;
2629 paOneByteMap = g_aOneByteMapX64;
2630 }
2631 else
2632 {
2633 pDis->x86.uAddrMode = (uint8_t)enmCpuMode;
2634 pDis->x86.uOpMode = (uint8_t)enmCpuMode;
2635 paOneByteMap = g_aOneByteMapX86;
2636 }
2637 return paOneByteMap;
2638}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use