VirtualBox

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

Last change on this file since 20041 was 20041, checked in by vboxsync, 15 years ago

Support 32 bits cr8 accesses (lock mov cr0, eax = mov cr8, eax)

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