VirtualBox

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

Last change on this file since 11460 was 11460, checked in by vboxsync, 16 years ago

Check for force flags when determining the new opcode in instruction groups.

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