VirtualBox

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

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

Byte, word and dword access to r8-r15.

  • Property svn:sync_process set to export
File size: 28.0 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_R8 : dword access */
99 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9 : dword access */
100 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10 : dword access */
101 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11 : dword access */
102 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12 : dword access */
103 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13 : dword access */
104 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14 : dword access */
105 RT_OFFSETOF(CPUMCTXCORE, r15) /* USE_REG_R15 : dword access */
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#define DIS_WRITE_REG32(p, idx, val) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]) = val)
113#define DIS_PTR_REG32(p, idx) ( (uint32_t *)((char *)(p) + g_aReg32Index[idx]))
114
115/**
116 * Array for accessing 16-bit general registers in CPUMCTXCORE structure
117 * by register's index from disasm.
118 */
119static const unsigned g_aReg16Index[] =
120{
121 RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_AX */
122 RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_CX */
123 RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_DX */
124 RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_BX */
125 RT_OFFSETOF(CPUMCTXCORE, esp), /* USE_REG_SP */
126 RT_OFFSETOF(CPUMCTXCORE, ebp), /* USE_REG_BP */
127 RT_OFFSETOF(CPUMCTXCORE, esi), /* USE_REG_SI */
128 RT_OFFSETOF(CPUMCTXCORE, edi), /* USE_REG_DI */
129 RT_OFFSETOF(CPUMCTXCORE, r8), /* USE_REG_R8 : word access */
130 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9 : word access */
131 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10 : word access */
132 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11 : word access */
133 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12 : word access */
134 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13 : word access */
135 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14 : word access */
136 RT_OFFSETOF(CPUMCTXCORE, r15) /* USE_REG_R15 : word access */
137};
138
139/**
140 * Macro for accessing 16-bit general purpose registers in CPUMCTXCORE structure.
141 */
142#define DIS_READ_REG16(p, idx) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]))
143#define DIS_WRITE_REG16(p, idx, val) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]) = val)
144#define DIS_PTR_REG16(p, idx) ( (uint16_t *)((char *)(p) + g_aReg16Index[idx]))
145
146/**
147 * Array for accessing 8-bit general registers in CPUMCTXCORE structure
148 * by register's index from disasm.
149 */
150static const unsigned g_aReg8Index[] =
151{
152 RT_OFFSETOF(CPUMCTXCORE, eax), /* USE_REG_AL */
153 RT_OFFSETOF(CPUMCTXCORE, ecx), /* USE_REG_CL */
154 RT_OFFSETOF(CPUMCTXCORE, edx), /* USE_REG_DL */
155 RT_OFFSETOF(CPUMCTXCORE, ebx), /* USE_REG_BL */
156 RT_OFFSETOF(CPUMCTXCORE, eax) + 1, /* USE_REG_AH */
157 RT_OFFSETOF(CPUMCTXCORE, ecx) + 1, /* USE_REG_CH */
158 RT_OFFSETOF(CPUMCTXCORE, edx) + 1, /* USE_REG_DH */
159 RT_OFFSETOF(CPUMCTXCORE, ebx) + 1, /* USE_REG_BH */
160 RT_OFFSETOF(CPUMCTXCORE, r8), /* USE_REG_R8 : byte access */
161 RT_OFFSETOF(CPUMCTXCORE, r9), /* USE_REG_R9 : byte access */
162 RT_OFFSETOF(CPUMCTXCORE, r10), /* USE_REG_R10 : byte access */
163 RT_OFFSETOF(CPUMCTXCORE, r11), /* USE_REG_R11 : byte access */
164 RT_OFFSETOF(CPUMCTXCORE, r12), /* USE_REG_R12 : byte access */
165 RT_OFFSETOF(CPUMCTXCORE, r13), /* USE_REG_R13 : byte access */
166 RT_OFFSETOF(CPUMCTXCORE, r14), /* USE_REG_R14 : byte access */
167 RT_OFFSETOF(CPUMCTXCORE, r15) /* USE_REG_R15 : byte access */
168};
169
170/**
171 * Macro for accessing 8-bit general purpose registers in CPUMCTXCORE structure.
172 */
173#define DIS_READ_REG8(p, idx) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]))
174#define DIS_WRITE_REG8(p, idx, val) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]) = val)
175#define DIS_PTR_REG8(p, idx) ( (uint8_t *)((char *)(p) + g_aReg8Index[idx]))
176
177/**
178 * Array for accessing segment registers in CPUMCTXCORE structure
179 * by register's index from disasm.
180 */
181static const unsigned g_aRegSegIndex[] =
182{
183 RT_OFFSETOF(CPUMCTXCORE, es), /* DIS_SELREG_ES */
184 RT_OFFSETOF(CPUMCTXCORE, cs), /* DIS_SELREG_CS */
185 RT_OFFSETOF(CPUMCTXCORE, ss), /* DIS_SELREG_SS */
186 RT_OFFSETOF(CPUMCTXCORE, ds), /* DIS_SELREG_DS */
187 RT_OFFSETOF(CPUMCTXCORE, fs), /* DIS_SELREG_FS */
188 RT_OFFSETOF(CPUMCTXCORE, gs) /* DIS_SELREG_GS */
189};
190
191static const unsigned g_aRegHidSegIndex[] =
192{
193 RT_OFFSETOF(CPUMCTXCORE, esHid), /* DIS_SELREG_ES */
194 RT_OFFSETOF(CPUMCTXCORE, csHid), /* DIS_SELREG_CS */
195 RT_OFFSETOF(CPUMCTXCORE, ssHid), /* DIS_SELREG_SS */
196 RT_OFFSETOF(CPUMCTXCORE, dsHid), /* DIS_SELREG_DS */
197 RT_OFFSETOF(CPUMCTXCORE, fsHid), /* DIS_SELREG_FS */
198 RT_OFFSETOF(CPUMCTXCORE, gsHid) /* DIS_SELREG_GS */
199};
200
201/**
202 * Macro for accessing segment registers in CPUMCTXCORE structure.
203 */
204#define DIS_READ_REGSEG(p, idx) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])))
205#define DIS_WRITE_REGSEG(p, idx, val) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])) = val)
206
207//*****************************************************************************
208//*****************************************************************************
209DISDECL(int) DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam)
210{
211 int subtype = OP_PARM_VSUBTYPE(pParam->param);
212
213 if (subtype == OP_PARM_v)
214 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
215
216 switch(subtype)
217 {
218 case OP_PARM_b:
219 return 1;
220
221 case OP_PARM_w:
222 return 2;
223
224 case OP_PARM_d:
225 return 4;
226
227 case OP_PARM_q:
228 case OP_PARM_dq:
229 return 8;
230
231 case OP_PARM_p: /* far pointer */
232 if (pCpu->addrmode == CPUMODE_32BIT)
233 return 6; /* 16:32 */
234 else
235 if (pCpu->addrmode == CPUMODE_64BIT)
236 return 12; /* 16:64 */
237 else
238 return 4; /* 16:16 */
239
240 default:
241 if (pParam->size)
242 return pParam->size;
243 else //@todo dangerous!!!
244 return 4;
245 }
246}
247//*****************************************************************************
248//*****************************************************************************
249DISDECL(DIS_SELREG) DISDetectSegReg(PDISCPUSTATE pCpu, POP_PARAMETER pParam)
250{
251 if (pCpu->prefix & PREFIX_SEG)
252 {
253 /* Use specified SEG: prefix. */
254 return pCpu->enmPrefixSeg;
255 }
256 else
257 {
258 /* Guess segment register by parameter type. */
259 if (pParam->flags & (USE_REG_GEN32|USE_REG_GEN64|USE_REG_GEN16))
260 {
261 AssertCompile(USE_REG_ESP == USE_REG_RSP);
262 AssertCompile(USE_REG_EBP == USE_REG_RBP);
263 AssertCompile(USE_REG_ESP == USE_REG_SP);
264 AssertCompile(USE_REG_EBP == USE_REG_BP);
265 if (pParam->base.reg_gen == USE_REG_ESP || pParam->base.reg_gen == USE_REG_EBP)
266 return DIS_SELREG_SS;
267 }
268 /* Default is use DS: for data access. */
269 return DIS_SELREG_DS;
270 }
271}
272//*****************************************************************************
273//*****************************************************************************
274DISDECL(uint8_t) DISQuerySegPrefixByte(PDISCPUSTATE pCpu)
275{
276 Assert(pCpu->prefix & PREFIX_SEG);
277 switch(pCpu->enmPrefixSeg)
278 {
279 case DIS_SELREG_ES:
280 return 0x26;
281 case DIS_SELREG_CS:
282 return 0x2E;
283 case DIS_SELREG_SS:
284 return 0x36;
285 case DIS_SELREG_DS:
286 return 0x3E;
287 case DIS_SELREG_FS:
288 return 0x64;
289 case DIS_SELREG_GS:
290 return 0x65;
291 default:
292 AssertFailed();
293 return 0;
294 }
295}
296
297
298/**
299 * Returns the value of the specified 8 bits general purpose register
300 *
301 */
302DISDECL(int) DISFetchReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal)
303{
304 AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
305
306 *pVal = DIS_READ_REG8(pCtx, reg8);
307 return VINF_SUCCESS;
308}
309
310/**
311 * Returns the value of the specified 16 bits general purpose register
312 *
313 */
314DISDECL(int) DISFetchReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal)
315{
316 AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
317
318 *pVal = DIS_READ_REG16(pCtx, reg16);
319 return VINF_SUCCESS;
320}
321
322/**
323 * Returns the value of the specified 32 bits general purpose register
324 *
325 */
326DISDECL(int) DISFetchReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal)
327{
328 AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
329
330 *pVal = DIS_READ_REG32(pCtx, reg32);
331 return VINF_SUCCESS;
332}
333
334/**
335 * Returns the value of the specified 64 bits general purpose register
336 *
337 */
338DISDECL(int) DISFetchReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal)
339{
340 AssertReturn(reg64 < ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
341
342 *pVal = DIS_READ_REG64(pCtx, reg64);
343 return VINF_SUCCESS;
344}
345
346/**
347 * Returns the pointer to the specified 8 bits general purpose register
348 *
349 */
350DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg)
351{
352 AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
353
354 *ppReg = DIS_PTR_REG8(pCtx, reg8);
355 return VINF_SUCCESS;
356}
357
358/**
359 * Returns the pointer to the specified 16 bits general purpose register
360 *
361 */
362DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg)
363{
364 AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
365
366 *ppReg = DIS_PTR_REG16(pCtx, reg16);
367 return VINF_SUCCESS;
368}
369
370/**
371 * Returns the pointer to the specified 32 bits general purpose register
372 *
373 */
374DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg)
375{
376 AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
377
378 *ppReg = DIS_PTR_REG32(pCtx, reg32);
379 return VINF_SUCCESS;
380}
381
382/**
383 * Returns the pointer to the specified 64 bits general purpose register
384 *
385 */
386DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg)
387{
388 AssertReturn(reg64 < ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
389
390 *ppReg = DIS_PTR_REG64(pCtx, reg64);
391 return VINF_SUCCESS;
392}
393
394/**
395 * Returns the value of the specified segment register
396 *
397 */
398DISDECL(int) DISFetchRegSeg(PCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal)
399{
400 AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
401
402 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
403 *pVal = DIS_READ_REGSEG(pCtx, sel);
404 return VINF_SUCCESS;
405}
406
407/**
408 * Returns the value of the specified segment register including a pointer to the hidden register in the supplied cpu context
409 *
410 */
411DISDECL(int) DISFetchRegSegEx(PCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL *pVal, CPUMSELREGHID **ppSelHidReg)
412{
413 AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
414
415 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
416 *pVal = DIS_READ_REGSEG(pCtx, sel);
417 *ppSelHidReg = (CPUMSELREGHID *)((char *)pCtx + g_aRegHidSegIndex[sel]);
418 return VINF_SUCCESS;
419}
420
421/**
422 * Updates the value of the specified 64 bits general purpose register
423 *
424 */
425DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64)
426{
427 AssertReturn(reg64 < ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER);
428
429 DIS_WRITE_REG64(pRegFrame, reg64, val64);
430 return VINF_SUCCESS;
431}
432
433/**
434 * Updates the value of the specified 32 bits general purpose register
435 *
436 */
437DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32)
438{
439 AssertReturn(reg32 < ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER);
440
441 DIS_WRITE_REG32(pRegFrame, reg32, val32);
442 return VINF_SUCCESS;
443}
444
445/**
446 * Updates the value of the specified 16 bits general purpose register
447 *
448 */
449DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg16, uint16_t val16)
450{
451 AssertReturn(reg16 < ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER);
452
453 DIS_WRITE_REG16(pRegFrame, reg16, val16);
454 return VINF_SUCCESS;
455}
456
457/**
458 * Updates the specified 8 bits general purpose register
459 *
460 */
461DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8)
462{
463 AssertReturn(reg8 < ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER);
464
465 DIS_WRITE_REG8(pRegFrame, reg8, val8);
466 return VINF_SUCCESS;
467}
468
469/**
470 * Updates the specified segment register
471 *
472 */
473DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DIS_SELREG sel, RTSEL val)
474{
475 AssertReturn(sel < ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER);
476
477 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL));
478 DIS_WRITE_REGSEG(pCtx, sel, val);
479 return VINF_SUCCESS;
480}
481
482/**
483 * Returns the value of the parameter in pParam
484 *
485 * @returns VBox error code
486 * @param pCtx CPU context structure pointer
487 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
488 * set correctly.
489 * @param pParam Pointer to the parameter to parse
490 * @param pParamVal Pointer to parameter value (OUT)
491 * @param parmtype Parameter type
492 *
493 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
494 *
495 */
496DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype)
497{
498 memset(pParamVal, 0, sizeof(*pParamVal));
499
500 if (DIS_IS_EFFECTIVE_ADDR(pParam->flags))
501 {
502 // Effective address
503 pParamVal->type = PARMTYPE_ADDRESS;
504 pParamVal->size = pParam->size;
505
506 if (pParam->flags & USE_BASE)
507 {
508 if (pParam->flags & USE_REG_GEN8)
509 {
510 pParamVal->flags |= PARAM_VAL8;
511 if (VBOX_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
512 }
513 else
514 if (pParam->flags & USE_REG_GEN16)
515 {
516 pParamVal->flags |= PARAM_VAL16;
517 if (VBOX_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
518 }
519 else
520 if (pParam->flags & USE_REG_GEN32)
521 {
522 pParamVal->flags |= PARAM_VAL32;
523 if (VBOX_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
524 }
525 else
526 if (pParam->flags & USE_REG_GEN64)
527 {
528 pParamVal->flags |= PARAM_VAL64;
529 if (VBOX_FAILURE(DISFetchReg64(pCtx, pParam->base.reg_gen, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
530 }
531 else {
532 AssertFailed();
533 return VERR_INVALID_PARAMETER;
534 }
535 }
536 // Note that scale implies index (SIB byte)
537 if (pParam->flags & USE_INDEX)
538 {
539 uint32_t val32;
540
541 pParamVal->flags |= PARAM_VAL32;
542 if (VBOX_FAILURE(DISFetchReg32(pCtx, pParam->index.reg_gen, &val32))) return VERR_INVALID_PARAMETER;
543
544 if (pParam->flags & USE_SCALE)
545 val32 *= pParam->scale;
546
547 pParamVal->val.val32 += val32;
548 }
549
550 if (pParam->flags & USE_DISPLACEMENT8)
551 {
552 if (pCpu->mode == CPUMODE_32BIT)
553 pParamVal->val.val32 += (int32_t)pParam->disp8;
554 else
555 if (pCpu->mode == CPUMODE_64BIT)
556 pParamVal->val.val64 += (int64_t)pParam->disp8;
557 else
558 pParamVal->val.val16 += (int16_t)pParam->disp8;
559 }
560 else
561 if (pParam->flags & USE_DISPLACEMENT16)
562 {
563 if (pCpu->mode == CPUMODE_32BIT)
564 pParamVal->val.val32 += (int32_t)pParam->disp16;
565 else
566 if (pCpu->mode == CPUMODE_64BIT)
567 pParamVal->val.val64 += (int64_t)pParam->disp16;
568 else
569 pParamVal->val.val16 += pParam->disp16;
570 }
571 else
572 if (pParam->flags & USE_DISPLACEMENT32)
573 {
574 if (pCpu->mode == CPUMODE_32BIT)
575 pParamVal->val.val32 += pParam->disp32;
576 else
577 pParamVal->val.val64 += pParam->disp32;
578 }
579 else
580 if (pParam->flags & USE_DISPLACEMENT64)
581 {
582 Assert(pCpu->mode == CPUMODE_64BIT);
583 pParamVal->val.val64 += (int64_t)pParam->disp64;
584 }
585 else
586 if (pParam->flags & USE_RIPDISPLACEMENT32)
587 {
588 Assert(pCpu->mode == CPUMODE_64BIT);
589 pParamVal->val.val64 += pParam->disp32 + pCtx->rip;
590 }
591 return VINF_SUCCESS;
592 }
593
594 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))
595 {
596 if (parmtype == PARAM_DEST)
597 {
598 // Caller needs to interpret the register according to the instruction (source/target, special value etc)
599 pParamVal->type = PARMTYPE_REGISTER;
600 pParamVal->size = pParam->size;
601 return VINF_SUCCESS;
602 }
603 //else PARAM_SOURCE
604
605 pParamVal->type = PARMTYPE_IMMEDIATE;
606
607 if (pParam->flags & USE_REG_GEN8)
608 {
609 pParamVal->flags |= PARAM_VAL8;
610 pParamVal->size = sizeof(uint8_t);
611 if (VBOX_FAILURE(DISFetchReg8(pCtx, pParam->base.reg_gen, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER;
612 }
613 else
614 if (pParam->flags & USE_REG_GEN16)
615 {
616 pParamVal->flags |= PARAM_VAL16;
617 pParamVal->size = sizeof(uint16_t);
618 if (VBOX_FAILURE(DISFetchReg16(pCtx, pParam->base.reg_gen, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER;
619 }
620 else
621 if (pParam->flags & USE_REG_GEN32)
622 {
623 pParamVal->flags |= PARAM_VAL32;
624 pParamVal->size = sizeof(uint32_t);
625 if (VBOX_FAILURE(DISFetchReg32(pCtx, pParam->base.reg_gen, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER;
626 }
627 else
628 if (pParam->flags & USE_REG_GEN64)
629 {
630 pParamVal->flags |= PARAM_VAL64;
631 pParamVal->size = sizeof(uint64_t);
632 if (VBOX_FAILURE(DISFetchReg64(pCtx, pParam->base.reg_gen, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER;
633 }
634 else
635 {
636 // Caller needs to interpret the register according to the instruction (source/target, special value etc)
637 pParamVal->type = PARMTYPE_REGISTER;
638 }
639 Assert(!(pParam->flags & USE_IMMEDIATE));
640 return VINF_SUCCESS;
641 }
642
643 if (pParam->flags & USE_IMMEDIATE)
644 {
645 pParamVal->type = PARMTYPE_IMMEDIATE;
646 if (pParam->flags & (USE_IMMEDIATE8|USE_IMMEDIATE8_REL))
647 {
648 pParamVal->flags |= PARAM_VAL8;
649 if (pParam->size == 2)
650 {
651 pParamVal->size = sizeof(uint16_t);
652 pParamVal->val.val16 = (uint8_t)pParam->parval;
653 }
654 else
655 {
656 pParamVal->size = sizeof(uint8_t);
657 pParamVal->val.val8 = (uint8_t)pParam->parval;
658 }
659 }
660 else
661 if (pParam->flags & (USE_IMMEDIATE16|USE_IMMEDIATE16_REL|USE_IMMEDIATE_ADDR_0_16|USE_IMMEDIATE16_SX8))
662 {
663 pParamVal->flags |= PARAM_VAL16;
664 pParamVal->size = sizeof(uint16_t);
665 pParamVal->val.val16 = (uint16_t)pParam->parval;
666 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) );
667 }
668 else
669 if (pParam->flags & (USE_IMMEDIATE32|USE_IMMEDIATE32_REL|USE_IMMEDIATE_ADDR_0_32|USE_IMMEDIATE32_SX8))
670 {
671 pParamVal->flags |= PARAM_VAL32;
672 pParamVal->size = sizeof(uint32_t);
673 pParamVal->val.val32 = (uint32_t)pParam->parval;
674 Assert(pParamVal->size == pParam->size || ((pParam->size == 1) && (pParam->flags & USE_IMMEDIATE32_SX8)) );
675 }
676 else
677 if (pParam->flags & (USE_IMMEDIATE64 | USE_IMMEDIATE64_REL))
678 {
679 pParamVal->flags |= PARAM_VAL64;
680 pParamVal->size = sizeof(uint64_t);
681 pParamVal->val.val64 = pParam->parval;
682 Assert(pParamVal->size == pParam->size);
683 }
684 else
685 if (pParam->flags & (USE_IMMEDIATE_ADDR_16_16))
686 {
687 pParamVal->flags |= PARAM_VALFARPTR16;
688 pParamVal->size = sizeof(uint16_t)*2;
689 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->parval >> 16);
690 pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->parval);
691 Assert(pParamVal->size == pParam->size);
692 }
693 else
694 if (pParam->flags & (USE_IMMEDIATE_ADDR_16_32))
695 {
696 pParamVal->flags |= PARAM_VALFARPTR32;
697 pParamVal->size = sizeof(uint16_t) + sizeof(uint32_t);
698 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->parval >> 32);
699 pParamVal->val.farptr.offset = (uint32_t)(pParam->parval & 0xFFFFFFFF);
700 Assert(pParam->size == 8);
701 }
702 }
703 return VINF_SUCCESS;
704}
705
706/**
707 * Returns the pointer to a register of the parameter in pParam. We need this
708 * pointer when an interpreted instruction updates a register as a side effect.
709 * In CMPXCHG we know that only [r/e]ax is updated, but with XADD this could
710 * be every register.
711 *
712 * @returns VBox error code
713 * @param pCtx CPU context structure pointer
714 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode
715 * set correctly.
716 * @param pParam Pointer to the parameter to parse
717 * @param pReg Pointer to parameter value (OUT)
718 * @param cbsize Parameter size (OUT)
719 *
720 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!
721 *
722 */
723DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, void **ppReg, size_t *pcbSize)
724{
725 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))
726 {
727 if (pParam->flags & USE_REG_GEN8)
728 {
729 uint8_t *pu8Reg;
730 if (VBOX_SUCCESS(DISPtrReg8(pCtx, pParam->base.reg_gen, &pu8Reg)))
731 {
732 *pcbSize = sizeof(uint8_t);
733 *ppReg = (void *)pu8Reg;
734 return VINF_SUCCESS;
735 }
736 }
737 else
738 if (pParam->flags & USE_REG_GEN16)
739 {
740 uint16_t *pu16Reg;
741 if (VBOX_SUCCESS(DISPtrReg16(pCtx, pParam->base.reg_gen, &pu16Reg)))
742 {
743 *pcbSize = sizeof(uint16_t);
744 *ppReg = (void *)pu16Reg;
745 return VINF_SUCCESS;
746 }
747 }
748 else
749 if (pParam->flags & USE_REG_GEN32)
750 {
751 uint32_t *pu32Reg;
752 if (VBOX_SUCCESS(DISPtrReg32(pCtx, pParam->base.reg_gen, &pu32Reg)))
753 {
754 *pcbSize = sizeof(uint32_t);
755 *ppReg = (void *)pu32Reg;
756 return VINF_SUCCESS;
757 }
758 }
759 else
760 if (pParam->flags & USE_REG_GEN64)
761 {
762 uint64_t *pu64Reg;
763 if (VBOX_SUCCESS(DISPtrReg64(pCtx, pParam->base.reg_gen, &pu64Reg)))
764 {
765 *pcbSize = sizeof(uint64_t);
766 *ppReg = (void *)pu64Reg;
767 return VINF_SUCCESS;
768 }
769 }
770 }
771 return VERR_INVALID_PARAMETER;
772}
773//*****************************************************************************
774//*****************************************************************************
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette