VirtualBox

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

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

include cpum.h

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