VirtualBox

source: vbox/trunk/src/VBox/Disassembler/DisasmReg.cpp@ 10158

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

Corrected parameter types (const).
Use SELMToFlatEx instead of SELMValidateAndConvertCSAddr when disassembling instructions.
(the latter is too strict)

  • Property svn:sync_process set to export
File size: 28.3 KB
Line 
1/** @file
2 *
3 * VBox disassembler:
4 * Core components
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_DIS
28#ifdef USING_VISUAL_STUDIO
29# include <stdafx.h>
30#endif
31
32#include <VBox/dis.h>
33#include <VBox/disopcode.h>
34#include <VBox/cpum.h>
35#include <VBox/err.h>
36#include <VBox/log.h>
37#include <iprt/assert.h>
38#include <iprt/string.h>
39#include <iprt/stdarg.h>
40#include "DisasmInternal.h"
41#include "DisasmTables.h"
42
43#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
44# include <stdlib.h>
45# include <stdio.h>
46#endif
47
48
49/*******************************************************************************
50* Global Variables *
51*******************************************************************************/
52
53/**
54 * Array for accessing 64-bit general registers in VMMREGFRAME structure
55 * by register's index from disasm.
56 */
57static const unsigned g_aReg64Index[] =
58{
59 RT_OFFSETOF(CPUMCTXCORE, rax), /* USE_REG_RAX */
60 RT_OFFSETOF(CPUMCTXCORE, rcx), /* USE_REG_RCX */
61 RT_OFFSETOF(CPUMCTXCORE, rdx), /* USE_REG_RDX */
62 RT_OFFSETOF(CPUMCTXCORE, rbx), /* USE_REG_RBX */
63 RT_OFFSETOF(CPUMCTXCORE, rsp), /* USE_REG_RSP */
64 RT_OFFSETOF(CPUMCTXCORE, rbp), /* USE_REG_RBP */
65 RT_OFFSETOF(CPUMCTXCORE, rsi), /* USE_REG_RSI */
66 RT_OFFSETOF(CPUMCTXCORE, rdi), /* USE_REG_RDI */
67 RT_OFFSETOF(CPUMCTXCORE, r8), /* USE_REG_R8 */
68 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9 */
69 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10 */
70 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11 */
71 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12 */
72 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13 */
73 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14 */
74 RT_OFFSETOF(CPUMCTXCORE, r15) /* USE_REG_R15 */
75};
76
77/**
78 * Macro for accessing 64-bit general purpose registers in CPUMCTXCORE structure.
79 */
80#define DIS_READ_REG64(p, idx) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]))
81#define DIS_WRITE_REG64(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]) = val)
82#define DIS_PTR_REG64(p, idx) ( (uint64_t *)((char *)(p) + g_aReg64Index[idx]))
83
84/**
85 * Array for accessing 32-bit general registers in VMMREGFRAME structure
86 * by register's index from disasm.
87 */
88static const unsigned g_aReg32Index[] =
89{
90 RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_EAX */
91 RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_ECX */
92 RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_EDX */
93 RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_EBX */
94 RT_OFFSETOF(CPUMCTXCORE, esp), /* USE_REG_ESP */
95 RT_OFFSETOF(CPUMCTXCORE, ebp), /* USE_REG_EBP */
96 RT_OFFSETOF(CPUMCTXCORE, esi), /* USE_REG_ESI */
97 RT_OFFSETOF(CPUMCTXCORE, edi), /* USE_REG_EDI */
98 RT_OFFSETOF(CPUMCTXCORE, r8), /* USE_REG_R8D */
99 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9D */
100 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10D */
101 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11D */
102 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12D */
103 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13D */
104 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14D */
105 RT_OFFSETOF(CPUMCTXCORE, r15) /* USE_REG_R15D */
106};
107
108/**
109 * Macro for accessing 32-bit general purpose registers in CPUMCTXCORE structure.
110 */
111#define DIS_READ_REG32(p, idx) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]))
112/* From http://www.cs.cmu.edu/~fp/courses/15213-s06/misc/asm64-handout.pdf:
113 * ``Perhaps unexpectedly, instructions that move or generate 32-bit register
114 * values also set the upper 32 bits of the register to zero. Consequently
115 * there is no need for an instruction movzlq.''
116 */
117#define DIS_WRITE_REG32(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg32Index[idx]) = (uint32_t)val)
118#define DIS_PTR_REG32(p, idx) ( (uint32_t *)((char *)(p) + g_aReg32Index[idx]))
119
120/**
121 * Array for accessing 16-bit general registers in CPUMCTXCORE structure
122 * by register's index from disasm.
123 */
124static const unsigned g_aReg16Index[] =
125{
126 RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_AX */
127 RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_CX */
128 RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_DX */
129 RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_BX */
130 RT_OFFSETOF(CPUMCTXCORE, esp), /* USE_REG_SP */
131 RT_OFFSETOF(CPUMCTXCORE, ebp), /* USE_REG_BP */
132 RT_OFFSETOF(CPUMCTXCORE, esi), /* USE_REG_SI */
133 RT_OFFSETOF(CPUMCTXCORE, edi), /* USE_REG_DI */
134 RT_OFFSETOF(CPUMCTXCORE, r8), /* USE_REG_R8W */
135 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9W */
136 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10W */
137 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11W */
138 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12W */
139 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13W */
140 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14W */
141 RT_OFFSETOF(CPUMCTXCORE, r15) /* USE_REG_R15W */
142};
143
144/**
145 * Macro for accessing 16-bit general purpose registers in CPUMCTXCORE structure.
146 */
147#define DIS_READ_REG16(p, idx) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]))
148#define DIS_WRITE_REG16(p, idx, val) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]) = val)
149#define DIS_PTR_REG16(p, idx) ( (uint16_t *)((char *)(p) + g_aReg16Index[idx]))
150
151/**
152 * Array for accessing 8-bit general registers in CPUMCTXCORE structure
153 * by register's index from disasm.
154 */
155static const unsigned g_aReg8Index[] =
156{
157 RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_AL */
158 RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_CL */
159 RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_DL */
160 RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_BL */
161 RT_OFFSETOF(CPUMCTXCORE, eax) + 1, /* USE_REG_AH */
162 RT_OFFSETOF(CPUMCTXCORE, ecx) + 1, /* USE_REG_CH */
163 RT_OFFSETOF(CPUMCTXCORE, edx) + 1, /* USE_REG_DH */
164 RT_OFFSETOF(CPUMCTXCORE, ebx) + 1, /* USE_REG_BH */
165 RT_OFFSETOF(CPUMCTXCORE, r8), /* USE_REG_R8B */
166 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9B */
167 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10B*/
168 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11B */
169 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12B */
170 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13B */
171 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14B */
172 RT_OFFSETOF(CPUMCTXCORE, r15), /* USE_REG_R15B */
173 RT_OFFSETOF(CPUMCTXCORE, esp), /* USE_REG_SPL; with REX prefix only */
174 RT_OFFSETOF(CPUMCTXCORE, ebp), /* USE_REG_BPL; with REX prefix only */
175 RT_OFFSETOF(CPUMCTXCORE, esi), /* USE_REG_SIL; with REX prefix only */
176 RT_OFFSETOF(CPUMCTXCORE, edi) /* USE_REG_DIL; with REX prefix only */
177};
178
179/**
180 * Macro for accessing 8-bit general purpose registers in CPUMCTXCORE structure.
181 */
182#define DIS_READ_REG8(p, idx) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]))
183#define DIS_WRITE_REG8(p, idx, val) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]) = val)
184#define DIS_PTR_REG8(p, idx) ( (uint8_t *)((char *)(p) + g_aReg8Index[idx]))
185
186/**
187 * Array for accessing segment registers in CPUMCTXCORE structure
188 * by register's index from disasm.
189 */
190static const unsigned g_aRegSegIndex[] =
191{
192 RT_OFFSETOF(CPUMCTXCORE, es), /* DIS_SELREG_ES */
193 RT_OFFSETOF(CPUMCTXCORE, cs), /* DIS_SELREG_CS */
194 RT_OFFSETOF(CPUMCTXCORE, ss), /* DIS_SELREG_SS */
195 RT_OFFSETOF(CPUMCTXCORE, ds), /* DIS_SELREG_DS */
196 RT_OFFSETOF(CPUMCTXCORE, fs), /* DIS_SELREG_FS */
197 RT_OFFSETOF(CPUMCTXCORE, gs) /* DIS_SELREG_GS */
198};
199
200static const unsigned g_aRegHidSegIndex[] =
201{
202 RT_OFFSETOF(CPUMCTXCORE, esHid), /* DIS_SELREG_ES */
203 RT_OFFSETOF(CPUMCTXCORE, csHid), /* DIS_SELREG_CS */
204 RT_OFFSETOF(CPUMCTXCORE, ssHid), /* DIS_SELREG_SS */
205 RT_OFFSETOF(CPUMCTXCORE, dsHid), /* DIS_SELREG_DS */
206 RT_OFFSETOF(CPUMCTXCORE, fsHid), /* DIS_SELREG_FS */
207 RT_OFFSETOF(CPUMCTXCORE, gsHid) /* DIS_SELREG_GS */
208};
209
210/**
211 * Macro for accessing segment registers in CPUMCTXCORE structure.
212 */
213#define DIS_READ_REGSEG(p, idx) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])))
214#define DIS_WRITE_REGSEG(p, idx, val) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])) = val)
215
216//*****************************************************************************
217//*****************************************************************************
218DISDECL(int) DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam)
219{
220 int subtype = OP_PARM_VSUBTYPE(pParam->param);
221
222 if (subtype == OP_PARM_v)
223 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
224
225 switch(subtype)
226 {
227 case OP_PARM_b:
228 return 1;
229
230 case OP_PARM_w:
231 return 2;
232
233 case OP_PARM_d:
234 return 4;
235
236 case OP_PARM_q:
237 case OP_PARM_dq:
238 return 8;
239
240 case OP_PARM_p: /* far pointer */
241 if (pCpu->addrmode == CPUMODE_32BIT)
242 return 6; /* 16:32 */
243 else
244 if (pCpu->addrmode == CPUMODE_64BIT)
245 return 12; /* 16:64 */
246 else
247 return 4; /* 16:16 */
248
249 default:
250 if (pParam->size)
251 return pParam->size;
252 else //@todo dangerous!!!
253 return 4;
254 }
255}
256//*****************************************************************************
257//*****************************************************************************
258DISDECL(DIS_SELREG) DISDetectSegReg(PDISCPUSTATE pCpu, POP_PARAMETER pParam)
259{
260 if (pCpu->prefix & PREFIX_SEG)
261 {
262 /* Use specified SEG: prefix. */
263 return pCpu->enmPrefixSeg;
264 }
265 else
266 {
267 /* Guess segment register by parameter type. */
268 if (pParam->flags & (USE_REG_GEN32|USE_REG_GEN64|USE_REG_GEN16))
269 {
270 AssertCompile(USE_REG_ESP == USE_REG_RSP);
271 AssertCompile(USE_REG_EBP == USE_REG_RBP);
272 AssertCompile(USE_REG_ESP == USE_REG_SP);
273 AssertCompile(USE_REG_EBP == USE_REG_BP);
274 if (pParam->base.reg_gen == USE_REG_ESP || pParam->base.reg_gen == USE_REG_EBP)
275 return DIS_SELREG_SS;
276 }
277 /* Default is use DS: for data access. */
278 return DIS_SELREG_DS;
279 }
280}
281//*****************************************************************************
282//*****************************************************************************
283DISDECL(uint8_t) DISQuerySegPrefixByte(PDISCPUSTATE pCpu)
284{
285 Assert(pCpu->prefix & PREFIX_SEG);
286 switch(pCpu->enmPrefixSeg)
287 {
288 case DIS_SELREG_ES:
289 return 0x26;
290 case DIS_SELREG_CS:
291 return 0x2E;
292 case DIS_SELREG_SS:
293 return 0x36;
294 case DIS_SELREG_DS:
295 return 0x3E;
296 case DIS_SELREG_FS:
297 return 0x64;
298 case DIS_SELREG_GS:
299 return 0x65;
300 default:
301 AssertFailed();
302 return 0;
303 }
304}
305
306
307/**
308 * Returns the value of the specified 8 bits general purpose register
309 *
310 */
311DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal)
312{
313 AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
314
315 *pVal = DIS_READ_REG8(pCtx, reg8);
316 return VINF_SUCCESS;
317}
318
319/**
320 * Returns the value of the specified 16 bits general purpose register
321 *
322 */
323DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal)
324{
325 AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
326
327 *pVal = DIS_READ_REG16(pCtx, reg16);
328 return VINF_SUCCESS;
329}
330
331/**
332 * Returns the value of the specified 32 bits general purpose register
333 *
334 */
335DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal)
336{
337 AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
338
339 *pVal = DIS_READ_REG32(pCtx, reg32);
340 return VINF_SUCCESS;
341}
342
343/**
344 * Returns the value of the specified 64 bits general purpose register
345 *
346 */
347DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal)
348{
349 AssertReturn(reg64 < ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
350
351 *pVal = DIS_READ_REG64(pCtx, reg64);
352 return VINF_SUCCESS;
353}
354
355/**
356 * Returns the pointer to the specified 8 bits general purpose register
357 *
358 */
359DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg)
360{
361 AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
362
363 *ppReg = DIS_PTR_REG8(pCtx, reg8);
364 return VINF_SUCCESS;
365}
366
367/**
368 * Returns the pointer to the specified 16 bits general purpose register
369 *
370 */
371DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg)
372{
373 AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
374
375 *ppReg = DIS_PTR_REG16(pCtx, reg16);
376 return VINF_SUCCESS;
377}
378
379/**
380 * Returns the pointer to the specified 32 bits general purpose register
381 *
382 */
383DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg)
384{
385 AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
386
387 *ppReg = DIS_PTR_REG32(pCtx, reg32);
388 return VINF_SUCCESS;
389}
390
391/**
392 * Returns the pointer to the specified 64 bits general purpose register
393 *
394 */
395DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg)
396{
397 AssertReturn(reg64 < ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
398
399 *ppReg = DIS_PTR_REG64(pCtx, reg64);
400 return VINF_SUCCESS;
401}
402
403/**
404 * Returns the value of the specified segment register
405 *
406 */
407DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal)
408{
409 AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
410
411 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
412 *pVal = DIS_READ_REGSEG(pCtx, sel);
413 return VINF_SUCCESS;
414}
415
416/**
417 * Returns the value of the specified segment register including a pointer to the hidden register in the supplied cpu context
418 *
419 */
420DISDECL(int) DISFetchRegSegEx(PCCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal, CPUMSELREGHID **ppSelHidReg)
421{
422 AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
423
424 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
425 *pVal = DIS_READ_REGSEG(pCtx, sel);
426 *ppSelHidReg = (CPUMSELREGHID *)((char *)pCtx + g_aRegHidSegIndex[sel]);
427 return VINF_SUCCESS;
428}
429
430/**
431 * Updates the value of the specified 64 bits general purpose register
432 *
433 */
434DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64)
435{
436 AssertReturn(reg64 < ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
437
438 DIS_WRITE_REG64(pRegFrame, reg64, val64);
439 return VINF_SUCCESS;
440}
441
442/**
443 * Updates the value of the specified 32 bits general purpose register
444 *
445 */
446DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32)
447{
448 AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
449
450 DIS_WRITE_REG32(pRegFrame, reg32, val32);
451 return VINF_SUCCESS;
452}
453
454/**
455 * Updates the value of the specified 16 bits general purpose register
456 *
457 */
458DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg16, uint16_t val16)
459{
460 AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
461
462 DIS_WRITE_REG16(pRegFrame, reg16, val16);
463 return VINF_SUCCESS;
464}
465
466/**
467 * Updates the specified 8 bits general purpose register
468 *
469 */
470DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8)
471{
472 AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
473
474 DIS_WRITE_REG8(pRegFrame, reg8, val8);
475 return VINF_SUCCESS;
476}
477
478/**
479 * Updates the specified segment register
480 *
481 */
482DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL val)
483{
484 AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
485
486 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
487 DIS_WRITE_REGSEG(pCtx, sel, val);
488 return VINF_SUCCESS;
489}
490
491/**
492 * Returns the value of the parameter in pParam
493 *
494 * @returns VBox error code
495 * @param pCtx CPU context structure pointer
496 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
497 * set correctly.
498 * @param pParam Pointer to the parameter to parse
499 * @param pParamVal Pointer to parameter value (OUT)
500 * @param parmtype Parameter type
501 *
502 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
503 *
504 */
505DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype)
506{
507 memset(pParamVal, 0, sizeof(*pParamVal));
508
509 if (DIS_IS_EFFECTIVE_ADDR(pParam->flags))
510 {
511 // Effective address
512 pParamVal->type = PARMTYPE_ADDRESS;
513 pParamVal->size = pParam->size;
514
515 if (pParam->flags & USE_BASE)
516 {
517 if (pParam->flags & USE_REG_GEN8)
518 {
519 pParamVal->flags |= PARAM_VAL8;
520 if (VBOX_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
521 }
522 else
523 if (pParam->flags & USE_REG_GEN16)
524 {
525 pParamVal->flags |= PARAM_VAL16;
526 if (VBOX_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
527 }
528 else
529 if (pParam->flags & USE_REG_GEN32)
530 {
531 pParamVal->flags |= PARAM_VAL32;
532 if (VBOX_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
533 }
534 else
535 if (pParam->flags & USE_REG_GEN64)
536 {
537 pParamVal->flags |= PARAM_VAL64;
538 if (VBOX_FAILURE(DISFetchReg64(pCtx, pParam->base.reg_gen, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
539 }
540 else {
541 AssertFailed();
542 return VERR_INVALID_PARAMETER;
543 }
544 }
545 // Note that scale implies index (SIB byte)
546 if (pParam->flags & USE_INDEX)
547 {
548 uint32_t val32;
549
550 pParamVal->flags |= PARAM_VAL32;
551 if (VBOX_FAILURE(DISFetchReg32(pCtx, pParam->index.reg_gen, &val32))) return VERR_INVALID_PARAMETER;
552
553 if (pParam->flags & USE_SCALE)
554 val32 *= pParam->scale;
555
556 pParamVal->val.val32 += val32;
557 }
558
559 if (pParam->flags & USE_DISPLACEMENT8)
560 {
561 if (pCpu->mode == CPUMODE_32BIT)
562 pParamVal->val.val32 += (int32_t)pParam->disp8;
563 else
564 if (pCpu->mode == CPUMODE_64BIT)
565 pParamVal->val.val64 += (int64_t)pParam->disp8;
566 else
567 pParamVal->val.val16 += (int16_t)pParam->disp8;
568 }
569 else
570 if (pParam->flags & USE_DISPLACEMENT16)
571 {
572 if (pCpu->mode == CPUMODE_32BIT)
573 pParamVal->val.val32 += (int32_t)pParam->disp16;
574 else
575 if (pCpu->mode == CPUMODE_64BIT)
576 pParamVal->val.val64 += (int64_t)pParam->disp16;
577 else
578 pParamVal->val.val16 += pParam->disp16;
579 }
580 else
581 if (pParam->flags & USE_DISPLACEMENT32)
582 {
583 if (pCpu->mode == CPUMODE_32BIT)
584 pParamVal->val.val32 += pParam->disp32;
585 else
586 pParamVal->val.val64 += pParam->disp32;
587 }
588 else
589 if (pParam->flags & USE_DISPLACEMENT64)
590 {
591 Assert(pCpu->mode == CPUMODE_64BIT);
592 pParamVal->val.val64 += (int64_t)pParam->disp64;
593 }
594 else
595 if (pParam->flags & USE_RIPDISPLACEMENT32)
596 {
597 Assert(pCpu->mode == CPUMODE_64BIT);
598 pParamVal->val.val64 += pParam->disp32 + pCtx->rip;
599 }
600 return VINF_SUCCESS;
601 }
602
603 if (pParam->flags & (USE_REG_GEN8|USE_REG_GEN16|USE_REG_GEN32|USE_REG_GEN64|USE_REG_FP|USE_REG_MMX|USE_REG_XMM|USE_REG_CR|USE_REG_DBG|USE_REG_SEG|USE_REG_TEST))
604 {
605 if (parmtype == PARAM_DEST)
606 {
607 // Caller needs to interpret the register according to the instruction (source/target, special value etc)
608 pParamVal->type = PARMTYPE_REGISTER;
609 pParamVal->size = pParam->size;
610 return VINF_SUCCESS;
611 }
612 //else PARAM_SOURCE
613
614 pParamVal->type = PARMTYPE_IMMEDIATE;
615
616 if (pParam->flags & USE_REG_GEN8)
617 {
618 pParamVal->flags |= PARAM_VAL8;
619 pParamVal->size = sizeof(uint8_t);
620 if (VBOX_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
621 }
622 else
623 if (pParam->flags & USE_REG_GEN16)
624 {
625 pParamVal->flags |= PARAM_VAL16;
626 pParamVal->size = sizeof(uint16_t);
627 if (VBOX_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
628 }
629 else
630 if (pParam->flags & USE_REG_GEN32)
631 {
632 pParamVal->flags |= PARAM_VAL32;
633 pParamVal->size = sizeof(uint32_t);
634 if (VBOX_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
635 }
636 else
637 if (pParam->flags & USE_REG_GEN64)
638 {
639 pParamVal->flags |= PARAM_VAL64;
640 pParamVal->size = sizeof(uint64_t);
641 if (VBOX_FAILURE(DISFetchReg64(pCtx, pParam->base.reg_gen, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
642 }
643 else
644 {
645 // Caller needs to interpret the register according to the instruction (source/target, special value etc)
646 pParamVal->type = PARMTYPE_REGISTER;
647 }
648 Assert(!(pParam->flags & USE_IMMEDIATE));
649 return VINF_SUCCESS;
650 }
651
652 if (pParam->flags & USE_IMMEDIATE)
653 {
654 pParamVal->type = PARMTYPE_IMMEDIATE;
655 if (pParam->flags & (USE_IMMEDIATE8|USE_IMMEDIATE8_REL))
656 {
657 pParamVal->flags |= PARAM_VAL8;
658 if (pParam->size == 2)
659 {
660 pParamVal->size = sizeof(uint16_t);
661 pParamVal->val.val16 = (uint8_t)pParam->parval;
662 }
663 else
664 {
665 pParamVal->size = sizeof(uint8_t);
666 pParamVal->val.val8 = (uint8_t)pParam->parval;
667 }
668 }
669 else
670 if (pParam->flags & (USE_IMMEDIATE16|USE_IMMEDIATE16_REL|USE_IMMEDIATE_ADDR_0_16|USE_IMMEDIATE16_SX8))
671 {
672 pParamVal->flags |= PARAM_VAL16;
673 pParamVal->size = sizeof(uint16_t);
674 pParamVal->val.val16 = (uint16_t)pParam->parval;
675 AssertMsg(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE16_SX8)), ("pParamVal->size %d vs %d EIP=%VGv\n", pParamVal->size, pParam->size, pCtx->eip) );
676 }
677 else
678 if (pParam->flags & (USE_IMMEDIATE32|USE_IMMEDIATE32_REL|USE_IMMEDIATE_ADDR_0_32|USE_IMMEDIATE32_SX8))
679 {
680 pParamVal->flags |= PARAM_VAL32;
681 pParamVal->size = sizeof(uint32_t);
682 pParamVal->val.val32 = (uint32_t)pParam->parval;
683 Assert(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE32_SX8)) );
684 }
685 else
686 if (pParam->flags & (USE_IMMEDIATE64 | USE_IMMEDIATE64_REL))
687 {
688 pParamVal->flags |= PARAM_VAL64;
689 pParamVal->size = sizeof(uint64_t);
690 pParamVal->val.val64 = pParam->parval;
691 Assert(pParamVal->size == pParam->size);
692 }
693 else
694 if (pParam->flags & (USE_IMMEDIATE_ADDR_16_16))
695 {
696 pParamVal->flags |= PARAM_VALFARPTR16;
697 pParamVal->size = sizeof(uint16_t)*2;
698 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->parval >> 16);
699 pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->parval);
700 Assert(pParamVal->size == pParam->size);
701 }
702 else
703 if (pParam->flags & (USE_IMMEDIATE_ADDR_16_32))
704 {
705 pParamVal->flags |= PARAM_VALFARPTR32;
706 pParamVal->size = sizeof(uint16_t) + sizeof(uint32_t);
707 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->parval >> 32);
708 pParamVal->val.farptr.offset = (uint32_t)(pParam->parval & 0xFFFFFFFF);
709 Assert(pParam->size == 8);
710 }
711 }
712 return VINF_SUCCESS;
713}
714
715/**
716 * Returns the pointer to a register of the parameter in pParam. We need this
717 * pointer when an interpreted instruction updates a register as a side effect.
718 * In CMPXCHG we know that only [r/e]ax is updated, but with XADD this could
719 * be every register.
720 *
721 * @returns VBox error code
722 * @param pCtx CPU context structure pointer
723 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
724 * set correctly.
725 * @param pParam Pointer to the parameter to parse
726 * @param pReg Pointer to parameter value (OUT)
727 * @param cbsize Parameter size (OUT)
728 *
729 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
730 *
731 */
732DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, void **ppReg, size_t *pcbSize)
733{
734 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))
735 {
736 if (pParam->flags & USE_REG_GEN8)
737 {
738 uint8_t *pu8Reg;
739 if (VBOX_SUCCESS(DISPtrReg8(pCtx, pParam->base.reg_gen, &pu8Reg)))
740 {
741 *pcbSize = sizeof(uint8_t);
742 *ppReg = (void *)pu8Reg;
743 return VINF_SUCCESS;
744 }
745 }
746 else
747 if (pParam->flags & USE_REG_GEN16)
748 {
749 uint16_t *pu16Reg;
750 if (VBOX_SUCCESS(DISPtrReg16(pCtx, pParam->base.reg_gen, &pu16Reg)))
751 {
752 *pcbSize = sizeof(uint16_t);
753 *ppReg = (void *)pu16Reg;
754 return VINF_SUCCESS;
755 }
756 }
757 else
758 if (pParam->flags & USE_REG_GEN32)
759 {
760 uint32_t *pu32Reg;
761 if (VBOX_SUCCESS(DISPtrReg32(pCtx, pParam->base.reg_gen, &pu32Reg)))
762 {
763 *pcbSize = sizeof(uint32_t);
764 *ppReg = (void *)pu32Reg;
765 return VINF_SUCCESS;
766 }
767 }
768 else
769 if (pParam->flags & USE_REG_GEN64)
770 {
771 uint64_t *pu64Reg;
772 if (VBOX_SUCCESS(DISPtrReg64(pCtx, pParam->base.reg_gen, &pu64Reg)))
773 {
774 *pcbSize = sizeof(uint64_t);
775 *ppReg = (void *)pu64Reg;
776 return VINF_SUCCESS;
777 }
778 }
779 }
780 return VERR_INVALID_PARAMETER;
781}
782//*****************************************************************************
783//*****************************************************************************
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