VirtualBox

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

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

Correction for address size override in 16 bits mode.

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