VirtualBox

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

Last change on this file since 8999 was 8999, checked in by vboxsync, 17 years ago

Disassembler updates for 64 bits code

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

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