VirtualBox

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

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

More 64 bits disasm updates

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