VirtualBox

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

Last change on this file since 2935 was 2333, checked in by vboxsync, 18 years ago

gcc-4.2 warnings

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