VirtualBox

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

Last change on this file since 10700 was 10394, checked in by vboxsync, 16 years ago

More bug fixes for index handling.

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