VirtualBox

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

Last change on this file since 41661 was 41661, checked in by vboxsync, 12 years ago

DIS: Windows build fix

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