VirtualBox

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

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

Cleaned up disassembler

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