VirtualBox

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

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

Not needed anymore

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