VirtualBox

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

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

Dropped the USE_EFFICIENT_ADDRESS flag. This breaks assumptions in CSAM about parameter flags.
Instead use DIS_IS_EFFECTIVE_ADDRESS.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 86.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.param = fpop->param1;
469 pCpu->param2.param = 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 pParam->size = sizeof(uint8_t);
1136
1137 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%02Xh", (uint32_t)pParam->parval);
1138 return sizeof(uint8_t);
1139}
1140//*****************************************************************************
1141//*****************************************************************************
1142unsigned ParseImmByte_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1143{
1144 return sizeof(uint8_t);
1145}
1146//*****************************************************************************
1147//*****************************************************************************
1148unsigned ParseImmByteSX(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1149{
1150 if (pCpu->opmode == CPUMODE_32BIT) /** @todo In AMD64 mode we're ending up with 16-bit parvals now, see the disassembler _output_ for tstAsmSignExtend-1.asm. */
1151 {
1152 pParam->parval = (uint32_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1153 pParam->flags |= USE_IMMEDIATE32_SX8;
1154 pParam->size = sizeof(uint32_t);
1155 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1156 }
1157 else
1158 {
1159 pParam->parval = (uint16_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1160 pParam->flags |= USE_IMMEDIATE16_SX8;
1161 pParam->size = sizeof(uint16_t);
1162 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
1163 }
1164 return sizeof(uint8_t);
1165}
1166//*****************************************************************************
1167//*****************************************************************************
1168unsigned ParseImmByteSX_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1169{
1170 return sizeof(uint8_t);
1171}
1172//*****************************************************************************
1173//*****************************************************************************
1174unsigned ParseImmUshort(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1175{
1176 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1177 pParam->flags |= USE_IMMEDIATE16;
1178 pParam->size = sizeof(uint16_t);
1179
1180 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
1181 return sizeof(uint16_t);
1182}
1183//*****************************************************************************
1184//*****************************************************************************
1185unsigned ParseImmUshort_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1186{
1187 return sizeof(uint16_t);
1188}
1189//*****************************************************************************
1190//*****************************************************************************
1191unsigned ParseImmUlong(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1192{
1193 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1194 pParam->flags |= USE_IMMEDIATE32;
1195 pParam->size = sizeof(uint32_t);
1196
1197 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1198 return sizeof(uint32_t);
1199}
1200//*****************************************************************************
1201//*****************************************************************************
1202unsigned ParseImmUlong_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1203{
1204 return sizeof(uint32_t);
1205}
1206//*****************************************************************************
1207//*****************************************************************************
1208unsigned ParseImmQword(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1209{
1210 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1211 pParam->flags |= USE_IMMEDIATE64;
1212 pParam->size = sizeof(uint64_t);
1213
1214 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08X", (uint32_t)pParam->parval);
1215 disasmAddStringF(&pParam->szParam[9], sizeof(pParam->szParam)-9, "%08Xh", (uint32_t)(pParam->parval >> 32));
1216 return sizeof(uint64_t);
1217}
1218//*****************************************************************************
1219//*****************************************************************************
1220unsigned ParseImmQword_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1221{
1222 return sizeof(uint64_t);
1223}
1224//*****************************************************************************
1225//*****************************************************************************
1226unsigned ParseImmV(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1227{
1228 if (pCpu->opmode == CPUMODE_32BIT)
1229 {
1230 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1231 pParam->flags |= USE_IMMEDIATE32;
1232 pParam->size = sizeof(uint32_t);
1233
1234 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1235 return sizeof(uint32_t);
1236 }
1237 else
1238 if (pCpu->opmode == CPUMODE_64BIT)
1239 {
1240 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1241 pParam->flags |= USE_IMMEDIATE64;
1242 pParam->size = sizeof(uint64_t);
1243
1244 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%VX64h", pParam->parval);
1245 return sizeof(uint64_t);
1246 }
1247 else
1248 {
1249 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1250 pParam->flags |= USE_IMMEDIATE16;
1251 pParam->size = sizeof(uint16_t);
1252
1253 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint32_t)pParam->parval);
1254 return sizeof(uint16_t);
1255 }
1256}
1257//*****************************************************************************
1258//*****************************************************************************
1259unsigned ParseImmV_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1260{
1261 if (pCpu->opmode == CPUMODE_32BIT)
1262 return sizeof(uint32_t);
1263 else
1264 if (pCpu->opmode == CPUMODE_64BIT)
1265 return sizeof(uint64_t);
1266
1267 return sizeof(uint16_t);
1268}
1269//*****************************************************************************
1270//*****************************************************************************
1271unsigned ParseImmZ(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1272{
1273 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1274 if (pCpu->opmode == CPUMODE_16BIT)
1275 {
1276 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1277 pParam->flags |= USE_IMMEDIATE16;
1278 pParam->size = sizeof(uint16_t);
1279
1280 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint32_t)pParam->parval);
1281 return sizeof(uint16_t);
1282 }
1283 else
1284 {
1285 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1286 pParam->flags |= USE_IMMEDIATE32;
1287 pParam->size = sizeof(uint32_t);
1288
1289 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1290 return sizeof(uint32_t);
1291 }
1292}
1293//*****************************************************************************
1294//*****************************************************************************
1295unsigned ParseImmZ_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1296{
1297 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1298 if (pCpu->opmode == CPUMODE_16BIT)
1299 return sizeof(uint16_t);
1300 return sizeof(uint32_t);
1301}
1302
1303//*****************************************************************************
1304// Relative displacement for branches (rel. to next instruction)
1305//*****************************************************************************
1306unsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1307{
1308 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1309 pParam->flags |= USE_IMMEDIATE8_REL;
1310 pParam->size = sizeof(uint8_t);
1311
1312 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%02Xh)", (uint32_t)pParam->parval);
1313 return sizeof(char);
1314}
1315//*****************************************************************************
1316// Relative displacement for branches (rel. to next instruction)
1317//*****************************************************************************
1318unsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1319{
1320 return sizeof(char);
1321}
1322//*****************************************************************************
1323// Relative displacement for branches (rel. to next instruction)
1324//*****************************************************************************
1325unsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1326{
1327 if (pCpu->opmode == CPUMODE_32BIT)
1328 {
1329 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1330 pParam->flags |= USE_IMMEDIATE32_REL;
1331 pParam->size = sizeof(int32_t);
1332
1333 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%08Xh)", (uint32_t)pParam->parval);
1334 return sizeof(int32_t);
1335 }
1336 else
1337 if (pCpu->opmode == CPUMODE_64BIT)
1338 {
1339 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1340 pParam->flags |= USE_IMMEDIATE64_REL;
1341 pParam->size = sizeof(int64_t);
1342
1343 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%VX64h)", pParam->parval);
1344 return sizeof(int64_t);
1345 }
1346 else
1347 {
1348 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1349 pParam->flags |= USE_IMMEDIATE16_REL;
1350 pParam->size = sizeof(int16_t);
1351
1352 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%04Xh)", (uint32_t)pParam->parval);
1353 return sizeof(uint16_t);
1354 }
1355}
1356//*****************************************************************************
1357// Relative displacement for branches (rel. to next instruction)
1358//*****************************************************************************
1359unsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1360{
1361 if (pCpu->opmode == CPUMODE_32BIT)
1362 return sizeof(int32_t);
1363 else
1364 if (pCpu->opmode == CPUMODE_64BIT)
1365 return sizeof(int64_t);
1366 return sizeof(uint16_t);
1367}
1368//*****************************************************************************
1369//*****************************************************************************
1370unsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1371{
1372 disasmGetPtrString(pCpu, pOp, pParam);
1373 if (pCpu->addrmode == CPUMODE_32BIT)
1374 {
1375 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1376 {// far 16:32 pointer
1377 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1378 *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
1379 pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
1380 pParam->size = sizeof(uint16_t) + sizeof(uint32_t);
1381
1382 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
1383 return sizeof(uint32_t) + sizeof(uint16_t);
1384 }
1385 else
1386 {// near 32 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->disp32 = DISReadDWord(pCpu, lpszCodeBlock);
1392 pParam->flags |= USE_DISPLACEMENT32;
1393 pParam->size = sizeof(uint32_t);
1394
1395 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08Xh]", pParam->disp32);
1396 return sizeof(uint32_t);
1397 }
1398 }
1399 else
1400 if (pCpu->addrmode == CPUMODE_64BIT)
1401 {
1402 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1403 /* near 64 bits pointer */
1404 /*
1405 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1406 * so we treat it like displacement.
1407 */
1408 pParam->disp64 = DISReadQWord(pCpu, lpszCodeBlock);
1409 pParam->flags |= USE_DISPLACEMENT64;
1410 pParam->size = sizeof(uint64_t);
1411
1412 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64);
1413 return sizeof(uint64_t);
1414 }
1415 else
1416 {
1417 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1418 {// far 16:16 pointer
1419 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1420 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1421 pParam->size = 2*sizeof(uint16_t);
1422
1423 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1424 return sizeof(uint32_t);
1425 }
1426 else
1427 {// near 16 bits pointer
1428 /*
1429 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1430 * so we treat it like displacement.
1431 */
1432 pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
1433 pParam->flags |= USE_DISPLACEMENT16;
1434 pParam->size = sizeof(uint16_t);
1435
1436 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
1437 return sizeof(uint16_t);
1438 }
1439 }
1440}
1441//*****************************************************************************
1442//*****************************************************************************
1443unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1444{
1445 if (pCpu->addrmode == CPUMODE_32BIT)
1446 {
1447 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1448 {// far 16:32 pointer
1449 return sizeof(uint32_t) + sizeof(uint16_t);
1450 }
1451 else
1452 {// near 32 bits pointer
1453 return sizeof(uint32_t);
1454 }
1455 }
1456 if (pCpu->addrmode == CPUMODE_64BIT)
1457 {
1458 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1459 return sizeof(uint64_t);
1460 }
1461 else
1462 {
1463 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1464 {// far 16:16 pointer
1465 return sizeof(uint32_t);
1466 }
1467 else
1468 {// near 16 bits pointer
1469 return sizeof(uint16_t);
1470 }
1471 }
1472}
1473//*****************************************************************************
1474//*****************************************************************************
1475unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1476{
1477 /*
1478 * Sets up flags for stored in OPC fixed registers.
1479 */
1480
1481 if (pParam->param == OP_PARM_NONE)
1482 {
1483 /* No parameter at all. */
1484 return 0;
1485 }
1486
1487 AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
1488 AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
1489 AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1490 AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
1491
1492 if (pParam->param <= OP_PARM_REG_GEN32_END)
1493 {
1494 /* 32-bit EAX..EDI registers. */
1495 if (pCpu->opmode == CPUMODE_32BIT)
1496 {
1497 /* Use 32-bit registers. */
1498 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1499 pParam->flags |= USE_REG_GEN32;
1500 pParam->size = 4;
1501 }
1502 else
1503 if (pCpu->opmode == CPUMODE_64BIT)
1504 {
1505 /* Use 64-bit registers. */
1506 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1507 if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
1508 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1509 && (pCpu->prefix & PREFIX_REX)
1510 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1511 pParam->base.reg_gen += 8;
1512
1513 pParam->flags |= USE_REG_GEN64;
1514 pParam->size = 8;
1515 }
1516 else
1517 {
1518 /* Use 16-bit registers. */
1519 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1520 pParam->flags |= USE_REG_GEN16;
1521 pParam->size = 2;
1522 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1523 }
1524 }
1525 else
1526 if (pParam->param <= OP_PARM_REG_SEG_END)
1527 {
1528 /* Segment ES..GS registers. */
1529 pParam->base.reg_seg = pParam->param - OP_PARM_REG_SEG_START;
1530 pParam->flags |= USE_REG_SEG;
1531 pParam->size = 2;
1532 }
1533 else
1534 if (pParam->param <= OP_PARM_REG_GEN16_END)
1535 {
1536 /* 16-bit AX..DI registers. */
1537 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN16_START;
1538 pParam->flags |= USE_REG_GEN16;
1539 pParam->size = 2;
1540 }
1541 else
1542 if (pParam->param <= OP_PARM_REG_GEN8_END)
1543 {
1544 /* 8-bit AL..DL, AH..DH registers. */
1545 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN8_START;
1546 pParam->flags |= USE_REG_GEN8;
1547 pParam->size = 1;
1548
1549 if (pCpu->opmode == CPUMODE_64BIT)
1550 {
1551 if ( (pOp->optype & OPTYPE_REXB_EXTENDS_OPREG)
1552 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1553 && (pCpu->prefix & PREFIX_REX)
1554 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1555 pParam->base.reg_gen += 8; /* least significant byte of R8-R15 */
1556 }
1557 }
1558 else
1559 if (pParam->param <= OP_PARM_REG_FP_END)
1560 {
1561 /* FPU registers. */
1562 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1563 pParam->flags |= USE_REG_FP;
1564 pParam->size = 10;
1565 }
1566 Assert(!(pParam->param >= OP_PARM_REG_GEN64_START && pParam->param <= OP_PARM_REG_GEN64_END));
1567
1568 /* else - not supported for now registers. */
1569
1570 return 0;
1571}
1572//*****************************************************************************
1573//*****************************************************************************
1574unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1575{
1576 disasmGetPtrString(pCpu, pOp, pParam);
1577 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1578
1579 pParam->flags |= USE_POINTER_DS_BASED;
1580 if (pCpu->addrmode == CPUMODE_32BIT)
1581 {
1582 pParam->base.reg_gen = USE_REG_ESI;
1583 pParam->flags |= USE_REG_GEN32;
1584 }
1585 else
1586 if (pCpu->addrmode == CPUMODE_64BIT)
1587 {
1588 pParam->base.reg_gen = USE_REG_RSI;
1589 pParam->flags |= USE_REG_GEN64;
1590 }
1591 else
1592 {
1593 pParam->base.reg_gen = USE_REG_SI;
1594 pParam->flags |= USE_REG_GEN16;
1595 }
1596 return 0; //no additional opcode bytes
1597}
1598//*****************************************************************************
1599//*****************************************************************************
1600unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1601{
1602 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1603
1604 pParam->flags |= USE_POINTER_DS_BASED;
1605 if (pCpu->addrmode == CPUMODE_32BIT)
1606 {
1607 pParam->base.reg_gen = USE_REG_ESI;
1608 pParam->flags |= USE_REG_GEN32;
1609 }
1610 else
1611 if (pCpu->addrmode == CPUMODE_64BIT)
1612 {
1613 pParam->base.reg_gen = USE_REG_RSI;
1614 pParam->flags |= USE_REG_GEN64;
1615 }
1616 else
1617 {
1618 pParam->base.reg_gen = USE_REG_SI;
1619 pParam->flags |= USE_REG_GEN16;
1620 }
1621 return 0; //no additional opcode bytes
1622}
1623//*****************************************************************************
1624//*****************************************************************************
1625unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1626{
1627 disasmGetPtrString(pCpu, pOp, pParam);
1628 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1629
1630 pParam->flags |= USE_POINTER_ES_BASED;
1631 if (pCpu->addrmode == CPUMODE_32BIT)
1632 {
1633 pParam->base.reg_gen = USE_REG_EDI;
1634 pParam->flags |= USE_REG_GEN32;
1635 }
1636 else
1637 if (pCpu->addrmode == CPUMODE_64BIT)
1638 {
1639 pParam->base.reg_gen = USE_REG_RDI;
1640 pParam->flags |= USE_REG_GEN64;
1641 }
1642 else
1643 {
1644 pParam->base.reg_gen = USE_REG_DI;
1645 pParam->flags |= USE_REG_GEN16;
1646 }
1647 return 0; //no additional opcode bytes
1648}
1649//*****************************************************************************
1650//*****************************************************************************
1651unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1652{
1653 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1654
1655 pParam->flags |= USE_POINTER_ES_BASED;
1656 if (pCpu->addrmode == CPUMODE_32BIT)
1657 {
1658 pParam->base.reg_gen = USE_REG_EDI;
1659 pParam->flags |= USE_REG_GEN32;
1660 }
1661 else
1662 if (pCpu->addrmode == CPUMODE_64BIT)
1663 {
1664 pParam->base.reg_gen = USE_REG_RDI;
1665 pParam->flags |= USE_REG_GEN64;
1666 }
1667 else
1668 {
1669 pParam->base.reg_gen = USE_REG_DI;
1670 pParam->flags |= USE_REG_GEN16;
1671 }
1672 return 0; //no additional opcode bytes
1673}
1674//*****************************************************************************
1675//*****************************************************************************
1676unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1677{
1678 const OPCODE *pOpcode;
1679 int size = sizeof(uint8_t);
1680
1681 //2nd byte
1682 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1683 pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
1684
1685 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1686 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1687 if (pCpu->lastprefix)
1688 {
1689 switch (pCpu->lastprefix)
1690 {
1691 case OP_OPSIZE: /* 0x66 */
1692 if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
1693 {
1694 /* Table entry is valid, so use the extension table. */
1695 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
1696
1697 /* Cancel prefix changes. */
1698 pCpu->prefix &= ~PREFIX_OPSIZE;
1699 pCpu->opmode = pCpu->mode;
1700 }
1701 break;
1702
1703 case OP_REPNE: /* 0xF2 */
1704 if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
1705 {
1706 /* Table entry is valid, so use the extension table. */
1707 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
1708
1709 /* Cancel prefix changes. */
1710 pCpu->prefix &= ~PREFIX_REPNE;
1711 }
1712 break;
1713
1714 case OP_REPE: /* 0xF3 */
1715 if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
1716 {
1717 /* Table entry is valid, so use the extension table. */
1718 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
1719
1720 /* Cancel prefix changes. */
1721 pCpu->prefix &= ~PREFIX_REP;
1722 }
1723 break;
1724 }
1725 }
1726
1727 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1728 return size;
1729}
1730//*****************************************************************************
1731//*****************************************************************************
1732unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1733{
1734 unsigned size = 0;
1735
1736 if (pCpu->prefix & PREFIX_REP)
1737 {
1738 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1739 pCpu->prefix &= ~PREFIX_REP;
1740 }
1741 else
1742 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1743
1744 size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
1745 return size;
1746}
1747//*****************************************************************************
1748//*****************************************************************************
1749unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1750{
1751 int idx = (pCpu->opcode - 0x80) * 8;
1752 unsigned size = 0, modrm, reg;
1753
1754 modrm = DISReadByte(pCpu, lpszCodeBlock);
1755 reg = MODRM_REG(modrm);
1756
1757 pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
1758 //little hack to make sure the ModRM byte is included in the returned size
1759 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1760 size = sizeof(uint8_t); //ModRM byte
1761
1762 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1763
1764 return size;
1765}
1766//*****************************************************************************
1767//*****************************************************************************
1768unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1769{
1770 int idx;
1771 unsigned size = 0, modrm, reg;
1772
1773 switch (pCpu->opcode)
1774 {
1775 case 0xC0:
1776 case 0xC1:
1777 idx = (pCpu->opcode - 0xC0)*8;
1778 break;
1779
1780 case 0xD0:
1781 case 0xD1:
1782 case 0xD2:
1783 case 0xD3:
1784 idx = (pCpu->opcode - 0xD0 + 2)*8;
1785 break;
1786
1787 default:
1788 AssertMsgFailed(("Oops\n"));
1789 return sizeof(uint8_t);
1790 }
1791
1792 modrm = DISReadByte(pCpu, lpszCodeBlock);
1793 reg = MODRM_REG(modrm);
1794
1795 pOp = (PCOPCODE)&g_aMapX86_Group2[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 ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1808{
1809 int idx = (pCpu->opcode - 0xF6) * 8;
1810 unsigned size = 0, modrm, reg;
1811
1812 modrm = DISReadByte(pCpu, lpszCodeBlock);
1813 reg = MODRM_REG(modrm);
1814
1815 pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
1816
1817 //little hack to make sure the ModRM byte is included in the returned size
1818 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1819 size = sizeof(uint8_t); //ModRM byte
1820
1821 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1822
1823 return size;
1824}
1825//*****************************************************************************
1826//*****************************************************************************
1827unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1828{
1829 unsigned size = 0, modrm, reg;
1830
1831 modrm = DISReadByte(pCpu, lpszCodeBlock);
1832 reg = MODRM_REG(modrm);
1833
1834 pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
1835
1836 //little hack to make sure the ModRM byte is included in the returned size
1837 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1838 size = sizeof(uint8_t); //ModRM byte
1839
1840 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1841
1842 return size;
1843}
1844//*****************************************************************************
1845//*****************************************************************************
1846unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1847{
1848 unsigned size = 0, modrm, reg;
1849
1850 modrm = DISReadByte(pCpu, lpszCodeBlock);
1851 reg = MODRM_REG(modrm);
1852
1853 pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
1854
1855 //little hack to make sure the ModRM byte is included in the returned size
1856 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1857 size = sizeof(uint8_t); //ModRM byte
1858
1859 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1860
1861 return size;
1862}
1863//*****************************************************************************
1864// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
1865// It would appear the ModRM byte must always be present. How else can you
1866// determine the offset of the imm8_opcode byte otherwise?
1867//
1868//*****************************************************************************
1869unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1870{
1871 unsigned size = 0, modrmsize;
1872
1873#ifdef DEBUG_Sander
1874 //needs testing
1875 AssertMsgFailed(("Test me\n"));
1876#endif
1877
1878 unsigned ModRM = DISReadByte(pCpu, lpszCodeBlock);
1879 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1880 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1881 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1882
1883 modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
1884
1885 uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
1886
1887 pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
1888
1889 //little hack to make sure the ModRM byte is included in the returned size
1890 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1891 {
1892#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
1893 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
1894#endif
1895 size = sizeof(uint8_t); //ModRM byte
1896 }
1897
1898 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1899 size += sizeof(uint8_t); //imm8_opcode uint8_t
1900
1901 return size;
1902}
1903//*****************************************************************************
1904//*****************************************************************************
1905unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1906{
1907 unsigned size = 0, modrm, reg;
1908
1909 modrm = DISReadByte(pCpu, lpszCodeBlock);
1910 reg = MODRM_REG(modrm);
1911
1912 pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
1913
1914 //little hack to make sure the ModRM byte is included in the returned size
1915 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1916 size = sizeof(uint8_t); //ModRM byte
1917
1918 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1919
1920 return size;
1921}
1922//*****************************************************************************
1923//*****************************************************************************
1924unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1925{
1926 unsigned size = 0, modrm, reg, rm, mod;
1927
1928 modrm = DISReadByte(pCpu, lpszCodeBlock);
1929 mod = MODRM_MOD(modrm);
1930 reg = MODRM_REG(modrm);
1931 rm = MODRM_RM(modrm);
1932
1933 if (mod == 3 && rm == 0)
1934 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
1935 else
1936 if (mod == 3 && rm == 1)
1937 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
1938 else
1939 pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
1940
1941 //little hack to make sure the ModRM byte is included in the returned size
1942 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1943 size = sizeof(uint8_t); //ModRM byte
1944
1945 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1946
1947 return size;
1948}
1949//*****************************************************************************
1950//*****************************************************************************
1951unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1952{
1953 unsigned size = 0, modrm, reg;
1954
1955 modrm = DISReadByte(pCpu, lpszCodeBlock);
1956 reg = MODRM_REG(modrm);
1957
1958 pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
1959
1960 //little hack to make sure the ModRM byte is included in the returned size
1961 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1962 size = sizeof(uint8_t); //ModRM byte
1963
1964 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1965
1966 return size;
1967}
1968//*****************************************************************************
1969//*****************************************************************************
1970unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1971{
1972 unsigned size = 0, modrm, reg;
1973
1974 modrm = DISReadByte(pCpu, lpszCodeBlock);
1975 reg = MODRM_REG(modrm);
1976
1977 pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
1978
1979 //little hack to make sure the ModRM byte is included in the returned size
1980 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1981 size = sizeof(uint8_t); //ModRM byte
1982
1983 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1984
1985 return size;
1986}
1987//*****************************************************************************
1988//*****************************************************************************
1989unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1990{
1991 unsigned size = 0, modrm, reg;
1992
1993 modrm = DISReadByte(pCpu, lpszCodeBlock);
1994 reg = MODRM_REG(modrm);
1995
1996 pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
1997
1998 //little hack to make sure the ModRM byte is included in the returned size
1999 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2000 size = sizeof(uint8_t); //ModRM byte
2001
2002 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2003
2004 return size;
2005}
2006//*****************************************************************************
2007//*****************************************************************************
2008unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2009{
2010 unsigned size = 0, modrm, reg;
2011
2012 modrm = DISReadByte(pCpu, lpszCodeBlock);
2013 reg = MODRM_REG(modrm);
2014
2015 if (pCpu->prefix & PREFIX_OPSIZE)
2016 reg += 8; //2nd table
2017
2018 pOp = (PCOPCODE)&g_aMapX86_Group12[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 return size;
2026}
2027//*****************************************************************************
2028//*****************************************************************************
2029unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2030{
2031 unsigned size = 0, modrm, reg;
2032
2033 modrm = DISReadByte(pCpu, lpszCodeBlock);
2034 reg = MODRM_REG(modrm);
2035 if (pCpu->prefix & PREFIX_OPSIZE)
2036 reg += 8; //2nd table
2037
2038 pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
2039
2040 //little hack to make sure the ModRM byte is included in the returned size
2041 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2042 size = sizeof(uint8_t); //ModRM byte
2043
2044 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2045
2046 return size;
2047}
2048//*****************************************************************************
2049//*****************************************************************************
2050unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2051{
2052 unsigned size = 0, modrm, reg;
2053
2054 modrm = DISReadByte(pCpu, lpszCodeBlock);
2055 reg = MODRM_REG(modrm);
2056 if (pCpu->prefix & PREFIX_OPSIZE)
2057 reg += 8; //2nd table
2058
2059 pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
2060
2061 //little hack to make sure the ModRM byte is included in the returned size
2062 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2063 size = sizeof(uint8_t); //ModRM byte
2064
2065 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2066
2067 return size;
2068}
2069//*****************************************************************************
2070//*****************************************************************************
2071unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2072{
2073 unsigned size = 0, modrm, reg, mod, rm;
2074
2075 modrm = DISReadByte(pCpu, lpszCodeBlock);
2076 mod = MODRM_MOD(modrm);
2077 reg = MODRM_REG(modrm);
2078 rm = MODRM_RM(modrm);
2079
2080 if (mod == 3 && rm == 0)
2081 pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
2082 else
2083 pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
2084
2085 //little hack to make sure the ModRM byte is included in the returned size
2086 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2087 size = sizeof(uint8_t); //ModRM byte
2088
2089 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2090 return size;
2091}
2092//*****************************************************************************
2093//*****************************************************************************
2094unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2095{
2096 unsigned size = 0, modrm, reg;
2097
2098 modrm = DISReadByte(pCpu, lpszCodeBlock);
2099 reg = MODRM_REG(modrm);
2100
2101 pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
2102
2103 //little hack to make sure the ModRM byte is included in the returned size
2104 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2105 size = sizeof(uint8_t); //ModRM byte
2106
2107 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2108 return size;
2109}
2110//*****************************************************************************
2111#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2112static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
2113static const char *szModRMReg8_64[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8L", "R9L", "R10L", "R11L", "R12L", "R13L", "R14L", "R15L"};
2114static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
2115static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
2116static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
2117static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
2118#endif
2119static const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
2120static 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};
2121static const int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
2122//*****************************************************************************
2123void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam, int fRegAddr)
2124{
2125 int subtype, type, mod;
2126
2127 mod = pCpu->ModRM.Bits.Mod;
2128
2129 type = OP_PARM_VTYPE(pParam->param);
2130 subtype = OP_PARM_VSUBTYPE(pParam->param);
2131 if (fRegAddr)
2132 subtype = (pCpu->addrmode == CPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
2133 else
2134 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
2135 {
2136 switch(pCpu->opmode)
2137 {
2138 case CPUMODE_32BIT:
2139 subtype = OP_PARM_d;
2140 break;
2141 case CPUMODE_64BIT:
2142 subtype = OP_PARM_q;
2143 break;
2144 case CPUMODE_16BIT:
2145 subtype = OP_PARM_w;
2146 break;
2147 default:
2148 /* make gcc happy */
2149 break;
2150 }
2151 }
2152
2153 switch (subtype)
2154 {
2155 case OP_PARM_b:
2156#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2157 if (idx > (int)RT_ELEMENTS(szModRMReg8))
2158 disasmAddString(pParam->szParam, szModRMReg8_64[idx]);
2159 else
2160 disasmAddString(pParam->szParam, szModRMReg8[idx]);
2161#endif
2162 pParam->flags |= USE_REG_GEN8;
2163 pParam->base.reg_gen = idx;
2164 break;
2165
2166 case OP_PARM_w:
2167 disasmAddString(pParam->szParam, szModRMReg16[idx]);
2168 pParam->flags |= USE_REG_GEN16;
2169 pParam->base.reg_gen = idx;
2170 break;
2171
2172 case OP_PARM_d:
2173 disasmAddString(pParam->szParam, szModRMReg32[idx]);
2174 pParam->flags |= USE_REG_GEN32;
2175 pParam->base.reg_gen = idx;
2176 break;
2177
2178 case OP_PARM_q:
2179 disasmAddString(pParam->szParam, szModRMReg64[idx]);
2180 pParam->flags |= USE_REG_GEN64;
2181 pParam->base.reg_gen = idx;
2182 break;
2183
2184 default:
2185#ifdef IN_RING3
2186 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
2187 DIS_THROW(ExceptionInvalidModRM);
2188#else
2189 AssertMsgFailed(("Oops!\n"));
2190#endif
2191 break;
2192 }
2193}
2194//*****************************************************************************
2195//*****************************************************************************
2196void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
2197{
2198 disasmAddString(pParam->szParam, szModRMReg1616[idx]);
2199 pParam->flags |= USE_REG_GEN16;
2200 pParam->base.reg_gen = BaseModRMReg16[idx];
2201 if (idx < 4)
2202 {
2203 pParam->flags |= USE_INDEX;
2204 pParam->index.reg_gen = IndexModRMReg16[idx];
2205 }
2206}
2207//*****************************************************************************
2208//*****************************************************************************
2209void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
2210{
2211#if 0 //def DEBUG_Sander
2212 AssertMsg(idx < (int)ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
2213#endif
2214#ifdef IN_RING3
2215 if (idx >= (int)ELEMENTS(szModRMSegReg))
2216 {
2217 Log(("disasmModRMSReg %d failed!!\n", idx));
2218 DIS_THROW(ExceptionInvalidParameter);
2219 }
2220#endif
2221
2222 idx = RT_MIN(idx, (int)ELEMENTS(szModRMSegReg)-1);
2223 disasmAddString(pParam->szParam, szModRMSegReg[idx]);
2224 pParam->flags |= USE_REG_SEG;
2225 pParam->base.reg_seg = idx;
2226}
2227//*****************************************************************************
2228//*****************************************************************************
2229void disasmPrintAbs32(POP_PARAMETER pParam)
2230{
2231 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2232}
2233//*****************************************************************************
2234//*****************************************************************************
2235void disasmPrintDisp32(POP_PARAMETER pParam)
2236{
2237 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2238}
2239//*****************************************************************************
2240//*****************************************************************************
2241void disasmPrintDisp8(POP_PARAMETER pParam)
2242{
2243 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
2244}
2245//*****************************************************************************
2246//*****************************************************************************
2247void disasmPrintDisp16(POP_PARAMETER pParam)
2248{
2249 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
2250}
2251//*****************************************************************************
2252//*****************************************************************************
2253void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
2254{
2255 int subtype = OP_PARM_VSUBTYPE(pParam->param);
2256
2257 if (subtype == OP_PARM_v)
2258 {
2259 switch(pCpu->opmode)
2260 {
2261 case CPUMODE_32BIT:
2262 subtype = OP_PARM_d;
2263 break;
2264 case CPUMODE_64BIT:
2265 subtype = OP_PARM_q;
2266 break;
2267 case CPUMODE_16BIT:
2268 subtype = OP_PARM_w;
2269 break;
2270 default:
2271 /* make gcc happy */
2272 break;
2273 }
2274 }
2275
2276 switch (subtype)
2277 {
2278 case OP_PARM_a: //two words or dwords depending on operand size (bound only)
2279 break;
2280
2281 case OP_PARM_b:
2282 disasmAddString(pParam->szParam, "byte ptr ");
2283 break;
2284
2285 case OP_PARM_w:
2286 disasmAddString(pParam->szParam, "word ptr ");
2287 break;
2288
2289 case OP_PARM_d:
2290 disasmAddString(pParam->szParam, "dword ptr ");
2291 break;
2292
2293 case OP_PARM_q:
2294 case OP_PARM_dq:
2295 disasmAddString(pParam->szParam, "qword ptr ");
2296 break;
2297
2298 case OP_PARM_p:
2299 disasmAddString(pParam->szParam, "far ptr ");
2300 break;
2301
2302 case OP_PARM_s:
2303 break; //??
2304
2305 case OP_PARM_z:
2306 break;
2307 default:
2308 break; //no pointer type specified/necessary
2309 }
2310 if (pCpu->prefix & PREFIX_SEG)
2311 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->prefix_seg]);
2312}
2313#ifndef IN_GC
2314//*****************************************************************************
2315/* Read functions for getting the opcode bytes */
2316//*****************************************************************************
2317uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2318{
2319 if (pCpu->pfnReadBytes)
2320 {
2321 uint8_t temp = 0;
2322 int rc;
2323
2324 rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
2325 if (VBOX_FAILURE(rc))
2326 {
2327 Log(("DISReadByte failed!!\n"));
2328 DIS_THROW(ExceptionMemRead);
2329 }
2330 return temp;
2331 }
2332#ifdef IN_RING0
2333 AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
2334 return 0;
2335#else
2336 else return *(uint8_t *)pAddress;
2337#endif
2338}
2339//*****************************************************************************
2340//*****************************************************************************
2341uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2342{
2343 if (pCpu->pfnReadBytes)
2344 {
2345 uint16_t temp = 0;
2346 int rc;
2347
2348 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2349 if (VBOX_FAILURE(rc))
2350 {
2351 Log(("DISReadWord failed!!\n"));
2352 DIS_THROW(ExceptionMemRead);
2353 }
2354 return temp;
2355 }
2356#ifdef IN_RING0
2357 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
2358 return 0;
2359#else
2360 else return *(uint16_t *)pAddress;
2361#endif
2362}
2363//*****************************************************************************
2364//*****************************************************************************
2365uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2366{
2367 if (pCpu->pfnReadBytes)
2368 {
2369 uint32_t temp = 0;
2370 int rc;
2371
2372 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2373 if (VBOX_FAILURE(rc))
2374 {
2375 Log(("DISReadDWord failed!!\n"));
2376 DIS_THROW(ExceptionMemRead);
2377 }
2378 return temp;
2379 }
2380#ifdef IN_RING0
2381 AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
2382 return 0;
2383#else
2384 else return *(uint32_t *)pAddress;
2385#endif
2386}
2387//*****************************************************************************
2388//*****************************************************************************
2389uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2390{
2391 if (pCpu->pfnReadBytes)
2392 {
2393 uint64_t temp = 0;
2394 int rc;
2395
2396 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2397 if (VBOX_FAILURE(rc))
2398 {
2399 Log(("DISReadQWord %x failed!!\n", pAddress));
2400 DIS_THROW(ExceptionMemRead);
2401 }
2402
2403 return temp;
2404 }
2405#ifdef IN_RING0
2406 AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
2407 return 0;
2408#else
2409 else return *(uint64_t *)pAddress;
2410#endif
2411}
2412#endif /* IN_GC */
2413
2414#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2415//*****************************************************************************
2416//*****************************************************************************
2417void disasmAddString(char *psz, const char *pszAdd)
2418{
2419 strcat(psz, pszAdd);
2420}
2421//*****************************************************************************
2422//*****************************************************************************
2423void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
2424{
2425 va_list args;
2426 va_start(args, pszFormat);
2427 RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
2428 va_end(args);
2429}
2430
2431//*****************************************************************************
2432//*****************************************************************************
2433void disasmAddChar(char *psz, char ch)
2434{
2435 char sz[2];
2436
2437 sz[0] = ch;
2438 sz[1] = '\0';
2439 strcat(psz, sz);
2440}
2441#endif /* !DIS_CORE_ONLY */
2442
2443
2444/**
2445 * Validates the lock sequence.
2446 *
2447 * The AMD manual lists the following instructions:
2448 * ADC
2449 * ADD
2450 * AND
2451 * BTC
2452 * BTR
2453 * BTS
2454 * CMPXCHG
2455 * CMPXCHG8B
2456 * CMPXCHG16B
2457 * DEC
2458 * INC
2459 * NEG
2460 * NOT
2461 * OR
2462 * SBB
2463 * SUB
2464 * XADD
2465 * XCHG
2466 * XOR
2467 *
2468 * @param pCpu Fully dissassembled instruction.
2469 */
2470void disValidateLockSequence(PDISCPUSTATE pCpu)
2471{
2472 Assert(pCpu->prefix & PREFIX_LOCK);
2473
2474 /*
2475 * Filter out the valid lock sequences.
2476 */
2477 switch (pCpu->pCurInstr->opcode)
2478 {
2479 /* simple: no variations */
2480 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2481 return;
2482
2483 /* simple: /r - reject register destination. */
2484 case OP_BTC:
2485 case OP_BTR:
2486 case OP_BTS:
2487 case OP_CMPXCHG:
2488 case OP_XADD:
2489 if (pCpu->ModRM.Bits.Mod == 3)
2490 break;
2491 return;
2492
2493 /*
2494 * Lots of variants but its sufficient to check that param 1
2495 * is a memory operand.
2496 */
2497 case OP_ADC:
2498 case OP_ADD:
2499 case OP_AND:
2500 case OP_DEC:
2501 case OP_INC:
2502 case OP_NEG:
2503 case OP_NOT:
2504 case OP_OR:
2505 case OP_SBB:
2506 case OP_SUB:
2507 case OP_XCHG:
2508 case OP_XOR:
2509 if (pCpu->param1.flags & (USE_BASE | USE_INDEX | USE_DISPLACEMENT32 | USE_DISPLACEMENT16 | USE_DISPLACEMENT8 | USE_RIPDISPLACEMENT32))
2510 return;
2511 break;
2512
2513 default:
2514 break;
2515 }
2516
2517 /*
2518 * Invalid lock sequence, make it a OP_ILLUD2.
2519 */
2520 pCpu->pCurInstr = &g_aTwoByteMapX86[11];
2521 Assert(pCpu->pCurInstr->opcode == OP_ILLUD2);
2522}
2523
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