VirtualBox

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

Last change on this file since 39656 was 39086, checked in by vboxsync, 13 years ago

Dis,SrvPciRaw,Sup: warning fixes.

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