VirtualBox

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

Last change on this file since 8492 was 8492, checked in by vboxsync, 17 years ago

warnings

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette