VirtualBox

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

Last change on this file since 102948 was 101539, checked in by vboxsync, 14 months ago

DIS,VMM,DBGC,IPRT,++: Some disassembler tweaks and TB disassembly work. bugref:10371 bugref:9898

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