VirtualBox

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

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

Disassemble vmread/vmwrite

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