VirtualBox

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

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

Corrections

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