VirtualBox

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

Last change on this file since 1639 was 1464, checked in by vboxsync, 18 years ago

Added DISQuerySegPrefixByte

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