VirtualBox

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

Last change on this file since 27607 was 26269, checked in by vboxsync, 15 years ago

DisasmCore.cpp: Drop the size argument to disasmAddString*() since it's always a szParam.

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