VirtualBox

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

Last change on this file since 41715 was 41692, checked in by vboxsync, 13 years ago

DIS: Reducing the DISCPUMODE even more (200 bytes now) and making it have the same layout in all contexts. This is useful since it's used several places in the VM structure. Also a bunch of other cleanups.

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