VirtualBox

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

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

Enabled the disValidateLockSequence code.

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