VirtualBox

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

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

Deal with sign extending bytes to uint64_t.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 88.1 KB
Line 
1/** @file
2 *
3 * VBox disassembler:
4 * Core components
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_DIS
28#ifdef USING_VISUAL_STUDIO
29# include <stdafx.h>
30#endif
31
32#include <VBox/dis.h>
33#include <VBox/disopcode.h>
34#include <VBox/cpum.h>
35#include <VBox/err.h>
36#include <VBox/log.h>
37#include <iprt/assert.h>
38#include <iprt/string.h>
39#include <iprt/stdarg.h>
40#include "DisasmInternal.h"
41#include "DisasmTables.h"
42
43#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
44# include <stdlib.h>
45# include <stdio.h>
46#endif
47
48
49/*******************************************************************************
50* Internal Functions *
51*******************************************************************************/
52static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction);
53#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
54static void disasmAddString(char *psz, const char *pszString);
55static void disasmAddStringF(char *psz, uint32_t cbString, const char *pszFormat, ...);
56static void disasmAddChar(char *psz, char ch);
57#else
58# define disasmAddString(psz, pszString) do {} while (0)
59# ifdef _MSC_VER
60# define disasmAddStringF __noop
61# else
62# define disasmAddStringF(psz, cbString, pszFormat...) do {} while (0) /* Arg wanna get rid of that warning */
63# endif
64# define disasmAddChar(psz, ch) do {} while (0)
65#endif
66
67static unsigned QueryModRM(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
68static unsigned QueryModRM_SizeOnly(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
69static void UseSIB(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
70static unsigned ParseSIB_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu);
71
72/*******************************************************************************
73* Global Variables *
74*******************************************************************************/
75
76PFNDISPARSE pfnFullDisasm[IDX_ParseMax] =
77{
78 ParseIllegal,
79 ParseModRM,
80 UseModRM,
81 ParseImmByte,
82 ParseImmBRel,
83 ParseImmUshort,
84 ParseImmV,
85 ParseImmVRel,
86 ParseImmAddr,
87 ParseFixedReg,
88 ParseImmUlong,
89 ParseImmQword,
90 ParseTwoByteEsc,
91 ParseImmGrpl,
92 ParseShiftGrp2,
93 ParseGrp3,
94 ParseGrp4,
95 ParseGrp5,
96 Parse3DNow,
97 ParseGrp6,
98 ParseGrp7,
99 ParseGrp8,
100 ParseGrp9,
101 ParseGrp10,
102 ParseGrp12,
103 ParseGrp13,
104 ParseGrp14,
105 ParseGrp15,
106 ParseGrp16,
107 ParseModFence,
108 ParseYv,
109 ParseYb,
110 ParseXv,
111 ParseXb,
112 ParseEscFP,
113 ParseNopPause,
114 ParseImmByteSX,
115 ParseImmZ
116};
117
118PFNDISPARSE pfnCalcSize[IDX_ParseMax] =
119{
120 ParseIllegal,
121 ParseModRM_SizeOnly,
122 UseModRM,
123 ParseImmByte_SizeOnly,
124 ParseImmBRel_SizeOnly,
125 ParseImmUshort_SizeOnly,
126 ParseImmV_SizeOnly,
127 ParseImmVRel_SizeOnly,
128 ParseImmAddr_SizeOnly,
129 ParseFixedReg,
130 ParseImmUlong_SizeOnly,
131 ParseImmQword_SizeOnly,
132 ParseTwoByteEsc,
133 ParseImmGrpl,
134 ParseShiftGrp2,
135 ParseGrp3,
136 ParseGrp4,
137 ParseGrp5,
138 Parse3DNow,
139 ParseGrp6,
140 ParseGrp7,
141 ParseGrp8,
142 ParseGrp9,
143 ParseGrp10,
144 ParseGrp12,
145 ParseGrp13,
146 ParseGrp14,
147 ParseGrp15,
148 ParseGrp16,
149 ParseModFence,
150 ParseYv,
151 ParseYb,
152 ParseXv,
153 ParseXb,
154 ParseEscFP,
155 ParseNopPause,
156 ParseImmByteSX_SizeOnly,
157 ParseImmZ_SizeOnly
158};
159
160/**
161 * Parses one instruction.
162 * The result is found in pCpu.
163 *
164 * @returns Success indicator.
165 * @param pCpu Pointer to cpu structure which has DISCPUSTATE::mode set correctly.
166 * @param InstructionAddr Pointer to the instruction to parse.
167 * @param pcbInstruction Where to store the size of the instruction.
168 * NULL is allowed.
169 */
170DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
171{
172 /*
173 * Reset instruction settings
174 */
175 pCpu->prefix = PREFIX_NONE;
176 pCpu->enmPrefixSeg = DIS_SELREG_DS;
177 pCpu->lastprefix = 0;
178 pCpu->ModRM.u = 0;
179 pCpu->SIB.u = 0;
180 pCpu->param1.parval = 0;
181 pCpu->param2.parval = 0;
182 pCpu->param3.parval = 0;
183 pCpu->param1.szParam[0] = '\0';
184 pCpu->param2.szParam[0] = '\0';
185 pCpu->param3.szParam[0] = '\0';
186 pCpu->param1.flags = 0;
187 pCpu->param2.flags = 0;
188 pCpu->param3.flags = 0;
189 pCpu->param1.size = 0;
190 pCpu->param2.size = 0;
191 pCpu->param3.size = 0;
192 pCpu->pfnReadBytes = 0;
193 pCpu->uFilter = OPTYPE_ALL;
194 pCpu->pfnDisasmFnTable = pfnFullDisasm;
195
196 return VBOX_SUCCESS(disCoreOne(pCpu, InstructionAddr, pcbInstruction));
197}
198
199/**
200 * Parses one guest instruction.
201 * The result is found in pCpu and pcbInstruction.
202 *
203 * @returns VBox status code.
204 * @param InstructionAddr Address of the instruction to decode. What this means
205 * is left to the pfnReadBytes function.
206 * @param enmCpuMode The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT.
207 * @param pfnReadBytes Callback for reading instruction bytes.
208 * @param pvUser User argument for the instruction reader. (Ends up in apvUserData[0].)
209 * @param pCpu Pointer to cpu structure. Will be initialized.
210 * @param pcbInstruction Where to store the size of the instruction.
211 * NULL is allowed.
212 */
213DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,
214 PDISCPUSTATE pCpu, unsigned *pcbInstruction)
215{
216 /*
217 * Reset instruction settings
218 */
219 pCpu->prefix = PREFIX_NONE;
220 pCpu->enmPrefixSeg = DIS_SELREG_DS;
221 pCpu->lastprefix = 0;
222 pCpu->mode = enmCpuMode;
223 pCpu->ModRM.u = 0;
224 pCpu->SIB.u = 0;
225 pCpu->param1.parval = 0;
226 pCpu->param2.parval = 0;
227 pCpu->param3.parval = 0;
228 pCpu->param1.szParam[0] = '\0';
229 pCpu->param2.szParam[0] = '\0';
230 pCpu->param3.szParam[0] = '\0';
231 pCpu->param1.flags = 0;
232 pCpu->param2.flags = 0;
233 pCpu->param3.flags = 0;
234 pCpu->param1.size = 0;
235 pCpu->param2.size = 0;
236 pCpu->param3.size = 0;
237 pCpu->pfnReadBytes = pfnReadBytes;
238 pCpu->apvUserData[0] = pvUser;
239 pCpu->uFilter = OPTYPE_ALL;
240 pCpu->pfnDisasmFnTable = pfnFullDisasm;
241
242 return disCoreOne(pCpu, InstructionAddr, pcbInstruction);
243}
244
245/**
246 * Internal worker for DISCoreOne and DISCoreOneEx.
247 *
248 * @returns VBox status code.
249 * @param pCpu Initialized cpu state.
250 * @param InstructionAddr Instruction address.
251 * @param pcbInstruction Where to store the instruction size. Can be NULL.
252 */
253static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)
254{
255 const OPCODE *paOneByteMap;
256
257 /*
258 * Parse byte by byte.
259 */
260 unsigned iByte = 0;
261 unsigned cbInc;
262
263 if (pCpu->mode == CPUMODE_64BIT)
264 {
265 paOneByteMap = g_aOneByteMapX64;
266 pCpu->addrmode = CPUMODE_64BIT;
267 pCpu->opmode = CPUMODE_32BIT;
268 }
269 else
270 {
271 paOneByteMap = g_aOneByteMapX86;
272 pCpu->addrmode = pCpu->mode;
273 pCpu->opmode = pCpu->mode;
274 }
275
276#ifdef IN_RING3
277# ifndef __L4ENV__ /* Unfortunately, we have no exception handling in l4env */
278 try
279# else
280 pCpu->pJumpBuffer = &jumpbuffer;
281 if (setjmp(jumpbuffer) == 0)
282# endif
283#endif
284 {
285 while(1)
286 {
287 uint8_t codebyte = DISReadByte(pCpu, InstructionAddr+iByte);
288 uint8_t opcode = paOneByteMap[codebyte].opcode;
289
290 /* Hardcoded assumption about OP_* values!! */
291 if (opcode <= OP_LAST_PREFIX)
292 {
293 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
294 if (opcode != OP_REX)
295 {
296 /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
297 pCpu->lastprefix = opcode;
298 pCpu->prefix &= ~PREFIX_REX;
299 }
300
301 switch (opcode)
302 {
303 case OP_INVALID:
304 AssertMsgFailed(("Invalid opcode!!\n"));
305 return VERR_GENERAL_FAILURE; /** @todo better error code. */
306
307 // segment override prefix byte
308 case OP_SEG:
309 pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
310 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
311 if ( pCpu->mode != CPUMODE_64BIT
312 || pCpu->enmPrefixSeg >= DIS_SELREG_FS)
313 {
314 pCpu->prefix |= PREFIX_SEG;
315 }
316 iByte += sizeof(uint8_t);
317 continue; //fetch the next byte
318
319 // lock prefix byte
320 case OP_LOCK:
321 pCpu->prefix |= PREFIX_LOCK;
322 iByte += sizeof(uint8_t);
323 continue; //fetch the next byte
324
325 // address size override prefix byte
326 case OP_ADDRSIZE:
327 pCpu->prefix |= PREFIX_ADDRSIZE;
328 if (pCpu->mode == CPUMODE_16BIT)
329 pCpu->addrmode = CPUMODE_32BIT;
330 else
331 if (pCpu->mode == CPUMODE_32BIT)
332 pCpu->addrmode = CPUMODE_16BIT;
333 else
334 pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */
335
336 iByte += sizeof(uint8_t);
337 continue; //fetch the next byte
338
339 // operand size override prefix byte
340 case OP_OPSIZE:
341 pCpu->prefix |= PREFIX_OPSIZE;
342 if (pCpu->mode == CPUMODE_16BIT)
343 pCpu->opmode = CPUMODE_32BIT;
344 else
345 pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
346
347 iByte += sizeof(uint8_t);
348 continue; //fetch the next byte
349
350 // rep and repne are not really prefixes, but we'll treat them as such
351 case OP_REPE:
352 pCpu->prefix |= PREFIX_REP;
353 iByte += sizeof(uint8_t);
354 continue; //fetch the next byte
355
356 case OP_REPNE:
357 pCpu->prefix |= PREFIX_REPNE;
358 iByte += sizeof(uint8_t);
359 continue; //fetch the next byte
360
361 case OP_REX:
362 Assert(pCpu->mode == CPUMODE_64BIT);
363 /* REX prefix byte */
364 pCpu->prefix |= PREFIX_REX;
365 pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
366 iByte += sizeof(uint8_t);
367
368 if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W)
369 pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */
370 continue; //fetch the next byte
371 }
372 }
373
374 unsigned uIdx = iByte;
375 iByte += sizeof(uint8_t); //first opcode byte
376
377 pCpu->opaddr = InstructionAddr + uIdx;
378 pCpu->opcode = codebyte;
379
380 cbInc = ParseInstruction(InstructionAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu);
381 iByte += cbInc;
382 break;
383 }
384 }
385#ifdef IN_RING3
386# ifndef __L4ENV__
387 catch(...)
388# else
389 else /* setjmp has returned a non-zero value: an exception occured */
390# endif
391 {
392 pCpu->opsize = 0;
393 return VERR_DIS_GEN_FAILURE;
394 }
395#endif
396
397 pCpu->opsize = iByte;
398 if (pcbInstruction)
399 *pcbInstruction = iByte;
400
401 if (pCpu->prefix & PREFIX_LOCK)
402 disValidateLockSequence(pCpu);
403
404 return VINF_SUCCESS;
405}
406//*****************************************************************************
407//*****************************************************************************
408unsigned ParseInstruction(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, PDISCPUSTATE pCpu)
409{
410 int size = 0;
411 bool fFiltered = false;
412
413 // Store the opcode format string for disasmPrintf
414#ifndef DIS_CORE_ONLY
415 pCpu->pszOpcode = pOp->pszOpcode;
416#endif
417 pCpu->pCurInstr = pOp;
418
419 /*
420 * Apply filter to instruction type to determine if a full disassembly is required.
421 * @note Multibyte opcodes are always marked harmless until the final byte.
422 */
423 if ((pOp->optype & pCpu->uFilter) == 0)
424 {
425 fFiltered = true;
426 pCpu->pfnDisasmFnTable = pfnCalcSize;
427 }
428 else
429 {
430 /* Not filtered out -> full disassembly */
431 pCpu->pfnDisasmFnTable = pfnFullDisasm;
432 }
433
434 // Should contain the parameter type on input
435 pCpu->param1.param = pOp->param1;
436 pCpu->param2.param = pOp->param2;
437 pCpu->param3.param = pOp->param3;
438
439 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
440 if (pCpu->mode == CPUMODE_64BIT)
441 {
442 if (pOp->optype & OPTYPE_FORCED_64_OP_SIZE)
443 pCpu->opsize = CPUMODE_64BIT;
444 else
445 if ( (pOp->optype & OPTYPE_DEFAULT_64_OP_SIZE)
446 && !(pCpu->prefix & PREFIX_OPSIZE))
447 pCpu->opsize = CPUMODE_64BIT;
448 }
449
450 if (pOp->idxParse1 != IDX_ParseNop)
451 {
452 size += pCpu->pfnDisasmFnTable[pOp->idxParse1](lpszCodeBlock, pOp, &pCpu->param1, pCpu);
453 if (fFiltered == false) pCpu->param1.size = DISGetParamSize(pCpu, &pCpu->param1);
454 }
455
456 if (pOp->idxParse2 != IDX_ParseNop)
457 {
458 size += pCpu->pfnDisasmFnTable[pOp->idxParse2](lpszCodeBlock+size, pOp, &pCpu->param2, pCpu);
459 if (fFiltered == false) pCpu->param2.size = DISGetParamSize(pCpu, &pCpu->param2);
460 }
461
462 if (pOp->idxParse3 != IDX_ParseNop)
463 {
464 size += pCpu->pfnDisasmFnTable[pOp->idxParse3](lpszCodeBlock+size, pOp, &pCpu->param3, pCpu);
465 if (fFiltered == false) pCpu->param3.size = DISGetParamSize(pCpu, &pCpu->param3);
466 }
467 // else simple one byte instruction
468
469 return size;
470}
471//*****************************************************************************
472/* Floating point opcode parsing */
473//*****************************************************************************
474unsigned ParseEscFP(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
475{
476 int index;
477 const OPCODE *fpop;
478 unsigned size = 0, ModRM;
479
480 ModRM = DISReadByte(pCpu, lpszCodeBlock);
481
482 index = pCpu->opcode - 0xD8;
483 if (ModRM <= 0xBF)
484 {
485 fpop = &(g_paMapX86_FP_Low[index])[MODRM_REG(ModRM)];
486 pCpu->pCurInstr = (PCOPCODE)fpop;
487
488 // Should contain the parameter type on input
489 pCpu->param1.param = fpop->param1;
490 pCpu->param2.param = fpop->param2;
491 }
492 else
493 {
494 fpop = &(g_paMapX86_FP_High[index])[ModRM - 0xC0];
495 pCpu->pCurInstr = (PCOPCODE)fpop;
496 }
497
498 /*
499 * Apply filter to instruction type to determine if a full disassembly is required.
500 * @note Multibyte opcodes are always marked harmless until the final byte.
501 */
502 if ((fpop->optype & pCpu->uFilter) == 0)
503 {
504 pCpu->pfnDisasmFnTable = pfnCalcSize;
505 }
506 else
507 {
508 /* Not filtered out -> full disassembly */
509 pCpu->pfnDisasmFnTable = pfnFullDisasm;
510 }
511
512 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
513 if (pCpu->mode == CPUMODE_64BIT)
514 {
515 /* Note: redundant, but just in case this ever changes */
516 if (fpop->optype & OPTYPE_FORCED_64_OP_SIZE)
517 pCpu->opsize = CPUMODE_64BIT;
518 else
519 if ( (fpop->optype & OPTYPE_DEFAULT_64_OP_SIZE)
520 && !(pCpu->prefix & PREFIX_OPSIZE))
521 pCpu->opsize = CPUMODE_64BIT;
522 }
523
524 // Little hack to make sure the ModRM byte is included in the returned size
525 if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
526 size = sizeof(uint8_t); //ModRM byte
527
528 if (fpop->idxParse1 != IDX_ParseNop)
529 size += pCpu->pfnDisasmFnTable[fpop->idxParse1](lpszCodeBlock+size, (PCOPCODE)fpop, pParam, pCpu);
530
531 if (fpop->idxParse2 != IDX_ParseNop)
532 size += pCpu->pfnDisasmFnTable[fpop->idxParse2](lpszCodeBlock+size, (PCOPCODE)fpop, pParam, pCpu);
533
534 // Store the opcode format string for disasmPrintf
535#ifndef DIS_CORE_ONLY
536 pCpu->pszOpcode = fpop->pszOpcode;
537#endif
538
539 return size;
540}
541//*****************************************************************************
542// SIB byte: (32 bits mode only)
543// 7 - 6 5 - 3 2-0
544// Scale Index Base
545//*****************************************************************************
546static const char *szSIBBaseReg[8] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
547static const char *szSIBIndexReg[8] = {"EAX", "ECX", "EDX", "EBX", NULL, "EBP", "ESI", "EDI"};
548static const char *szSIBBaseReg64[16] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
549static const char *szSIBIndexReg64[16]= {"RAX", "RCX", "RDX", "RBX", NULL, "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
550static const char *szSIBScale[4] = {"", "*2", "*4", "*8"};
551//*****************************************************************************
552void UseSIB(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
553{
554 unsigned scale, base, index, regtype;
555 const char **ppszSIBIndexReg;
556 const char **ppszSIBBaseReg;
557 char szTemp[32];
558 szTemp[0] = '\0';
559
560 scale = pCpu->SIB.Bits.Scale;
561 base = pCpu->SIB.Bits.Base;
562 index = pCpu->SIB.Bits.Index;
563
564 if (pCpu->addrmode == CPUMODE_32BIT)
565 {
566 ppszSIBIndexReg = szSIBIndexReg;
567 ppszSIBBaseReg = szSIBBaseReg;
568 regtype = USE_REG_GEN32;
569 }
570 else
571 {
572 ppszSIBIndexReg = szSIBIndexReg64;
573 ppszSIBBaseReg = szSIBBaseReg64;
574 regtype = USE_REG_GEN64;
575 }
576
577 if (ppszSIBIndexReg[index])
578 {
579 pParam->flags |= USE_INDEX;
580 pParam->index.reg_gen = index;
581
582 if (scale != 0)
583 {
584 pParam->flags |= USE_SCALE;
585 pParam->scale = (1<<scale);
586 }
587
588 if (base == 5 && pCpu->ModRM.Bits.Mod == 0)
589 disasmAddStringF(szTemp, sizeof(szTemp), "%s%s", ppszSIBIndexReg[index], szSIBScale[scale]);
590 else
591 disasmAddStringF(szTemp, sizeof(szTemp), "%s+%s%s", ppszSIBBaseReg[base], ppszSIBIndexReg[index], szSIBScale[scale]);
592 }
593 else
594 {
595 if (base != 5 || pCpu->ModRM.Bits.Mod != 0)
596 disasmAddStringF(szTemp, sizeof(szTemp), "%s", ppszSIBBaseReg[base]);
597 }
598
599 if (base == 5 && pCpu->ModRM.Bits.Mod == 0)
600 {
601 // [scaled index] + disp32
602 disasmAddString(pParam->szParam, &szTemp[0]);
603 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 pParam->flags |= USE_IMMEDIATE32;
1326 pParam->size = sizeof(uint32_t);
1327
1328 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1329 return sizeof(uint32_t);
1330 }
1331}
1332//*****************************************************************************
1333//*****************************************************************************
1334unsigned ParseImmZ_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1335{
1336 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1337 if (pCpu->opmode == CPUMODE_16BIT)
1338 return sizeof(uint16_t);
1339 return sizeof(uint32_t);
1340}
1341
1342//*****************************************************************************
1343// Relative displacement for branches (rel. to next instruction)
1344//*****************************************************************************
1345unsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1346{
1347 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1348 pParam->flags |= USE_IMMEDIATE8_REL;
1349 pParam->size = sizeof(uint8_t);
1350
1351 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%02Xh)", (uint32_t)pParam->parval);
1352 return sizeof(char);
1353}
1354//*****************************************************************************
1355// Relative displacement for branches (rel. to next instruction)
1356//*****************************************************************************
1357unsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1358{
1359 return sizeof(char);
1360}
1361//*****************************************************************************
1362// Relative displacement for branches (rel. to next instruction)
1363//*****************************************************************************
1364unsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1365{
1366 if (pCpu->opmode == CPUMODE_32BIT)
1367 {
1368 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1369 pParam->flags |= USE_IMMEDIATE32_REL;
1370 pParam->size = sizeof(int32_t);
1371
1372 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%08Xh)", (uint32_t)pParam->parval);
1373 return sizeof(int32_t);
1374 }
1375 else
1376 if (pCpu->opmode == CPUMODE_64BIT)
1377 {
1378 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1379 pParam->flags |= USE_IMMEDIATE64_REL;
1380 pParam->size = sizeof(int64_t);
1381
1382 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%VX64h)", pParam->parval);
1383 return sizeof(int64_t);
1384 }
1385 else
1386 {
1387 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1388 pParam->flags |= USE_IMMEDIATE16_REL;
1389 pParam->size = sizeof(int16_t);
1390
1391 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%04Xh)", (uint32_t)pParam->parval);
1392 return sizeof(uint16_t);
1393 }
1394}
1395//*****************************************************************************
1396// Relative displacement for branches (rel. to next instruction)
1397//*****************************************************************************
1398unsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1399{
1400 if (pCpu->opmode == CPUMODE_32BIT)
1401 return sizeof(int32_t);
1402 else
1403 if (pCpu->opmode == CPUMODE_64BIT)
1404 return sizeof(int64_t);
1405 return sizeof(uint16_t);
1406}
1407//*****************************************************************************
1408//*****************************************************************************
1409unsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1410{
1411 disasmGetPtrString(pCpu, pOp, pParam);
1412 if (pCpu->addrmode == CPUMODE_32BIT)
1413 {
1414 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1415 {// far 16:32 pointer
1416 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1417 *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
1418 pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
1419 pParam->size = sizeof(uint16_t) + sizeof(uint32_t);
1420
1421 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
1422 return sizeof(uint32_t) + sizeof(uint16_t);
1423 }
1424 else
1425 {// near 32 bits pointer
1426 /*
1427 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1428 * so we treat it like displacement.
1429 */
1430 pParam->disp32 = DISReadDWord(pCpu, lpszCodeBlock);
1431 pParam->flags |= USE_DISPLACEMENT32;
1432 pParam->size = sizeof(uint32_t);
1433
1434 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08Xh]", pParam->disp32);
1435 return sizeof(uint32_t);
1436 }
1437 }
1438 else
1439 if (pCpu->addrmode == CPUMODE_64BIT)
1440 {
1441 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1442 /* near 64 bits pointer */
1443 /*
1444 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1445 * so we treat it like displacement.
1446 */
1447 pParam->disp64 = DISReadQWord(pCpu, lpszCodeBlock);
1448 pParam->flags |= USE_DISPLACEMENT64;
1449 pParam->size = sizeof(uint64_t);
1450
1451 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64);
1452 return sizeof(uint64_t);
1453 }
1454 else
1455 {
1456 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1457 {// far 16:16 pointer
1458 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1459 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1460 pParam->size = 2*sizeof(uint16_t);
1461
1462 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1463 return sizeof(uint32_t);
1464 }
1465 else
1466 {// near 16 bits pointer
1467 /*
1468 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1469 * so we treat it like displacement.
1470 */
1471 pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
1472 pParam->flags |= USE_DISPLACEMENT16;
1473 pParam->size = sizeof(uint16_t);
1474
1475 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
1476 return sizeof(uint16_t);
1477 }
1478 }
1479}
1480//*****************************************************************************
1481//*****************************************************************************
1482unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1483{
1484 if (pCpu->addrmode == CPUMODE_32BIT)
1485 {
1486 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1487 {// far 16:32 pointer
1488 return sizeof(uint32_t) + sizeof(uint16_t);
1489 }
1490 else
1491 {// near 32 bits pointer
1492 return sizeof(uint32_t);
1493 }
1494 }
1495 if (pCpu->addrmode == CPUMODE_64BIT)
1496 {
1497 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1498 return sizeof(uint64_t);
1499 }
1500 else
1501 {
1502 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1503 {// far 16:16 pointer
1504 return sizeof(uint32_t);
1505 }
1506 else
1507 {// near 16 bits pointer
1508 return sizeof(uint16_t);
1509 }
1510 }
1511}
1512//*****************************************************************************
1513//*****************************************************************************
1514unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1515{
1516 /*
1517 * Sets up flags for stored in OPC fixed registers.
1518 */
1519
1520 if (pParam->param == OP_PARM_NONE)
1521 {
1522 /* No parameter at all. */
1523 return 0;
1524 }
1525
1526 AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
1527 AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
1528 AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1529 AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
1530
1531 if (pParam->param <= OP_PARM_REG_GEN32_END)
1532 {
1533 /* 32-bit EAX..EDI registers. */
1534 if (pCpu->opmode == CPUMODE_32BIT)
1535 {
1536 /* Use 32-bit registers. */
1537 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1538 pParam->flags |= USE_REG_GEN32;
1539 pParam->size = 4;
1540 }
1541 else
1542 if (pCpu->opmode == CPUMODE_64BIT)
1543 {
1544 /* Use 64-bit registers. */
1545 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1546 if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
1547 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1548 && (pCpu->prefix & PREFIX_REX)
1549 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1550 pParam->base.reg_gen += 8;
1551
1552 pParam->flags |= USE_REG_GEN64;
1553 pParam->size = 8;
1554 }
1555 else
1556 {
1557 /* Use 16-bit registers. */
1558 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1559 pParam->flags |= USE_REG_GEN16;
1560 pParam->size = 2;
1561 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1562 }
1563 }
1564 else
1565 if (pParam->param <= OP_PARM_REG_SEG_END)
1566 {
1567 /* Segment ES..GS registers. */
1568 pParam->base.reg_seg = (DIS_SELREG)(pParam->param - OP_PARM_REG_SEG_START);
1569 pParam->flags |= USE_REG_SEG;
1570 pParam->size = 2;
1571 }
1572 else
1573 if (pParam->param <= OP_PARM_REG_GEN16_END)
1574 {
1575 /* 16-bit AX..DI registers. */
1576 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN16_START;
1577 pParam->flags |= USE_REG_GEN16;
1578 pParam->size = 2;
1579 }
1580 else
1581 if (pParam->param <= OP_PARM_REG_GEN8_END)
1582 {
1583 /* 8-bit AL..DL, AH..DH registers. */
1584 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN8_START;
1585 pParam->flags |= USE_REG_GEN8;
1586 pParam->size = 1;
1587
1588 if (pCpu->opmode == CPUMODE_64BIT)
1589 {
1590 if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
1591 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1592 && (pCpu->prefix & PREFIX_REX)
1593 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1594 pParam->base.reg_gen += 8; /* least significant byte of R8-R15 */
1595 }
1596 }
1597 else
1598 if (pParam->param <= OP_PARM_REG_FP_END)
1599 {
1600 /* FPU registers. */
1601 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1602 pParam->flags |= USE_REG_FP;
1603 pParam->size = 10;
1604 }
1605 Assert(!(pParam->param >= OP_PARM_REG_GEN64_START && pParam->param <= OP_PARM_REG_GEN64_END));
1606
1607 /* else - not supported for now registers. */
1608
1609 return 0;
1610}
1611//*****************************************************************************
1612//*****************************************************************************
1613unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1614{
1615 disasmGetPtrString(pCpu, pOp, pParam);
1616 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1617
1618 pParam->flags |= USE_POINTER_DS_BASED;
1619 if (pCpu->addrmode == CPUMODE_32BIT)
1620 {
1621 pParam->base.reg_gen = USE_REG_ESI;
1622 pParam->flags |= USE_REG_GEN32;
1623 }
1624 else
1625 if (pCpu->addrmode == CPUMODE_64BIT)
1626 {
1627 pParam->base.reg_gen = USE_REG_RSI;
1628 pParam->flags |= USE_REG_GEN64;
1629 }
1630 else
1631 {
1632 pParam->base.reg_gen = USE_REG_SI;
1633 pParam->flags |= USE_REG_GEN16;
1634 }
1635 return 0; //no additional opcode bytes
1636}
1637//*****************************************************************************
1638//*****************************************************************************
1639unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1640{
1641 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1642
1643 pParam->flags |= USE_POINTER_DS_BASED;
1644 if (pCpu->addrmode == CPUMODE_32BIT)
1645 {
1646 pParam->base.reg_gen = USE_REG_ESI;
1647 pParam->flags |= USE_REG_GEN32;
1648 }
1649 else
1650 if (pCpu->addrmode == CPUMODE_64BIT)
1651 {
1652 pParam->base.reg_gen = USE_REG_RSI;
1653 pParam->flags |= USE_REG_GEN64;
1654 }
1655 else
1656 {
1657 pParam->base.reg_gen = USE_REG_SI;
1658 pParam->flags |= USE_REG_GEN16;
1659 }
1660 return 0; //no additional opcode bytes
1661}
1662//*****************************************************************************
1663//*****************************************************************************
1664unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1665{
1666 disasmGetPtrString(pCpu, pOp, pParam);
1667 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1668
1669 pParam->flags |= USE_POINTER_ES_BASED;
1670 if (pCpu->addrmode == CPUMODE_32BIT)
1671 {
1672 pParam->base.reg_gen = USE_REG_EDI;
1673 pParam->flags |= USE_REG_GEN32;
1674 }
1675 else
1676 if (pCpu->addrmode == CPUMODE_64BIT)
1677 {
1678 pParam->base.reg_gen = USE_REG_RDI;
1679 pParam->flags |= USE_REG_GEN64;
1680 }
1681 else
1682 {
1683 pParam->base.reg_gen = USE_REG_DI;
1684 pParam->flags |= USE_REG_GEN16;
1685 }
1686 return 0; //no additional opcode bytes
1687}
1688//*****************************************************************************
1689//*****************************************************************************
1690unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1691{
1692 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1693
1694 pParam->flags |= USE_POINTER_ES_BASED;
1695 if (pCpu->addrmode == CPUMODE_32BIT)
1696 {
1697 pParam->base.reg_gen = USE_REG_EDI;
1698 pParam->flags |= USE_REG_GEN32;
1699 }
1700 else
1701 if (pCpu->addrmode == CPUMODE_64BIT)
1702 {
1703 pParam->base.reg_gen = USE_REG_RDI;
1704 pParam->flags |= USE_REG_GEN64;
1705 }
1706 else
1707 {
1708 pParam->base.reg_gen = USE_REG_DI;
1709 pParam->flags |= USE_REG_GEN16;
1710 }
1711 return 0; //no additional opcode bytes
1712}
1713//*****************************************************************************
1714//*****************************************************************************
1715unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1716{
1717 const OPCODE *pOpcode;
1718 int size = sizeof(uint8_t);
1719
1720 //2nd byte
1721 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1722 pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
1723
1724 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1725 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1726 if (pCpu->lastprefix)
1727 {
1728 switch (pCpu->lastprefix)
1729 {
1730 case OP_OPSIZE: /* 0x66 */
1731 if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
1732 {
1733 /* Table entry is valid, so use the extension table. */
1734 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
1735
1736 /* Cancel prefix changes. */
1737 pCpu->prefix &= ~PREFIX_OPSIZE;
1738 pCpu->opmode = pCpu->mode;
1739 }
1740 break;
1741
1742 case OP_REPNE: /* 0xF2 */
1743 if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
1744 {
1745 /* Table entry is valid, so use the extension table. */
1746 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
1747
1748 /* Cancel prefix changes. */
1749 pCpu->prefix &= ~PREFIX_REPNE;
1750 }
1751 break;
1752
1753 case OP_REPE: /* 0xF3 */
1754 if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
1755 {
1756 /* Table entry is valid, so use the extension table. */
1757 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
1758
1759 /* Cancel prefix changes. */
1760 pCpu->prefix &= ~PREFIX_REP;
1761 }
1762 break;
1763 }
1764 }
1765
1766 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1767 return size;
1768}
1769//*****************************************************************************
1770//*****************************************************************************
1771unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1772{
1773 unsigned size = 0;
1774
1775 if (pCpu->prefix & PREFIX_REP)
1776 {
1777 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1778 pCpu->prefix &= ~PREFIX_REP;
1779 }
1780 else
1781 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1782
1783 size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
1784 return size;
1785}
1786//*****************************************************************************
1787//*****************************************************************************
1788unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1789{
1790 int idx = (pCpu->opcode - 0x80) * 8;
1791 unsigned size = 0, modrm, reg;
1792
1793 modrm = DISReadByte(pCpu, lpszCodeBlock);
1794 reg = MODRM_REG(modrm);
1795
1796 pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
1797 //little hack to make sure the ModRM byte is included in the returned size
1798 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1799 size = sizeof(uint8_t); //ModRM byte
1800
1801 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1802
1803 return size;
1804}
1805//*****************************************************************************
1806//*****************************************************************************
1807unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1808{
1809 int idx;
1810 unsigned size = 0, modrm, reg;
1811
1812 switch (pCpu->opcode)
1813 {
1814 case 0xC0:
1815 case 0xC1:
1816 idx = (pCpu->opcode - 0xC0)*8;
1817 break;
1818
1819 case 0xD0:
1820 case 0xD1:
1821 case 0xD2:
1822 case 0xD3:
1823 idx = (pCpu->opcode - 0xD0 + 2)*8;
1824 break;
1825
1826 default:
1827 AssertMsgFailed(("Oops\n"));
1828 return sizeof(uint8_t);
1829 }
1830
1831 modrm = DISReadByte(pCpu, lpszCodeBlock);
1832 reg = MODRM_REG(modrm);
1833
1834 pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
1835
1836 //little hack to make sure the ModRM byte is included in the returned size
1837 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1838 size = sizeof(uint8_t); //ModRM byte
1839
1840 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1841
1842 return size;
1843}
1844//*****************************************************************************
1845//*****************************************************************************
1846unsigned ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1847{
1848 int idx = (pCpu->opcode - 0xF6) * 8;
1849 unsigned size = 0, modrm, reg;
1850
1851 modrm = DISReadByte(pCpu, lpszCodeBlock);
1852 reg = MODRM_REG(modrm);
1853
1854 pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
1855
1856 //little hack to make sure the ModRM byte is included in the returned size
1857 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1858 size = sizeof(uint8_t); //ModRM byte
1859
1860 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1861
1862 return size;
1863}
1864//*****************************************************************************
1865//*****************************************************************************
1866unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1867{
1868 unsigned size = 0, modrm, reg;
1869
1870 modrm = DISReadByte(pCpu, lpszCodeBlock);
1871 reg = MODRM_REG(modrm);
1872
1873 pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
1874
1875 //little hack to make sure the ModRM byte is included in the returned size
1876 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1877 size = sizeof(uint8_t); //ModRM byte
1878
1879 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1880
1881 return size;
1882}
1883//*****************************************************************************
1884//*****************************************************************************
1885unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1886{
1887 unsigned size = 0, modrm, reg;
1888
1889 modrm = DISReadByte(pCpu, lpszCodeBlock);
1890 reg = MODRM_REG(modrm);
1891
1892 pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
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 size = sizeof(uint8_t); //ModRM byte
1897
1898 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1899
1900 return size;
1901}
1902//*****************************************************************************
1903// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
1904// It would appear the ModRM byte must always be present. How else can you
1905// determine the offset of the imm8_opcode byte otherwise?
1906//
1907//*****************************************************************************
1908unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1909{
1910 unsigned size = 0, modrmsize;
1911
1912#ifdef DEBUG_Sander
1913 //needs testing
1914 AssertMsgFailed(("Test me\n"));
1915#endif
1916
1917 unsigned ModRM = DISReadByte(pCpu, lpszCodeBlock);
1918 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1919 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1920 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1921
1922 modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
1923
1924 uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
1925
1926 pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
1927
1928 //little hack to make sure the ModRM byte is included in the returned size
1929 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1930 {
1931#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
1932 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
1933#endif
1934 size = sizeof(uint8_t); //ModRM byte
1935 }
1936
1937 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1938 size += sizeof(uint8_t); //imm8_opcode uint8_t
1939
1940 return size;
1941}
1942//*****************************************************************************
1943//*****************************************************************************
1944unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1945{
1946 unsigned size = 0, modrm, reg;
1947
1948 modrm = DISReadByte(pCpu, lpszCodeBlock);
1949 reg = MODRM_REG(modrm);
1950
1951 pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
1952
1953 //little hack to make sure the ModRM byte is included in the returned size
1954 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1955 size = sizeof(uint8_t); //ModRM byte
1956
1957 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1958
1959 return size;
1960}
1961//*****************************************************************************
1962//*****************************************************************************
1963unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1964{
1965 unsigned size = 0, modrm, reg, rm, mod;
1966
1967 modrm = DISReadByte(pCpu, lpszCodeBlock);
1968 mod = MODRM_MOD(modrm);
1969 reg = MODRM_REG(modrm);
1970 rm = MODRM_RM(modrm);
1971
1972 if (mod == 3 && rm == 0)
1973 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
1974 else
1975 if (mod == 3 && rm == 1)
1976 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
1977 else
1978 pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
1979
1980 //little hack to make sure the ModRM byte is included in the returned size
1981 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1982 size = sizeof(uint8_t); //ModRM byte
1983
1984 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1985
1986 return size;
1987}
1988//*****************************************************************************
1989//*****************************************************************************
1990unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1991{
1992 unsigned size = 0, modrm, reg;
1993
1994 modrm = DISReadByte(pCpu, lpszCodeBlock);
1995 reg = MODRM_REG(modrm);
1996
1997 pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
1998
1999 //little hack to make sure the ModRM byte is included in the returned size
2000 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2001 size = sizeof(uint8_t); //ModRM byte
2002
2003 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2004
2005 return size;
2006}
2007//*****************************************************************************
2008//*****************************************************************************
2009unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2010{
2011 unsigned size = 0, modrm, reg;
2012
2013 modrm = DISReadByte(pCpu, lpszCodeBlock);
2014 reg = MODRM_REG(modrm);
2015
2016 pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
2017
2018 //little hack to make sure the ModRM byte is included in the returned size
2019 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2020 size = sizeof(uint8_t); //ModRM byte
2021
2022 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2023
2024 return size;
2025}
2026//*****************************************************************************
2027//*****************************************************************************
2028unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2029{
2030 unsigned size = 0, modrm, reg;
2031
2032 modrm = DISReadByte(pCpu, lpszCodeBlock);
2033 reg = MODRM_REG(modrm);
2034
2035 pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
2036
2037 //little hack to make sure the ModRM byte is included in the returned size
2038 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2039 size = sizeof(uint8_t); //ModRM byte
2040
2041 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2042
2043 return size;
2044}
2045//*****************************************************************************
2046//*****************************************************************************
2047unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2048{
2049 unsigned size = 0, modrm, reg;
2050
2051 modrm = DISReadByte(pCpu, lpszCodeBlock);
2052 reg = MODRM_REG(modrm);
2053
2054 if (pCpu->prefix & PREFIX_OPSIZE)
2055 reg += 8; //2nd table
2056
2057 pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
2058
2059 //little hack to make sure the ModRM byte is included in the returned size
2060 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2061 size = sizeof(uint8_t); //ModRM byte
2062
2063 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2064 return size;
2065}
2066//*****************************************************************************
2067//*****************************************************************************
2068unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2069{
2070 unsigned size = 0, modrm, reg;
2071
2072 modrm = DISReadByte(pCpu, lpszCodeBlock);
2073 reg = MODRM_REG(modrm);
2074 if (pCpu->prefix & PREFIX_OPSIZE)
2075 reg += 8; //2nd table
2076
2077 pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
2078
2079 //little hack to make sure the ModRM byte is included in the returned size
2080 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2081 size = sizeof(uint8_t); //ModRM byte
2082
2083 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2084
2085 return size;
2086}
2087//*****************************************************************************
2088//*****************************************************************************
2089unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2090{
2091 unsigned size = 0, modrm, reg;
2092
2093 modrm = DISReadByte(pCpu, lpszCodeBlock);
2094 reg = MODRM_REG(modrm);
2095 if (pCpu->prefix & PREFIX_OPSIZE)
2096 reg += 8; //2nd table
2097
2098 pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
2099
2100 //little hack to make sure the ModRM byte is included in the returned size
2101 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2102 size = sizeof(uint8_t); //ModRM byte
2103
2104 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2105
2106 return size;
2107}
2108//*****************************************************************************
2109//*****************************************************************************
2110unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2111{
2112 unsigned size = 0, modrm, reg, mod, rm;
2113
2114 modrm = DISReadByte(pCpu, lpszCodeBlock);
2115 mod = MODRM_MOD(modrm);
2116 reg = MODRM_REG(modrm);
2117 rm = MODRM_RM(modrm);
2118
2119 if (mod == 3 && rm == 0)
2120 pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
2121 else
2122 pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
2123
2124 //little hack to make sure the ModRM byte is included in the returned size
2125 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2126 size = sizeof(uint8_t); //ModRM byte
2127
2128 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2129 return size;
2130}
2131//*****************************************************************************
2132//*****************************************************************************
2133unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2134{
2135 unsigned size = 0, modrm, reg;
2136
2137 modrm = DISReadByte(pCpu, lpszCodeBlock);
2138 reg = MODRM_REG(modrm);
2139
2140 pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
2141
2142 //little hack to make sure the ModRM byte is included in the returned size
2143 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2144 size = sizeof(uint8_t); //ModRM byte
2145
2146 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2147 return size;
2148}
2149//*****************************************************************************
2150#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2151static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"};
2152static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"};
2153static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"};
2154static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
2155static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
2156#endif
2157static const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
2158static 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};
2159static const int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
2160//*****************************************************************************
2161void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam, int fRegAddr)
2162{
2163 int subtype, type, mod;
2164
2165 mod = pCpu->ModRM.Bits.Mod;
2166
2167 type = OP_PARM_VTYPE(pParam->param);
2168 subtype = OP_PARM_VSUBTYPE(pParam->param);
2169 if (fRegAddr)
2170 subtype = (pCpu->addrmode == CPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
2171 else
2172 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
2173 {
2174 switch(pCpu->opmode)
2175 {
2176 case CPUMODE_32BIT:
2177 subtype = OP_PARM_d;
2178 break;
2179 case CPUMODE_64BIT:
2180 subtype = OP_PARM_q;
2181 break;
2182 case CPUMODE_16BIT:
2183 subtype = OP_PARM_w;
2184 break;
2185 default:
2186 /* make gcc happy */
2187 break;
2188 }
2189 }
2190
2191 switch (subtype)
2192 {
2193 case OP_PARM_b:
2194 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8);
2195
2196 /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
2197 /* Intel® 64 and IA-32 Architectures Software Developer’s Manual: 3.4.1.1 */
2198 if ( (pCpu->prefix & PREFIX_REX)
2199 && idx >= USE_REG_AH
2200 && idx <= USE_REG_BH)
2201 {
2202 idx += (USE_REG_SPL - USE_REG_AH);
2203 }
2204 disasmAddString(pParam->szParam, szModRMReg8[idx]);
2205
2206 pParam->flags |= USE_REG_GEN8;
2207 pParam->base.reg_gen = idx;
2208 break;
2209
2210 case OP_PARM_w:
2211 disasmAddString(pParam->szParam, szModRMReg16[idx]);
2212 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8);
2213
2214 pParam->flags |= USE_REG_GEN16;
2215 pParam->base.reg_gen = idx;
2216 break;
2217
2218 case OP_PARM_d:
2219 disasmAddString(pParam->szParam, szModRMReg32[idx]);
2220 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8);
2221
2222 pParam->flags |= USE_REG_GEN32;
2223 pParam->base.reg_gen = idx;
2224 break;
2225
2226 case OP_PARM_q:
2227 disasmAddString(pParam->szParam, szModRMReg64[idx]);
2228 pParam->flags |= USE_REG_GEN64;
2229 pParam->base.reg_gen = idx;
2230 break;
2231
2232 default:
2233#ifdef IN_RING3
2234 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
2235 DIS_THROW(ExceptionInvalidModRM);
2236#else
2237 AssertMsgFailed(("Oops!\n"));
2238#endif
2239 break;
2240 }
2241}
2242//*****************************************************************************
2243//*****************************************************************************
2244void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam)
2245{
2246 disasmAddString(pParam->szParam, szModRMReg1616[idx]);
2247 pParam->flags |= USE_REG_GEN16;
2248 pParam->base.reg_gen = BaseModRMReg16[idx];
2249 if (idx < 4)
2250 {
2251 pParam->flags |= USE_INDEX;
2252 pParam->index.reg_gen = IndexModRMReg16[idx];
2253 }
2254}
2255//*****************************************************************************
2256//*****************************************************************************
2257void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam)
2258{
2259#if 0 //def DEBUG_Sander
2260 AssertMsg(idx < ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
2261#endif
2262#ifdef IN_RING3
2263 if (idx >= ELEMENTS(szModRMSegReg))
2264 {
2265 Log(("disasmModRMSReg %d failed!!\n", idx));
2266 DIS_THROW(ExceptionInvalidParameter);
2267 }
2268#endif
2269
2270 idx = RT_MIN(idx, ELEMENTS(szModRMSegReg)-1);
2271 disasmAddString(pParam->szParam, szModRMSegReg[idx]);
2272 pParam->flags |= USE_REG_SEG;
2273 pParam->base.reg_seg = (DIS_SELREG)idx;
2274}
2275//*****************************************************************************
2276//*****************************************************************************
2277void disasmPrintAbs32(POP_PARAMETER pParam)
2278{
2279 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2280}
2281//*****************************************************************************
2282//*****************************************************************************
2283void disasmPrintDisp32(POP_PARAMETER pParam)
2284{
2285 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2286}
2287//*****************************************************************************
2288//*****************************************************************************
2289void disasmPrintDisp64(POP_PARAMETER pParam)
2290{
2291 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%16RX64h", pParam->disp64);
2292}
2293//*****************************************************************************
2294//*****************************************************************************
2295void disasmPrintDisp8(POP_PARAMETER pParam)
2296{
2297 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
2298}
2299//*****************************************************************************
2300//*****************************************************************************
2301void disasmPrintDisp16(POP_PARAMETER pParam)
2302{
2303 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
2304}
2305//*****************************************************************************
2306//*****************************************************************************
2307void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
2308{
2309 int subtype = OP_PARM_VSUBTYPE(pParam->param);
2310
2311 if (subtype == OP_PARM_v)
2312 {
2313 switch(pCpu->opmode)
2314 {
2315 case CPUMODE_32BIT:
2316 subtype = OP_PARM_d;
2317 break;
2318 case CPUMODE_64BIT:
2319 subtype = OP_PARM_q;
2320 break;
2321 case CPUMODE_16BIT:
2322 subtype = OP_PARM_w;
2323 break;
2324 default:
2325 /* make gcc happy */
2326 break;
2327 }
2328 }
2329
2330 switch (subtype)
2331 {
2332 case OP_PARM_a: //two words or dwords depending on operand size (bound only)
2333 break;
2334
2335 case OP_PARM_b:
2336 disasmAddString(pParam->szParam, "byte ptr ");
2337 break;
2338
2339 case OP_PARM_w:
2340 disasmAddString(pParam->szParam, "word ptr ");
2341 break;
2342
2343 case OP_PARM_d:
2344 disasmAddString(pParam->szParam, "dword ptr ");
2345 break;
2346
2347 case OP_PARM_q:
2348 case OP_PARM_dq:
2349 disasmAddString(pParam->szParam, "qword ptr ");
2350 break;
2351
2352 case OP_PARM_p:
2353 disasmAddString(pParam->szParam, "far ptr ");
2354 break;
2355
2356 case OP_PARM_s:
2357 break; //??
2358
2359 case OP_PARM_z:
2360 break;
2361 default:
2362 break; //no pointer type specified/necessary
2363 }
2364 if (pCpu->prefix & PREFIX_SEG)
2365 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->enmPrefixSeg]);
2366}
2367#ifndef IN_GC
2368//*****************************************************************************
2369/* Read functions for getting the opcode bytes */
2370//*****************************************************************************
2371uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2372{
2373 if (pCpu->pfnReadBytes)
2374 {
2375 uint8_t temp = 0;
2376 int rc;
2377
2378 rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
2379 if (VBOX_FAILURE(rc))
2380 {
2381 Log(("DISReadByte failed!!\n"));
2382 DIS_THROW(ExceptionMemRead);
2383 }
2384 return temp;
2385 }
2386#ifdef IN_RING0
2387 AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
2388 return 0;
2389#else
2390 else return *(uint8_t *)pAddress;
2391#endif
2392}
2393//*****************************************************************************
2394//*****************************************************************************
2395uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2396{
2397 if (pCpu->pfnReadBytes)
2398 {
2399 uint16_t temp = 0;
2400 int rc;
2401
2402 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2403 if (VBOX_FAILURE(rc))
2404 {
2405 Log(("DISReadWord failed!!\n"));
2406 DIS_THROW(ExceptionMemRead);
2407 }
2408 return temp;
2409 }
2410#ifdef IN_RING0
2411 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
2412 return 0;
2413#else
2414 else return *(uint16_t *)pAddress;
2415#endif
2416}
2417//*****************************************************************************
2418//*****************************************************************************
2419uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2420{
2421 if (pCpu->pfnReadBytes)
2422 {
2423 uint32_t temp = 0;
2424 int rc;
2425
2426 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2427 if (VBOX_FAILURE(rc))
2428 {
2429 Log(("DISReadDWord failed!!\n"));
2430 DIS_THROW(ExceptionMemRead);
2431 }
2432 return temp;
2433 }
2434#ifdef IN_RING0
2435 AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
2436 return 0;
2437#else
2438 else return *(uint32_t *)pAddress;
2439#endif
2440}
2441//*****************************************************************************
2442//*****************************************************************************
2443uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2444{
2445 if (pCpu->pfnReadBytes)
2446 {
2447 uint64_t temp = 0;
2448 int rc;
2449
2450 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2451 if (VBOX_FAILURE(rc))
2452 {
2453 Log(("DISReadQWord %x failed!!\n", pAddress));
2454 DIS_THROW(ExceptionMemRead);
2455 }
2456
2457 return temp;
2458 }
2459#ifdef IN_RING0
2460 AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
2461 return 0;
2462#else
2463 else return *(uint64_t *)pAddress;
2464#endif
2465}
2466#endif /* IN_GC */
2467
2468#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2469//*****************************************************************************
2470//*****************************************************************************
2471void disasmAddString(char *psz, const char *pszAdd)
2472{
2473 strcat(psz, pszAdd);
2474}
2475//*****************************************************************************
2476//*****************************************************************************
2477void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
2478{
2479 va_list args;
2480 va_start(args, pszFormat);
2481 RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
2482 va_end(args);
2483}
2484
2485//*****************************************************************************
2486//*****************************************************************************
2487void disasmAddChar(char *psz, char ch)
2488{
2489 char sz[2];
2490
2491 sz[0] = ch;
2492 sz[1] = '\0';
2493 strcat(psz, sz);
2494}
2495#endif /* !DIS_CORE_ONLY */
2496
2497
2498/**
2499 * Validates the lock sequence.
2500 *
2501 * The AMD manual lists the following instructions:
2502 * ADC
2503 * ADD
2504 * AND
2505 * BTC
2506 * BTR
2507 * BTS
2508 * CMPXCHG
2509 * CMPXCHG8B
2510 * CMPXCHG16B
2511 * DEC
2512 * INC
2513 * NEG
2514 * NOT
2515 * OR
2516 * SBB
2517 * SUB
2518 * XADD
2519 * XCHG
2520 * XOR
2521 *
2522 * @param pCpu Fully dissassembled instruction.
2523 */
2524void disValidateLockSequence(PDISCPUSTATE pCpu)
2525{
2526 Assert(pCpu->prefix & PREFIX_LOCK);
2527
2528 /*
2529 * Filter out the valid lock sequences.
2530 */
2531 switch (pCpu->pCurInstr->opcode)
2532 {
2533 /* simple: no variations */
2534 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2535 return;
2536
2537 /* simple: /r - reject register destination. */
2538 case OP_BTC:
2539 case OP_BTR:
2540 case OP_BTS:
2541 case OP_CMPXCHG:
2542 case OP_XADD:
2543 if (pCpu->ModRM.Bits.Mod == 3)
2544 break;
2545 return;
2546
2547 /*
2548 * Lots of variants but its sufficient to check that param 1
2549 * is a memory operand.
2550 */
2551 case OP_ADC:
2552 case OP_ADD:
2553 case OP_AND:
2554 case OP_DEC:
2555 case OP_INC:
2556 case OP_NEG:
2557 case OP_NOT:
2558 case OP_OR:
2559 case OP_SBB:
2560 case OP_SUB:
2561 case OP_XCHG:
2562 case OP_XOR:
2563 if (pCpu->param1.flags & (USE_BASE | USE_INDEX | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16 | USE_DISPLACEMENT8 | USE_RIPDISPLACEMENT32))
2564 return;
2565 break;
2566
2567 default:
2568 break;
2569 }
2570
2571 /*
2572 * Invalid lock sequence, make it a OP_ILLUD2.
2573 */
2574 pCpu->pCurInstr = &g_aTwoByteMapX86[11];
2575 Assert(pCpu->pCurInstr->opcode == OP_ILLUD2);
2576}
2577
Note: See TracBrowser for help on using the repository browser.

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