VirtualBox

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

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

DIS,CSAM: Combine the displacement members of OP_PARAMETER into a union to save a little bit of space.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 97.9 KB
Line 
1/* $Id: DisasmCore.cpp 41662 2012-06-12 08:29:07Z 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.215389.xyz. 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->uDisp.i32 = 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->uDisp.i64 = 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->uDisp.i32 = pCpu->i32SibDisp;
740 disasmPrintDisp32(pParam);
741 }
742 else
743 {
744 pParam->flags |= USE_RIPDISPLACEMENT32;
745 pParam->uDisp.i32 = pCpu->i32SibDisp;
746 disasmAddString(pParam->szParam, "RIP+");
747 disasmPrintDisp32(pParam);
748 }
749 }
750 else
751 { //register address
752 pParam->flags |= USE_BASE;
753 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
754 }
755 disasmAddChar(pParam->szParam, ']');
756 break;
757
758 case 1: //effective address + 8 bits displacement
759 disasmGetPtrString(pCpu, pOp, pParam);
760 disasmAddChar(pParam->szParam, '[');
761 if (rm == 4) {//SIB byte follows ModRM
762 UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
763 }
764 else
765 {
766 pParam->flags |= USE_BASE;
767 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
768 }
769 pParam->uDisp.i8 = pCpu->i32SibDisp;
770 pParam->flags |= USE_DISPLACEMENT8;
771
772 if (pParam->uDisp.i8 != 0)
773 {
774 if (pParam->uDisp.i8 > 0)
775 disasmAddChar(pParam->szParam, '+');
776 disasmPrintDisp8(pParam);
777 }
778 disasmAddChar(pParam->szParam, ']');
779 break;
780
781 case 2: //effective address + 32 bits displacement
782 disasmGetPtrString(pCpu, pOp, pParam);
783 disasmAddChar(pParam->szParam, '[');
784 if (rm == 4) {//SIB byte follows ModRM
785 UseSIB(lpszCodeBlock, pOp, pParam, pCpu);
786 }
787 else
788 {
789 pParam->flags |= USE_BASE;
790 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
791 }
792 pParam->uDisp.i32 = pCpu->i32SibDisp;
793 pParam->flags |= USE_DISPLACEMENT32;
794
795 if (pParam->uDisp.i32 != 0)
796 {
797 disasmAddChar(pParam->szParam, '+');
798 disasmPrintDisp32(pParam);
799 }
800 disasmAddChar(pParam->szParam, ']');
801 break;
802
803 case 3: //registers
804 disasmModRMReg(pCpu, pOp, rm, pParam, 0);
805 break;
806 }
807 }
808 else
809 {//16 bits addressing mode
810 switch (mod)
811 {
812 case 0: //effective address
813 disasmGetPtrString(pCpu, pOp, pParam);
814 disasmAddChar(pParam->szParam, '[');
815 if (rm == 6)
816 {//16 bits displacement
817 pParam->uDisp.i16 = pCpu->i32SibDisp;
818 pParam->flags |= USE_DISPLACEMENT16;
819 disasmPrintDisp16(pParam);
820 }
821 else
822 {
823 pParam->flags |= USE_BASE;
824 disasmModRMReg16(pCpu, pOp, rm, pParam);
825 }
826 disasmAddChar(pParam->szParam, ']');
827 break;
828
829 case 1: //effective address + 8 bits displacement
830 disasmGetPtrString(pCpu, pOp, pParam);
831 disasmAddChar(pParam->szParam, '[');
832 disasmModRMReg16(pCpu, pOp, rm, pParam);
833 pParam->uDisp.i8 = pCpu->i32SibDisp;
834 pParam->flags |= USE_BASE | USE_DISPLACEMENT8;
835
836 if (pParam->uDisp.i8 != 0)
837 {
838 if (pParam->uDisp.i8 > 0)
839 disasmAddChar(pParam->szParam, '+');
840 disasmPrintDisp8(pParam);
841 }
842 disasmAddChar(pParam->szParam, ']');
843 break;
844
845 case 2: //effective address + 16 bits displacement
846 disasmGetPtrString(pCpu, pOp, pParam);
847 disasmAddChar(pParam->szParam, '[');
848 disasmModRMReg16(pCpu, pOp, rm, pParam);
849 pParam->uDisp.i16 = pCpu->i32SibDisp;
850 pParam->flags |= USE_BASE | USE_DISPLACEMENT16;
851
852 if (pParam->uDisp.i16 != 0)
853 {
854 disasmAddChar(pParam->szParam, '+');
855 disasmPrintDisp16(pParam);
856 }
857 disasmAddChar(pParam->szParam, ']');
858 break;
859
860 case 3: //registers
861 disasmModRMReg(pCpu, pOp, rm, pParam, 0);
862 break;
863 }
864 }
865 return 0; //everything was already fetched in ParseModRM
866}
867//*****************************************************************************
868// Query the size of the ModRM parameters and fetch the immediate data (if any)
869//*****************************************************************************
870unsigned QueryModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
871{
872 unsigned sibinc;
873 unsigned size = 0;
874 // unsigned reg = pCpu->ModRM.Bits.Reg;
875 unsigned mod = pCpu->ModRM.Bits.Mod;
876 unsigned rm = pCpu->ModRM.Bits.Rm;
877
878 if (!pSibInc)
879 pSibInc = &sibinc;
880
881 *pSibInc = 0;
882
883 if (pCpu->addrmode != CPUMODE_16BIT)
884 {
885 Assert(pCpu->addrmode == CPUMODE_32BIT || pCpu->addrmode == CPUMODE_64BIT);
886
887 /*
888 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
889 */
890 if (mod != 3 && rm == 4)
891 { /* SIB byte follows ModRM */
892 *pSibInc = ParseSIB(lpszCodeBlock, pOp, pParam, pCpu);
893 lpszCodeBlock += *pSibInc;
894 size += *pSibInc;
895 }
896
897 switch (mod)
898 {
899 case 0: /* Effective address */
900 if (rm == 5) { /* 32 bits displacement */
901 pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock);
902 size += sizeof(int32_t);
903 }
904 /* else register address */
905 break;
906
907 case 1: /* Effective address + 8 bits displacement */
908 pCpu->i32SibDisp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
909 size += sizeof(char);
910 break;
911
912 case 2: /* Effective address + 32 bits displacement */
913 pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock);
914 size += sizeof(int32_t);
915 break;
916
917 case 3: /* registers */
918 break;
919 }
920 }
921 else
922 {
923 /* 16 bits mode */
924 switch (mod)
925 {
926 case 0: /* Effective address */
927 if (rm == 6) {
928 pCpu->i32SibDisp = DISReadWord(pCpu, lpszCodeBlock);
929 size += sizeof(uint16_t);
930 }
931 /* else register address */
932 break;
933
934 case 1: /* Effective address + 8 bits displacement */
935 pCpu->i32SibDisp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
936 size += sizeof(char);
937 break;
938
939 case 2: /* Effective address + 32 bits displacement */
940 pCpu->i32SibDisp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);
941 size += sizeof(uint16_t);
942 break;
943
944 case 3: /* registers */
945 break;
946 }
947 }
948 return size;
949}
950//*****************************************************************************
951// Query the size of the ModRM parameters and fetch the immediate data (if any)
952//*****************************************************************************
953unsigned QueryModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
954{
955 unsigned sibinc;
956 unsigned size = 0;
957 // unsigned reg = pCpu->ModRM.Bits.Reg;
958 unsigned mod = pCpu->ModRM.Bits.Mod;
959 unsigned rm = pCpu->ModRM.Bits.Rm;
960
961 if (!pSibInc)
962 pSibInc = &sibinc;
963
964 *pSibInc = 0;
965
966 if (pCpu->addrmode != CPUMODE_16BIT)
967 {
968 Assert(pCpu->addrmode == CPUMODE_32BIT || pCpu->addrmode == CPUMODE_64BIT);
969 /*
970 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
971 */
972 if (mod != 3 && rm == 4)
973 { /* SIB byte follows ModRM */
974 *pSibInc = ParseSIB_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu);
975 lpszCodeBlock += *pSibInc;
976 size += *pSibInc;
977 }
978
979 switch (mod)
980 {
981 case 0: //effective address
982 if (rm == 5) { /* 32 bits displacement */
983 size += sizeof(int32_t);
984 }
985 /* else register address */
986 break;
987
988 case 1: /* Effective address + 8 bits displacement */
989 size += sizeof(char);
990 break;
991
992 case 2: /* Effective address + 32 bits displacement */
993 size += sizeof(int32_t);
994 break;
995
996 case 3: /* registers */
997 break;
998 }
999 }
1000 else
1001 {
1002 /* 16 bits mode */
1003 switch (mod)
1004 {
1005 case 0: //effective address
1006 if (rm == 6) {
1007 size += sizeof(uint16_t);
1008 }
1009 /* else register address */
1010 break;
1011
1012 case 1: /* Effective address + 8 bits displacement */
1013 size += sizeof(char);
1014 break;
1015
1016 case 2: /* Effective address + 32 bits displacement */
1017 size += sizeof(uint16_t);
1018 break;
1019
1020 case 3: /* registers */
1021 break;
1022 }
1023 }
1024 return size;
1025}
1026//*****************************************************************************
1027//*****************************************************************************
1028unsigned ParseIllegal(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1029{
1030 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1031 AssertFailed();
1032 return 0;
1033}
1034//*****************************************************************************
1035//*****************************************************************************
1036unsigned ParseModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1037{
1038 unsigned size = sizeof(uint8_t); //ModRM byte
1039 unsigned sibinc, ModRM;
1040
1041 ModRM = DISReadByte(pCpu, lpszCodeBlock);
1042 lpszCodeBlock += sizeof(uint8_t);
1043
1044 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1045 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1046 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1047
1048 /* Disregard the mod bits for certain instructions (mov crx, mov drx).
1049 *
1050 * From the AMD manual:
1051 * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
1052 * encoding of the MOD field in the MODR/M byte.
1053 */
1054 if (pOp->optype & OPTYPE_MOD_FIXED_11)
1055 pCpu->ModRM.Bits.Mod = 3;
1056
1057 if (pCpu->prefix & PREFIX_REX)
1058 {
1059 Assert(pCpu->mode == CPUMODE_64BIT);
1060
1061 /* REX.R extends the Reg field. */
1062 pCpu->ModRM.Bits.Reg |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_R)) << 3);
1063
1064 /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
1065 if (!( pCpu->ModRM.Bits.Mod != 3
1066 && pCpu->ModRM.Bits.Rm == 4)
1067 &&
1068 !( pCpu->ModRM.Bits.Mod == 0
1069 && pCpu->ModRM.Bits.Rm == 5))
1070 {
1071 pCpu->ModRM.Bits.Rm |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_B)) << 3);
1072 }
1073 }
1074 size += QueryModRM(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
1075 lpszCodeBlock += sibinc;
1076
1077 UseModRM(lpszCodeBlock, pOp, pParam, pCpu);
1078 return size;
1079}
1080//*****************************************************************************
1081//*****************************************************************************
1082unsigned ParseModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1083{
1084 unsigned size = sizeof(uint8_t); //ModRM byte
1085 unsigned sibinc, ModRM;
1086
1087 ModRM = DISReadByte(pCpu, lpszCodeBlock);
1088 lpszCodeBlock += sizeof(uint8_t);
1089
1090 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1091 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1092 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1093
1094 /* Disregard the mod bits for certain instructions (mov crx, mov drx).
1095 *
1096 * From the AMD manual:
1097 * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
1098 * encoding of the MOD field in the MODR/M byte.
1099 */
1100 if (pOp->optype & OPTYPE_MOD_FIXED_11)
1101 pCpu->ModRM.Bits.Mod = 3;
1102
1103 if (pCpu->prefix & PREFIX_REX)
1104 {
1105 Assert(pCpu->mode == CPUMODE_64BIT);
1106
1107 /* REX.R extends the Reg field. */
1108 pCpu->ModRM.Bits.Reg |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_R)) << 3);
1109
1110 /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
1111 if (!( pCpu->ModRM.Bits.Mod != 3
1112 && pCpu->ModRM.Bits.Rm == 4)
1113 &&
1114 !( pCpu->ModRM.Bits.Mod == 0
1115 && pCpu->ModRM.Bits.Rm == 5))
1116 {
1117 pCpu->ModRM.Bits.Rm |= ((!!(pCpu->prefix_rex & PREFIX_REX_FLAGS_B)) << 3);
1118 }
1119 }
1120
1121 size += QueryModRM_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
1122 lpszCodeBlock += sibinc;
1123
1124 /* UseModRM is not necessary here; we're only interested in the opcode size */
1125 return size;
1126}
1127//*****************************************************************************
1128//*****************************************************************************
1129unsigned ParseModFence(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1130{
1131 ////AssertMsgFailed(("??\n"));
1132 //nothing to do apparently
1133 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1134 return 0;
1135}
1136//*****************************************************************************
1137//*****************************************************************************
1138unsigned ParseImmByte(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1139{
1140 NOREF(pOp);
1141 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1142 pParam->flags |= USE_IMMEDIATE8;
1143 pParam->size = sizeof(uint8_t);
1144
1145 disasmAddStringF1(pParam->szParam, "0%02Xh", (uint32_t)pParam->parval);
1146 return sizeof(uint8_t);
1147}
1148//*****************************************************************************
1149//*****************************************************************************
1150unsigned ParseImmByte_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1151{
1152 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1153 return sizeof(uint8_t);
1154}
1155//*****************************************************************************
1156//*****************************************************************************
1157unsigned ParseImmByteSX(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1158{
1159 NOREF(pOp);
1160 if (pCpu->opmode == CPUMODE_32BIT)
1161 {
1162 pParam->parval = (uint32_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1163 pParam->flags |= USE_IMMEDIATE32_SX8;
1164 pParam->size = sizeof(uint32_t);
1165 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval);
1166 }
1167 else
1168 if (pCpu->opmode == CPUMODE_64BIT)
1169 {
1170 pParam->parval = (uint64_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1171 pParam->flags |= USE_IMMEDIATE64_SX8;
1172 pParam->size = sizeof(uint64_t);
1173 disasmAddStringF1(pParam->szParam, "0%016RX64h", pParam->parval);
1174 }
1175 else
1176 {
1177 pParam->parval = (uint16_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1178 pParam->flags |= USE_IMMEDIATE16_SX8;
1179 pParam->size = sizeof(uint16_t);
1180 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint16_t)pParam->parval);
1181 }
1182 return sizeof(uint8_t);
1183}
1184//*****************************************************************************
1185//*****************************************************************************
1186unsigned ParseImmByteSX_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1187{
1188 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1189 return sizeof(uint8_t);
1190}
1191//*****************************************************************************
1192//*****************************************************************************
1193unsigned ParseImmUshort(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1194{
1195 NOREF(pOp);
1196 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1197 pParam->flags |= USE_IMMEDIATE16;
1198 pParam->size = sizeof(uint16_t);
1199
1200 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint16_t)pParam->parval);
1201 return sizeof(uint16_t);
1202}
1203//*****************************************************************************
1204//*****************************************************************************
1205unsigned ParseImmUshort_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1206{
1207 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1208 return sizeof(uint16_t);
1209}
1210//*****************************************************************************
1211//*****************************************************************************
1212unsigned ParseImmUlong(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1213{
1214 NOREF(pOp);
1215 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1216 pParam->flags |= USE_IMMEDIATE32;
1217 pParam->size = sizeof(uint32_t);
1218
1219 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval);
1220 return sizeof(uint32_t);
1221}
1222//*****************************************************************************
1223//*****************************************************************************
1224unsigned ParseImmUlong_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1225{
1226 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1227 return sizeof(uint32_t);
1228}
1229//*****************************************************************************
1230//*****************************************************************************
1231unsigned ParseImmQword(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1232{
1233 NOREF(pOp);
1234 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1235 pParam->flags |= USE_IMMEDIATE64;
1236 pParam->size = sizeof(uint64_t);
1237
1238 disasmAddStringF2(pParam->szParam, "0%08X%08Xh",
1239 (uint32_t)pParam->parval, (uint32_t)(pParam->parval >> 32));
1240 return sizeof(uint64_t);
1241}
1242//*****************************************************************************
1243//*****************************************************************************
1244unsigned ParseImmQword_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1245{
1246 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1247 return sizeof(uint64_t);
1248}
1249//*****************************************************************************
1250//*****************************************************************************
1251unsigned ParseImmV(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1252{
1253 NOREF(pOp);
1254 if (pCpu->opmode == CPUMODE_32BIT)
1255 {
1256 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1257 pParam->flags |= USE_IMMEDIATE32;
1258 pParam->size = sizeof(uint32_t);
1259
1260 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval);
1261 return sizeof(uint32_t);
1262 }
1263 else
1264 if (pCpu->opmode == CPUMODE_64BIT)
1265 {
1266 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1267 pParam->flags |= USE_IMMEDIATE64;
1268 pParam->size = sizeof(uint64_t);
1269
1270 disasmAddStringF1(pParam->szParam, "0%RX64h", pParam->parval);
1271 return sizeof(uint64_t);
1272 }
1273 else
1274 {
1275 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1276 pParam->flags |= USE_IMMEDIATE16;
1277 pParam->size = sizeof(uint16_t);
1278
1279 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint32_t)pParam->parval);
1280 return sizeof(uint16_t);
1281 }
1282}
1283//*****************************************************************************
1284//*****************************************************************************
1285unsigned ParseImmV_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1286{
1287 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam);
1288 if (pCpu->opmode == CPUMODE_32BIT)
1289 return sizeof(uint32_t);
1290 if (pCpu->opmode == CPUMODE_64BIT)
1291 return sizeof(uint64_t);
1292 return sizeof(uint16_t);
1293}
1294//*****************************************************************************
1295//*****************************************************************************
1296unsigned ParseImmZ(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1297{
1298 NOREF(pOp);
1299 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1300 if (pCpu->opmode == CPUMODE_16BIT)
1301 {
1302 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1303 pParam->flags |= USE_IMMEDIATE16;
1304 pParam->size = sizeof(uint16_t);
1305
1306 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint32_t)pParam->parval);
1307 return sizeof(uint16_t);
1308 }
1309 else
1310 {
1311 /* 64 bits op mode means *sign* extend to 64 bits. */
1312 if (pCpu->opmode == CPUMODE_64BIT)
1313 {
1314 pParam->parval = (uint64_t)(int32_t)DISReadDWord(pCpu, lpszCodeBlock);
1315 pParam->flags |= USE_IMMEDIATE64;
1316 pParam->size = sizeof(uint64_t);
1317 disasmAddStringF1(pParam->szParam, "0%RX64h", pParam->parval);
1318 }
1319 else
1320 {
1321 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1322 pParam->flags |= USE_IMMEDIATE32;
1323 pParam->size = sizeof(uint32_t);
1324 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval);
1325 }
1326 return sizeof(uint32_t);
1327 }
1328}
1329//*****************************************************************************
1330//*****************************************************************************
1331unsigned ParseImmZ_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1332{
1333 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam);
1334 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1335 if (pCpu->opmode == CPUMODE_16BIT)
1336 return sizeof(uint16_t);
1337 return sizeof(uint32_t);
1338}
1339
1340//*****************************************************************************
1341// Relative displacement for branches (rel. to next instruction)
1342//*****************************************************************************
1343unsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1344{
1345 NOREF(pOp);
1346 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1347 pParam->flags |= USE_IMMEDIATE8_REL;
1348 pParam->size = sizeof(uint8_t);
1349
1350 disasmAddStringF1(pParam->szParam, " (0%02Xh)", (uint32_t)pParam->parval);
1351 return sizeof(char);
1352}
1353//*****************************************************************************
1354// Relative displacement for branches (rel. to next instruction)
1355//*****************************************************************************
1356unsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1357{
1358 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1359 return sizeof(char);
1360}
1361//*****************************************************************************
1362// Relative displacement for branches (rel. to next instruction)
1363//*****************************************************************************
1364unsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1365{
1366 NOREF(pOp);
1367 if (pCpu->opmode == CPUMODE_32BIT)
1368 {
1369 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1370 pParam->flags |= USE_IMMEDIATE32_REL;
1371 pParam->size = sizeof(int32_t);
1372
1373 disasmAddStringF1(pParam->szParam, " (0%08Xh)", (uint32_t)pParam->parval);
1374 return sizeof(int32_t);
1375 }
1376 else
1377 if (pCpu->opmode == CPUMODE_64BIT)
1378 {
1379 /* 32 bits relative immediate sign extended to 64 bits. */
1380 pParam->parval = (uint64_t)(int32_t)DISReadDWord(pCpu, lpszCodeBlock);
1381 pParam->flags |= USE_IMMEDIATE64_REL;
1382 pParam->size = sizeof(int64_t);
1383
1384 disasmAddStringF1(pParam->szParam, " (0%RX64h)", pParam->parval);
1385 return sizeof(int32_t);
1386 }
1387 else
1388 {
1389 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1390 pParam->flags |= USE_IMMEDIATE16_REL;
1391 pParam->size = sizeof(int16_t);
1392
1393 disasmAddStringF1(pParam->szParam, " (0%04Xh)", (uint32_t)pParam->parval);
1394 return sizeof(int16_t);
1395 }
1396}
1397//*****************************************************************************
1398// Relative displacement for branches (rel. to next instruction)
1399//*****************************************************************************
1400unsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1401{
1402 NOREF(lpszCodeBlock); NOREF(pOp); NOREF(pParam);
1403 if (pCpu->opmode == CPUMODE_16BIT)
1404 return sizeof(int16_t);
1405 /* Both 32 & 64 bits mode use 32 bits relative immediates. */
1406 return sizeof(int32_t);
1407}
1408//*****************************************************************************
1409//*****************************************************************************
1410unsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1411{
1412 disasmGetPtrString(pCpu, pOp, pParam);
1413 if (pCpu->addrmode == CPUMODE_32BIT)
1414 {
1415 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1416 {// far 16:32 pointer
1417 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1418 *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
1419 pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
1420 pParam->size = sizeof(uint16_t) + sizeof(uint32_t);
1421
1422 disasmAddStringF2(pParam->szParam, "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
1423 return sizeof(uint32_t) + sizeof(uint16_t);
1424 }
1425 else
1426 {// near 32 bits pointer
1427 /*
1428 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1429 * so we treat it like displacement.
1430 */
1431 pParam->uDisp.i32 = DISReadDWord(pCpu, lpszCodeBlock);
1432 pParam->flags |= USE_DISPLACEMENT32;
1433 pParam->size = sizeof(uint32_t);
1434
1435 disasmAddStringF1(pParam->szParam, "[0%08Xh]", pParam->uDisp.i32);
1436 return sizeof(uint32_t);
1437 }
1438 }
1439 else
1440 if (pCpu->addrmode == CPUMODE_64BIT)
1441 {
1442 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1443 /* near 64 bits pointer */
1444 /*
1445 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1446 * so we treat it like displacement.
1447 */
1448 pParam->uDisp.i64 = DISReadQWord(pCpu, lpszCodeBlock);
1449 pParam->flags |= USE_DISPLACEMENT64;
1450 pParam->size = sizeof(uint64_t);
1451
1452 disasmAddStringF2(pParam->szParam, "[0%08X%08Xh]", (uint32_t)(pParam->uDisp.i64 >> 32), (uint32_t)pParam->uDisp.i64);
1453 return sizeof(uint64_t);
1454 }
1455 else
1456 {
1457 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1458 {// far 16:16 pointer
1459 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1460 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1461 pParam->size = 2*sizeof(uint16_t);
1462
1463 disasmAddStringF2(pParam->szParam, "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1464 return sizeof(uint32_t);
1465 }
1466 else
1467 {// near 16 bits pointer
1468 /*
1469 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1470 * so we treat it like displacement.
1471 */
1472 pParam->uDisp.i16 = DISReadWord(pCpu, lpszCodeBlock);
1473 pParam->flags |= USE_DISPLACEMENT16;
1474 pParam->size = sizeof(uint16_t);
1475
1476 disasmAddStringF1(pParam->szParam, "[0%04Xh]", (uint32_t)pParam->uDisp.i16);
1477 return sizeof(uint16_t);
1478 }
1479 }
1480}
1481//*****************************************************************************
1482//*****************************************************************************
1483unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1484{
1485 NOREF(lpszCodeBlock); NOREF(pOp);
1486 if (pCpu->addrmode == CPUMODE_32BIT)
1487 {
1488 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1489 {// far 16:32 pointer
1490 return sizeof(uint32_t) + sizeof(uint16_t);
1491 }
1492 else
1493 {// near 32 bits pointer
1494 return sizeof(uint32_t);
1495 }
1496 }
1497 if (pCpu->addrmode == CPUMODE_64BIT)
1498 {
1499 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1500 return sizeof(uint64_t);
1501 }
1502 else
1503 {
1504 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1505 {// far 16:16 pointer
1506 return sizeof(uint32_t);
1507 }
1508 else
1509 {// near 16 bits pointer
1510 return sizeof(uint16_t);
1511 }
1512 }
1513}
1514//*****************************************************************************
1515//*****************************************************************************
1516unsigned ParseImmAddrF(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1517{
1518 disasmGetPtrString(pCpu, pOp, pParam);
1519 // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
1520 Assert(pCpu->opmode == CPUMODE_16BIT || pCpu->opmode == CPUMODE_32BIT);
1521 Assert(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p);
1522 if (pCpu->opmode == CPUMODE_32BIT)
1523 {
1524 // far 16:32 pointer
1525 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1526 *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
1527 pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
1528 pParam->size = sizeof(uint16_t) + sizeof(uint32_t);
1529
1530 disasmAddStringF2(pParam->szParam, "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
1531 return sizeof(uint32_t) + sizeof(uint16_t);
1532 }
1533 else
1534 {
1535 // far 16:16 pointer
1536 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1537 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1538 pParam->size = 2*sizeof(uint16_t);
1539
1540 disasmAddStringF2(pParam->szParam, "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1541 return sizeof(uint32_t);
1542 }
1543}
1544//*****************************************************************************
1545//*****************************************************************************
1546unsigned ParseImmAddrF_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1547{
1548 NOREF(lpszCodeBlock); NOREF(pOp);
1549 // immediate far pointers - only 16:16 or 16:32
1550 Assert(pCpu->opmode == CPUMODE_16BIT || pCpu->opmode == CPUMODE_32BIT);
1551 Assert(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p);
1552 if (pCpu->opmode == CPUMODE_32BIT)
1553 {
1554 // far 16:32 pointer
1555 return sizeof(uint32_t) + sizeof(uint16_t);
1556 }
1557 else
1558 {
1559 // far 16:16 pointer
1560 return sizeof(uint32_t);
1561 }
1562}
1563//*****************************************************************************
1564//*****************************************************************************
1565unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1566{
1567 NOREF(lpszCodeBlock);
1568
1569 /*
1570 * Sets up flags for stored in OPC fixed registers.
1571 */
1572
1573 if (pParam->param == OP_PARM_NONE)
1574 {
1575 /* No parameter at all. */
1576 return 0;
1577 }
1578
1579 AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
1580 AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
1581 AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1582 AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
1583
1584 if (pParam->param <= OP_PARM_REG_GEN32_END)
1585 {
1586 /* 32-bit EAX..EDI registers. */
1587 if (pCpu->opmode == CPUMODE_32BIT)
1588 {
1589 /* Use 32-bit registers. */
1590 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1591 pParam->flags |= USE_REG_GEN32;
1592 pParam->size = 4;
1593 }
1594 else
1595 if (pCpu->opmode == CPUMODE_64BIT)
1596 {
1597 /* Use 64-bit registers. */
1598 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1599 if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
1600 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1601 && (pCpu->prefix & PREFIX_REX)
1602 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1603 pParam->base.reg_gen += 8;
1604
1605 pParam->flags |= USE_REG_GEN64;
1606 pParam->size = 8;
1607 }
1608 else
1609 {
1610 /* Use 16-bit registers. */
1611 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1612 pParam->flags |= USE_REG_GEN16;
1613 pParam->size = 2;
1614 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1615 }
1616 }
1617 else
1618 if (pParam->param <= OP_PARM_REG_SEG_END)
1619 {
1620 /* Segment ES..GS registers. */
1621 pParam->base.reg_seg = (DIS_SELREG)(pParam->param - OP_PARM_REG_SEG_START);
1622 pParam->flags |= USE_REG_SEG;
1623 pParam->size = 2;
1624 }
1625 else
1626 if (pParam->param <= OP_PARM_REG_GEN16_END)
1627 {
1628 /* 16-bit AX..DI registers. */
1629 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN16_START;
1630 pParam->flags |= USE_REG_GEN16;
1631 pParam->size = 2;
1632 }
1633 else
1634 if (pParam->param <= OP_PARM_REG_GEN8_END)
1635 {
1636 /* 8-bit AL..DL, AH..DH registers. */
1637 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN8_START;
1638 pParam->flags |= USE_REG_GEN8;
1639 pParam->size = 1;
1640
1641 if (pCpu->opmode == CPUMODE_64BIT)
1642 {
1643 if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
1644 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1645 && (pCpu->prefix & PREFIX_REX)
1646 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1647 pParam->base.reg_gen += 8; /* least significant byte of R8-R15 */
1648 }
1649 }
1650 else
1651 if (pParam->param <= OP_PARM_REG_FP_END)
1652 {
1653 /* FPU registers. */
1654 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1655 pParam->flags |= USE_REG_FP;
1656 pParam->size = 10;
1657 }
1658 Assert(!(pParam->param >= OP_PARM_REG_GEN64_START && pParam->param <= OP_PARM_REG_GEN64_END));
1659
1660 /* else - not supported for now registers. */
1661
1662 return 0;
1663}
1664//*****************************************************************************
1665//*****************************************************************************
1666unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1667{
1668 NOREF(pu8CodeBlock);
1669 disasmGetPtrString(pCpu, pOp, pParam);
1670 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1671
1672 pParam->flags |= USE_POINTER_DS_BASED;
1673 if (pCpu->addrmode == CPUMODE_32BIT)
1674 {
1675 pParam->base.reg_gen = USE_REG_ESI;
1676 pParam->flags |= USE_REG_GEN32;
1677 }
1678 else
1679 if (pCpu->addrmode == CPUMODE_64BIT)
1680 {
1681 pParam->base.reg_gen = USE_REG_RSI;
1682 pParam->flags |= USE_REG_GEN64;
1683 }
1684 else
1685 {
1686 pParam->base.reg_gen = USE_REG_SI;
1687 pParam->flags |= USE_REG_GEN16;
1688 }
1689 return 0; //no additional opcode bytes
1690}
1691//*****************************************************************************
1692//*****************************************************************************
1693unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1694{
1695 NOREF(pu8CodeBlock); NOREF(pOp);
1696 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1697
1698 pParam->flags |= USE_POINTER_DS_BASED;
1699 if (pCpu->addrmode == CPUMODE_32BIT)
1700 {
1701 pParam->base.reg_gen = USE_REG_ESI;
1702 pParam->flags |= USE_REG_GEN32;
1703 }
1704 else
1705 if (pCpu->addrmode == CPUMODE_64BIT)
1706 {
1707 pParam->base.reg_gen = USE_REG_RSI;
1708 pParam->flags |= USE_REG_GEN64;
1709 }
1710 else
1711 {
1712 pParam->base.reg_gen = USE_REG_SI;
1713 pParam->flags |= USE_REG_GEN16;
1714 }
1715 return 0; //no additional opcode bytes
1716}
1717//*****************************************************************************
1718//*****************************************************************************
1719unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1720{
1721 NOREF(pu8CodeBlock);
1722 disasmGetPtrString(pCpu, pOp, pParam);
1723 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1724
1725 pParam->flags |= USE_POINTER_ES_BASED;
1726 if (pCpu->addrmode == CPUMODE_32BIT)
1727 {
1728 pParam->base.reg_gen = USE_REG_EDI;
1729 pParam->flags |= USE_REG_GEN32;
1730 }
1731 else
1732 if (pCpu->addrmode == CPUMODE_64BIT)
1733 {
1734 pParam->base.reg_gen = USE_REG_RDI;
1735 pParam->flags |= USE_REG_GEN64;
1736 }
1737 else
1738 {
1739 pParam->base.reg_gen = USE_REG_DI;
1740 pParam->flags |= USE_REG_GEN16;
1741 }
1742 return 0; //no additional opcode bytes
1743}
1744//*****************************************************************************
1745//*****************************************************************************
1746unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1747{
1748 NOREF(pu8CodeBlock); NOREF(pOp);
1749 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1750
1751 pParam->flags |= USE_POINTER_ES_BASED;
1752 if (pCpu->addrmode == CPUMODE_32BIT)
1753 {
1754 pParam->base.reg_gen = USE_REG_EDI;
1755 pParam->flags |= USE_REG_GEN32;
1756 }
1757 else
1758 if (pCpu->addrmode == CPUMODE_64BIT)
1759 {
1760 pParam->base.reg_gen = USE_REG_RDI;
1761 pParam->flags |= USE_REG_GEN64;
1762 }
1763 else
1764 {
1765 pParam->base.reg_gen = USE_REG_DI;
1766 pParam->flags |= USE_REG_GEN16;
1767 }
1768 return 0; //no additional opcode bytes
1769}
1770//*****************************************************************************
1771//*****************************************************************************
1772unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1773{
1774 const OPCODE *pOpcode;
1775 int size = sizeof(uint8_t);
1776 NOREF(pOp); NOREF(pParam);
1777
1778 /* 2nd byte */
1779 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1780
1781 /* default to the non-prefixed table. */
1782 pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
1783
1784 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1785 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1786 if (pCpu->lastprefix)
1787 {
1788 switch (pCpu->lastprefix)
1789 {
1790 case OP_OPSIZE: /* 0x66 */
1791 if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
1792 {
1793 /* Table entry is valid, so use the extension table. */
1794 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
1795
1796 /* Cancel prefix changes. */
1797 pCpu->prefix &= ~PREFIX_OPSIZE;
1798 pCpu->opmode = pCpu->mode;
1799 }
1800 break;
1801
1802 case OP_REPNE: /* 0xF2 */
1803 if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
1804 {
1805 /* Table entry is valid, so use the extension table. */
1806 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
1807
1808 /* Cancel prefix changes. */
1809 pCpu->prefix &= ~PREFIX_REPNE;
1810 }
1811 break;
1812
1813 case OP_REPE: /* 0xF3 */
1814 if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
1815 {
1816 /* Table entry is valid, so use the extension table. */
1817 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
1818
1819 /* Cancel prefix changes. */
1820 pCpu->prefix &= ~PREFIX_REP;
1821 }
1822 break;
1823 }
1824 }
1825
1826 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1827 return size;
1828}
1829//*****************************************************************************
1830//*****************************************************************************
1831unsigned ParseThreeByteEsc4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1832{
1833 const OPCODE *pOpcode;
1834 int size = sizeof(uint8_t);
1835 NOREF(pOp); NOREF(pParam);
1836
1837 /* 3rd byte */
1838 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1839
1840 /* default to the non-prefixed table. */
1841 if (g_apThreeByteMapX86_0F38[pCpu->opcode >> 4])
1842 {
1843 pOpcode = g_apThreeByteMapX86_0F38[pCpu->opcode >> 4];
1844 pOpcode = &pOpcode[pCpu->opcode & 0xf];
1845 }
1846 else
1847 pOpcode = &g_InvalidOpcode[0];
1848
1849 /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1850 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1851 switch (pCpu->lastprefix)
1852 {
1853 case OP_OPSIZE: /* 0x66 */
1854 if (g_apThreeByteMapX86_660F38[pCpu->opcode >> 4])
1855 {
1856 pOpcode = g_apThreeByteMapX86_660F38[pCpu->opcode >> 4];
1857 pOpcode = &pOpcode[pCpu->opcode & 0xf];
1858
1859 if (pOpcode->opcode != OP_INVALID)
1860 {
1861 /* Table entry is valid, so use the extension table. */
1862
1863 /* Cancel prefix changes. */
1864 pCpu->prefix &= ~PREFIX_OPSIZE;
1865 pCpu->opmode = pCpu->mode;
1866 }
1867 }
1868 break;
1869
1870 case OP_REPNE: /* 0xF2 */
1871 if (g_apThreeByteMapX86_F20F38[pCpu->opcode >> 4])
1872 {
1873 pOpcode = g_apThreeByteMapX86_F20F38[pCpu->opcode >> 4];
1874 pOpcode = &pOpcode[pCpu->opcode & 0xf];
1875
1876 if (pOpcode->opcode != OP_INVALID)
1877 {
1878 /* Table entry is valid, so use the extension table. */
1879
1880 /* Cancel prefix changes. */
1881 pCpu->prefix &= ~PREFIX_REPNE;
1882 }
1883 }
1884 break;
1885 }
1886
1887 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1888 return size;
1889}
1890//*****************************************************************************
1891//*****************************************************************************
1892unsigned ParseThreeByteEsc5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1893{
1894 const OPCODE *pOpcode;
1895 int size = sizeof(uint8_t);
1896 NOREF(pOp); NOREF(pParam);
1897
1898 /* 3rd byte */
1899 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1900
1901 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1902 Assert(pCpu->lastprefix == OP_OPSIZE);
1903
1904 /* default to the non-prefixed table. */
1905 if (g_apThreeByteMapX86_660F3A[pCpu->opcode >> 4])
1906 {
1907 pOpcode = g_apThreeByteMapX86_660F3A[pCpu->opcode >> 4];
1908 pOpcode = &pOpcode[pCpu->opcode & 0xf];
1909
1910 if (pOpcode->opcode != OP_INVALID)
1911 {
1912 /* Table entry is valid, so use the extension table. */
1913
1914 /* Cancel prefix changes. */
1915 pCpu->prefix &= ~PREFIX_OPSIZE;
1916 pCpu->opmode = pCpu->mode;
1917 }
1918 }
1919 else
1920 pOpcode = &g_InvalidOpcode[0];
1921
1922 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1923 return size;
1924}
1925//*****************************************************************************
1926//*****************************************************************************
1927unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1928{
1929 unsigned size = 0;
1930 NOREF(pParam);
1931
1932 if (pCpu->prefix & PREFIX_REP)
1933 {
1934 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1935 pCpu->prefix &= ~PREFIX_REP;
1936 }
1937 else
1938 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1939
1940 size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
1941 return size;
1942}
1943//*****************************************************************************
1944//*****************************************************************************
1945unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1946{
1947 int idx = (pCpu->opcode - 0x80) * 8;
1948 unsigned size = 0, modrm, reg;
1949 NOREF(pParam);
1950
1951 modrm = DISReadByte(pCpu, lpszCodeBlock);
1952 reg = MODRM_REG(modrm);
1953
1954 pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
1955 //little hack to make sure the ModRM byte is included in the returned size
1956 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1957 size = sizeof(uint8_t); //ModRM byte
1958
1959 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1960
1961 return size;
1962}
1963//*****************************************************************************
1964//*****************************************************************************
1965unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1966{
1967 int idx;
1968 unsigned size = 0, modrm, reg;
1969 NOREF(pParam);
1970
1971 switch (pCpu->opcode)
1972 {
1973 case 0xC0:
1974 case 0xC1:
1975 idx = (pCpu->opcode - 0xC0)*8;
1976 break;
1977
1978 case 0xD0:
1979 case 0xD1:
1980 case 0xD2:
1981 case 0xD3:
1982 idx = (pCpu->opcode - 0xD0 + 2)*8;
1983 break;
1984
1985 default:
1986 AssertMsgFailed(("Oops\n"));
1987 return sizeof(uint8_t);
1988 }
1989
1990 modrm = DISReadByte(pCpu, lpszCodeBlock);
1991 reg = MODRM_REG(modrm);
1992
1993 pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
1994
1995 //little hack to make sure the ModRM byte is included in the returned size
1996 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1997 size = sizeof(uint8_t); //ModRM byte
1998
1999 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2000
2001 return size;
2002}
2003//*****************************************************************************
2004//*****************************************************************************
2005unsigned ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2006{
2007 int idx = (pCpu->opcode - 0xF6) * 8;
2008 unsigned size = 0, modrm, reg;
2009 NOREF(pParam);
2010
2011 modrm = DISReadByte(pCpu, lpszCodeBlock);
2012 reg = MODRM_REG(modrm);
2013
2014 pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
2015
2016 //little hack to make sure the ModRM byte is included in the returned size
2017 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2018 size = sizeof(uint8_t); //ModRM byte
2019
2020 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2021
2022 return size;
2023}
2024//*****************************************************************************
2025//*****************************************************************************
2026unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2027{
2028 unsigned size = 0, modrm, reg;
2029 NOREF(pParam);
2030
2031 modrm = DISReadByte(pCpu, lpszCodeBlock);
2032 reg = MODRM_REG(modrm);
2033
2034 pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
2035
2036 //little hack to make sure the ModRM byte is included in the returned size
2037 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2038 size = sizeof(uint8_t); //ModRM byte
2039
2040 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2041
2042 return size;
2043}
2044//*****************************************************************************
2045//*****************************************************************************
2046unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2047{
2048 unsigned size = 0, modrm, reg;
2049 NOREF(pParam);
2050
2051 modrm = DISReadByte(pCpu, lpszCodeBlock);
2052 reg = MODRM_REG(modrm);
2053
2054 pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
2055
2056 //little hack to make sure the ModRM byte is included in the returned size
2057 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2058 size = sizeof(uint8_t); //ModRM byte
2059
2060 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2061
2062 return size;
2063}
2064//*****************************************************************************
2065// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
2066// It would appear the ModRM byte must always be present. How else can you
2067// determine the offset of the imm8_opcode byte otherwise?
2068//
2069//*****************************************************************************
2070unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2071{
2072 unsigned size = 0, modrmsize;
2073
2074#ifdef DEBUG_Sander
2075 //needs testing
2076 AssertMsgFailed(("Test me\n"));
2077#endif
2078
2079 unsigned ModRM = DISReadByte(pCpu, lpszCodeBlock);
2080 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
2081 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
2082 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
2083
2084 modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
2085
2086 uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
2087
2088 pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
2089
2090 //little hack to make sure the ModRM byte is included in the returned size
2091 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2092 {
2093#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
2094 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
2095#endif
2096 size = sizeof(uint8_t); //ModRM byte
2097 }
2098
2099 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2100 size += sizeof(uint8_t); //imm8_opcode uint8_t
2101
2102 return size;
2103}
2104//*****************************************************************************
2105//*****************************************************************************
2106unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2107{
2108 unsigned size = 0, modrm, reg;
2109 NOREF(pParam);
2110
2111 modrm = DISReadByte(pCpu, lpszCodeBlock);
2112 reg = MODRM_REG(modrm);
2113
2114 pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
2115
2116 //little hack to make sure the ModRM byte is included in the returned size
2117 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2118 size = sizeof(uint8_t); //ModRM byte
2119
2120 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2121
2122 return size;
2123}
2124//*****************************************************************************
2125//*****************************************************************************
2126unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2127{
2128 unsigned size = 0, modrm, reg, rm, mod;
2129 NOREF(pParam);
2130
2131 modrm = DISReadByte(pCpu, lpszCodeBlock);
2132 mod = MODRM_MOD(modrm);
2133 reg = MODRM_REG(modrm);
2134 rm = MODRM_RM(modrm);
2135
2136 if (mod == 3 && rm == 0)
2137 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
2138 else
2139 if (mod == 3 && rm == 1)
2140 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
2141 else
2142 pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
2143
2144 //little hack to make sure the ModRM byte is included in the returned size
2145 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2146 size = sizeof(uint8_t); //ModRM byte
2147
2148 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2149
2150 return size;
2151}
2152//*****************************************************************************
2153//*****************************************************************************
2154unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2155{
2156 unsigned size = 0, modrm, reg;
2157 NOREF(pParam);
2158
2159 modrm = DISReadByte(pCpu, lpszCodeBlock);
2160 reg = MODRM_REG(modrm);
2161
2162 pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
2163
2164 //little hack to make sure the ModRM byte is included in the returned size
2165 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2166 size = sizeof(uint8_t); //ModRM byte
2167
2168 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2169
2170 return size;
2171}
2172//*****************************************************************************
2173//*****************************************************************************
2174unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2175{
2176 unsigned size = 0, modrm, reg;
2177 NOREF(pParam);
2178
2179 modrm = DISReadByte(pCpu, lpszCodeBlock);
2180 reg = MODRM_REG(modrm);
2181
2182 pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
2183
2184 //little hack to make sure the ModRM byte is included in the returned size
2185 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2186 size = sizeof(uint8_t); //ModRM byte
2187
2188 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2189
2190 return size;
2191}
2192//*****************************************************************************
2193//*****************************************************************************
2194unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2195{
2196 unsigned size = 0, modrm, reg;
2197 NOREF(pParam);
2198
2199 modrm = DISReadByte(pCpu, lpszCodeBlock);
2200 reg = MODRM_REG(modrm);
2201
2202 pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
2203
2204 //little hack to make sure the ModRM byte is included in the returned size
2205 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2206 size = sizeof(uint8_t); //ModRM byte
2207
2208 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2209
2210 return size;
2211}
2212//*****************************************************************************
2213//*****************************************************************************
2214unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2215{
2216 unsigned size = 0, modrm, reg;
2217 NOREF(pParam);
2218
2219 modrm = DISReadByte(pCpu, lpszCodeBlock);
2220 reg = MODRM_REG(modrm);
2221
2222 if (pCpu->prefix & PREFIX_OPSIZE)
2223 reg += 8; //2nd table
2224
2225 pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
2226
2227 //little hack to make sure the ModRM byte is included in the returned size
2228 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2229 size = sizeof(uint8_t); //ModRM byte
2230
2231 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2232 return size;
2233}
2234//*****************************************************************************
2235//*****************************************************************************
2236unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2237{
2238 unsigned size = 0, modrm, reg;
2239 NOREF(pParam);
2240
2241 modrm = DISReadByte(pCpu, lpszCodeBlock);
2242 reg = MODRM_REG(modrm);
2243 if (pCpu->prefix & PREFIX_OPSIZE)
2244 reg += 8; //2nd table
2245
2246 pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
2247
2248 //little hack to make sure the ModRM byte is included in the returned size
2249 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2250 size = sizeof(uint8_t); //ModRM byte
2251
2252 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2253
2254 return size;
2255}
2256//*****************************************************************************
2257//*****************************************************************************
2258unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2259{
2260 unsigned size = 0, modrm, reg;
2261 NOREF(pParam);
2262
2263 modrm = DISReadByte(pCpu, lpszCodeBlock);
2264 reg = MODRM_REG(modrm);
2265 if (pCpu->prefix & PREFIX_OPSIZE)
2266 reg += 8; //2nd table
2267
2268 pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
2269
2270 //little hack to make sure the ModRM byte is included in the returned size
2271 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2272 size = sizeof(uint8_t); //ModRM byte
2273
2274 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2275
2276 return size;
2277}
2278//*****************************************************************************
2279//*****************************************************************************
2280unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2281{
2282 unsigned size = 0, modrm, reg, mod, rm;
2283 NOREF(pParam);
2284
2285 modrm = DISReadByte(pCpu, lpszCodeBlock);
2286 mod = MODRM_MOD(modrm);
2287 reg = MODRM_REG(modrm);
2288 rm = MODRM_RM(modrm);
2289
2290 if (mod == 3 && rm == 0)
2291 pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
2292 else
2293 pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
2294
2295 //little hack to make sure the ModRM byte is included in the returned size
2296 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2297 size = sizeof(uint8_t); //ModRM byte
2298
2299 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2300 return size;
2301}
2302//*****************************************************************************
2303//*****************************************************************************
2304unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2305{
2306 unsigned size = 0, modrm, reg;
2307 NOREF(pParam);
2308
2309 modrm = DISReadByte(pCpu, lpszCodeBlock);
2310 reg = MODRM_REG(modrm);
2311
2312 pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
2313
2314 //little hack to make sure the ModRM byte is included in the returned size
2315 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2316 size = sizeof(uint8_t); //ModRM byte
2317
2318 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2319 return size;
2320}
2321//*****************************************************************************
2322#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2323static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"};
2324static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"};
2325static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"};
2326static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
2327static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
2328#endif
2329static const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
2330static 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};
2331static const int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
2332//*****************************************************************************
2333void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam, int fRegAddr)
2334{
2335 int subtype, type, mod;
2336 NOREF(pOp); NOREF(pCpu);
2337
2338 mod = pCpu->ModRM.Bits.Mod;
2339
2340 type = OP_PARM_VTYPE(pParam->param);
2341 subtype = OP_PARM_VSUBTYPE(pParam->param);
2342 if (fRegAddr)
2343 subtype = (pCpu->addrmode == CPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
2344 else
2345 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
2346 {
2347 switch(pCpu->opmode)
2348 {
2349 case CPUMODE_32BIT:
2350 subtype = OP_PARM_d;
2351 break;
2352 case CPUMODE_64BIT:
2353 subtype = OP_PARM_q;
2354 break;
2355 case CPUMODE_16BIT:
2356 subtype = OP_PARM_w;
2357 break;
2358 default:
2359 /* make gcc happy */
2360 break;
2361 }
2362 }
2363
2364 switch (subtype)
2365 {
2366 case OP_PARM_b:
2367 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8);
2368
2369 /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
2370 /* Intel® 64 and IA-32 Architectures Software Developer’s Manual: 3.4.1.1 */
2371 if ( (pCpu->prefix & PREFIX_REX)
2372 && idx >= USE_REG_AH
2373 && idx <= USE_REG_BH)
2374 {
2375 idx += (USE_REG_SPL - USE_REG_AH);
2376 }
2377 disasmAddString(pParam->szParam, szModRMReg8[idx]);
2378
2379 pParam->flags |= USE_REG_GEN8;
2380 pParam->base.reg_gen = idx;
2381 break;
2382
2383 case OP_PARM_w:
2384 disasmAddString(pParam->szParam, szModRMReg16[idx]);
2385 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8);
2386
2387 pParam->flags |= USE_REG_GEN16;
2388 pParam->base.reg_gen = idx;
2389 break;
2390
2391 case OP_PARM_d:
2392 disasmAddString(pParam->szParam, szModRMReg32[idx]);
2393 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8);
2394
2395 pParam->flags |= USE_REG_GEN32;
2396 pParam->base.reg_gen = idx;
2397 break;
2398
2399 case OP_PARM_q:
2400 disasmAddString(pParam->szParam, szModRMReg64[idx]);
2401 pParam->flags |= USE_REG_GEN64;
2402 pParam->base.reg_gen = idx;
2403 break;
2404
2405 default:
2406 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
2407 pCpu->rc = VERR_DIS_INVALID_MODRM;
2408 break;
2409 }
2410}
2411//*****************************************************************************
2412//*****************************************************************************
2413void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam)
2414{
2415 NOREF(pCpu); NOREF(pOp);
2416 disasmAddString(pParam->szParam, szModRMReg1616[idx]);
2417 pParam->flags |= USE_REG_GEN16;
2418 pParam->base.reg_gen = BaseModRMReg16[idx];
2419 if (idx < 4)
2420 {
2421 pParam->flags |= USE_INDEX;
2422 pParam->index.reg_gen = IndexModRMReg16[idx];
2423 }
2424}
2425//*****************************************************************************
2426//*****************************************************************************
2427void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam)
2428{
2429 NOREF(pOp);
2430 if (idx >= RT_ELEMENTS(szModRMSegReg))
2431 {
2432 Log(("disasmModRMSReg %d failed!!\n", idx));
2433 pCpu->rc = VERR_DIS_INVALID_PARAMETER;
2434 return;
2435 }
2436
2437 disasmAddString(pParam->szParam, szModRMSegReg[idx]);
2438 pParam->flags |= USE_REG_SEG;
2439 pParam->base.reg_seg = (DIS_SELREG)idx;
2440}
2441//*****************************************************************************
2442//*****************************************************************************
2443void disasmPrintAbs32(POP_PARAMETER pParam)
2444{
2445 disasmAddStringF1(pParam->szParam, "%08Xh", pParam->uDisp.i32); NOREF(pParam);
2446}
2447//*****************************************************************************
2448//*****************************************************************************
2449void disasmPrintDisp32(POP_PARAMETER pParam)
2450{
2451 disasmAddStringF1(pParam->szParam, "%08Xh", pParam->uDisp.i32); NOREF(pParam);
2452}
2453//*****************************************************************************
2454//*****************************************************************************
2455void disasmPrintDisp64(POP_PARAMETER pParam)
2456{
2457 disasmAddStringF1(pParam->szParam, "%16RX64h", pParam->uDisp.i64); NOREF(pParam);
2458}
2459//*****************************************************************************
2460//*****************************************************************************
2461void disasmPrintDisp8(POP_PARAMETER pParam)
2462{
2463 disasmAddStringF1(pParam->szParam, "%d", pParam->uDisp.i8); NOREF(pParam);
2464}
2465//*****************************************************************************
2466//*****************************************************************************
2467void disasmPrintDisp16(POP_PARAMETER pParam)
2468{
2469 disasmAddStringF1(pParam->szParam, "%04Xh", pParam->uDisp.i16); NOREF(pParam);
2470}
2471//*****************************************************************************
2472//*****************************************************************************
2473void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
2474{
2475 int subtype = OP_PARM_VSUBTYPE(pParam->param);
2476 NOREF(pOp);
2477
2478 if (subtype == OP_PARM_v)
2479 {
2480 switch(pCpu->opmode)
2481 {
2482 case CPUMODE_32BIT:
2483 subtype = OP_PARM_d;
2484 break;
2485 case CPUMODE_64BIT:
2486 subtype = OP_PARM_q;
2487 break;
2488 case CPUMODE_16BIT:
2489 subtype = OP_PARM_w;
2490 break;
2491 default:
2492 /* make gcc happy */
2493 break;
2494 }
2495 }
2496
2497 switch (subtype)
2498 {
2499 case OP_PARM_a: //two words or dwords depending on operand size (bound only)
2500 break;
2501
2502 case OP_PARM_b:
2503 disasmAddString(pParam->szParam, "byte ptr ");
2504 break;
2505
2506 case OP_PARM_w:
2507 disasmAddString(pParam->szParam, "word ptr ");
2508 break;
2509
2510 case OP_PARM_d:
2511 disasmAddString(pParam->szParam, "dword ptr ");
2512 break;
2513
2514 case OP_PARM_q:
2515 case OP_PARM_dq:
2516 disasmAddString(pParam->szParam, "qword ptr ");
2517 break;
2518
2519 case OP_PARM_p:
2520 disasmAddString(pParam->szParam, "far ptr ");
2521 break;
2522
2523 case OP_PARM_s:
2524 break; //??
2525
2526 case OP_PARM_z:
2527 break;
2528 default:
2529 break; //no pointer type specified/necessary
2530 }
2531 if (pCpu->prefix & PREFIX_SEG)
2532 disasmAddStringF1(pParam->szParam, "%s:", szModRMSegReg[pCpu->enmPrefixSeg]);
2533}
2534
2535
2536/**
2537 * Slow path for storing instruction bytes.
2538 *
2539 * @param pCpu The disassembler state.
2540 * @param uAddress The address.
2541 * @param pbSrc The bytes.
2542 * @param cbSrc The number of bytes.
2543 */
2544DECL_NO_INLINE(static, void)
2545disStoreInstrBytesSlow(PDISCPUSTATE pCpu, RTUINTPTR uAddress, const uint8_t *pbSrc, size_t cbSrc)
2546{
2547 /*
2548 * Figure out which case it is.
2549 */
2550 uint32_t cbInstr = pCpu->opsize;
2551 RTUINTPTR off = uAddress - pCpu->uInstrAddr;
2552 if (off < cbInstr)
2553 {
2554 if (off + cbSrc <= cbInstr)
2555 {
2556 AssertMsg(memcmp(&pCpu->abInstr[off], pbSrc, cbSrc) == 0,
2557 ("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
2558 return; /* fully re-reading old stuff. */
2559 }
2560
2561 /* Only partially re-reading stuff, skip ahead and add the rest. */
2562 uint32_t cbAlreadyRead = cbInstr - (uint32_t)off;
2563 Assert(memcmp(&pCpu->abInstr[off], pbSrc, cbAlreadyRead) == 0);
2564 uAddress += cbAlreadyRead;
2565 pbSrc += cbAlreadyRead;
2566 cbSrc -= cbAlreadyRead;
2567 }
2568
2569 if (off >= sizeof(cbInstr))
2570 {
2571 /* The instruction is too long! This shouldn't happen. */
2572 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
2573 return;
2574 }
2575 else if (off > cbInstr)
2576 {
2577 /* Mind the gap - this shouldn't happen, but read the gap bytes if it does. */
2578 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.16Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
2579 uint32_t cbGap = off - cbInstr;
2580 int rc = pCpu->pfnReadBytes(pCpu, &pCpu->abInstr[cbInstr], uAddress - cbGap, cbGap);
2581 if (RT_FAILURE(rc))
2582 {
2583 pCpu->rc = VERR_DIS_MEM_READ;
2584 RT_BZERO(&pCpu->abInstr[cbInstr], cbGap);
2585 }
2586 pCpu->opsize = cbInstr = off;
2587 }
2588
2589 /*
2590 * Copy the bytes.
2591 */
2592 if (off + cbSrc <= sizeof(pCpu->abInstr))
2593 {
2594 memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbSrc);
2595 pCpu->opsize = cbInstr + (uint32_t)cbSrc;
2596 }
2597 else
2598 {
2599 size_t cbToCopy = sizeof(pCpu->abInstr) - off;
2600 memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbToCopy);
2601 pCpu->opsize = sizeof(pCpu->abInstr);
2602 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, sizeof(pCpu->abInstr), pCpu->abInstr));
2603 }
2604}
2605
2606DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
2607{
2608#ifdef IN_RING0
2609 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
2610 RT_BZERO(pbDst, cbToRead);
2611 return VERR_DIS_NO_READ_CALLBACK;
2612#else
2613 memcpy(pbDst, (void const *)(uintptr_t)uSrcAddr, cbToRead);
2614 return VINF_SUCCESS;
2615#endif
2616}
2617
2618//*****************************************************************************
2619/* Read functions for getting the opcode bytes */
2620//*****************************************************************************
2621uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2622{
2623 uint8_t bTemp = 0;
2624 int rc = pCpu->pfnReadBytes(pCpu, &bTemp, uAddress, sizeof(bTemp));
2625 if (RT_FAILURE(rc))
2626 {
2627 Log(("DISReadByte failed!!\n"));
2628 pCpu->rc = VERR_DIS_MEM_READ;
2629 }
2630
2631/** @todo change this into reading directly into abInstr and use it as a
2632 * cache. */
2633 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress
2634 && pCpu->opsize + sizeof(bTemp) < sizeof(pCpu->abInstr)))
2635 pCpu->abInstr[pCpu->opsize++] = bTemp;
2636 else
2637 disStoreInstrBytesSlow(pCpu, uAddress, &bTemp, sizeof(bTemp));
2638
2639 return bTemp;
2640}
2641//*****************************************************************************
2642//*****************************************************************************
2643uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2644{
2645 RTUINT16U uTemp;
2646 uTemp.u = 0;
2647 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
2648 if (RT_FAILURE(rc))
2649 {
2650 Log(("DISReadWord failed!!\n"));
2651 pCpu->rc = VERR_DIS_MEM_READ;
2652 }
2653
2654 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress
2655 && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr)))
2656 {
2657 pCpu->abInstr[pCpu->opsize ] = uTemp.au8[0];
2658 pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1];
2659 pCpu->opsize += 2;
2660 }
2661 else
2662 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
2663
2664 return uTemp.u;
2665}
2666//*****************************************************************************
2667//*****************************************************************************
2668uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2669{
2670 RTUINT32U uTemp;
2671 uTemp.u = 0;
2672 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
2673 if (RT_FAILURE(rc))
2674 {
2675 Log(("DISReadDWord failed!!\n"));
2676 pCpu->rc = VERR_DIS_MEM_READ;
2677 }
2678
2679 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress
2680 && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr)))
2681 {
2682 pCpu->abInstr[pCpu->opsize ] = uTemp.au8[0];
2683 pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1];
2684 pCpu->abInstr[pCpu->opsize + 2] = uTemp.au8[2];
2685 pCpu->abInstr[pCpu->opsize + 3] = uTemp.au8[3];
2686 pCpu->opsize += 4;
2687 }
2688 else
2689 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
2690
2691 return uTemp.u;
2692}
2693//*****************************************************************************
2694//*****************************************************************************
2695uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2696{
2697 RTUINT64U uTemp;
2698 uTemp.u = 0;
2699 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
2700 if (RT_FAILURE(rc))
2701 {
2702 Log(("DISReadQWord %x failed!!\n", uAddress));
2703 pCpu->rc = VERR_DIS_MEM_READ;
2704 }
2705
2706 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress
2707 && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr)))
2708 {
2709 pCpu->abInstr[pCpu->opsize ] = uTemp.au8[0];
2710 pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1];
2711 pCpu->abInstr[pCpu->opsize + 2] = uTemp.au8[2];
2712 pCpu->abInstr[pCpu->opsize + 3] = uTemp.au8[3];
2713 pCpu->abInstr[pCpu->opsize + 4] = uTemp.au8[4];
2714 pCpu->abInstr[pCpu->opsize + 5] = uTemp.au8[5];
2715 pCpu->abInstr[pCpu->opsize + 6] = uTemp.au8[6];
2716 pCpu->abInstr[pCpu->opsize + 7] = uTemp.au8[7];
2717 pCpu->opsize += 4;
2718 }
2719 else
2720 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
2721
2722 return uTemp.u;
2723}
2724
2725#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2726//*****************************************************************************
2727//*****************************************************************************
2728void disasmAddString(char *psz, const char *pszAdd)
2729{
2730 strcat(psz, pszAdd);
2731}
2732//*****************************************************************************
2733//*****************************************************************************
2734void disasmAddStringF(char *psz, const char *pszFormat, ...)
2735{
2736 va_list args;
2737 va_start(args, pszFormat);
2738 size_t cchCur = strlen(psz);
2739 Assert(cchCur < RT_SIZEOFMEMB(OP_PARAMETER, szParam));
2740 RTStrPrintfV(psz + cchCur, RT_SIZEOFMEMB(OP_PARAMETER, szParam) - cchCur,
2741 pszFormat, args);
2742 va_end(args);
2743}
2744
2745//*****************************************************************************
2746//*****************************************************************************
2747void disasmAddChar(char *psz, char ch)
2748{
2749 char sz[2];
2750
2751 sz[0] = ch;
2752 sz[1] = '\0';
2753 strcat(psz, sz);
2754}
2755#endif /* !DIS_CORE_ONLY */
2756
2757
2758/**
2759 * Validates the lock sequence.
2760 *
2761 * The AMD manual lists the following instructions:
2762 * ADC
2763 * ADD
2764 * AND
2765 * BTC
2766 * BTR
2767 * BTS
2768 * CMPXCHG
2769 * CMPXCHG8B
2770 * CMPXCHG16B
2771 * DEC
2772 * INC
2773 * NEG
2774 * NOT
2775 * OR
2776 * SBB
2777 * SUB
2778 * XADD
2779 * XCHG
2780 * XOR
2781 *
2782 * @param pCpu Fully disassembled instruction.
2783 */
2784void disValidateLockSequence(PDISCPUSTATE pCpu)
2785{
2786 Assert(pCpu->prefix & PREFIX_LOCK);
2787
2788 /*
2789 * Filter out the valid lock sequences.
2790 */
2791 switch (pCpu->pCurInstr->opcode)
2792 {
2793 /* simple: no variations */
2794 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2795 return;
2796
2797 /* simple: /r - reject register destination. */
2798 case OP_BTC:
2799 case OP_BTR:
2800 case OP_BTS:
2801 case OP_CMPXCHG:
2802 case OP_XADD:
2803 if (pCpu->ModRM.Bits.Mod == 3)
2804 break;
2805 return;
2806
2807 /*
2808 * Lots of variants but its sufficient to check that param 1
2809 * is a memory operand.
2810 */
2811 case OP_ADC:
2812 case OP_ADD:
2813 case OP_AND:
2814 case OP_DEC:
2815 case OP_INC:
2816 case OP_NEG:
2817 case OP_NOT:
2818 case OP_OR:
2819 case OP_SBB:
2820 case OP_SUB:
2821 case OP_XCHG:
2822 case OP_XOR:
2823 if (pCpu->param1.flags & (USE_BASE | USE_INDEX | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16 | USE_DISPLACEMENT8 | USE_RIPDISPLACEMENT32))
2824 return;
2825 break;
2826
2827 default:
2828 break;
2829 }
2830
2831 /*
2832 * Invalid lock sequence, make it a OP_ILLUD2.
2833 */
2834 pCpu->pCurInstr = &g_aTwoByteMapX86[11];
2835 Assert(pCpu->pCurInstr->opcode == OP_ILLUD2);
2836}
2837
Note: See TracBrowser for help on using the repository browser.

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