VirtualBox

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

Last change on this file since 41742 was 41742, checked in by vboxsync, 12 years ago

DISOPPARAM: s/scale/uScale/ + doc

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