VirtualBox

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

Last change on this file since 41528 was 41494, checked in by vboxsync, 13 years ago

DISCoreOne: don't assert on invalid opcode, just return VERR_DIS_INVALID_OPCODE.

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