VirtualBox

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

Last change on this file since 29676 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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