VirtualBox

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

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

Duh!

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