VirtualBox

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

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

DIS: Chagned FNDISREADBYTES to permit reading more bytes that the immeidate request. Not using the read-ahead feature in any important code path yet, that's comming next, bit by bit.

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