VirtualBox

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

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

DIS,DIS-users: Drop the operand/parameter formatting during instruction parsing. The desired formatter can do this afterwards if desired. Should save time + size. (DISCPUSTATE is now 256 bytes here on 64-bit linux, was ~406 yesterday.)

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