VirtualBox

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

Last change on this file since 400 was 1, checked in by vboxsync, 55 years ago

import

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

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