VirtualBox

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

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

Disassembler fixes + testcase for 64 bits

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