VirtualBox

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

Last change on this file since 9098 was 9097, checked in by vboxsync, 16 years ago

ParseEscFP: Why copy fpop->param[12] to pCpu->param[12].parval? Copying it to pCpu->param[12].param as well for now.
ParseImmByteSX: Added a todo for AMD64 because I'm seeing words instead of dwords/qwords there in the output.
UseModRM: Set USE_EFFICIENT_ADDRESS in OP_PARAMETER::flags if it's an efficient address in order to assist instruction formatting.

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