VirtualBox

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

Last change on this file since 1296 was 1155, checked in by vboxsync, 18 years ago

Use RTStrPrintfV (%04X still broken though)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 85.0 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 * 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, sizeof(szTemp), "%s%s", szSIBIndexReg[index], szSIBScale[scale]);
993 else
994 disasmAddStringF(szTemp, sizeof(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, sizeof(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, sizeof(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, sizeof(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, sizeof(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, sizeof(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, sizeof(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, sizeof(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 disasmAddChar(pParam->szParam, '+');
1246 disasmPrintDisp16(pParam);
1247 }
1248 disasmAddChar(pParam->szParam, ']');
1249 break;
1250
1251 case 3: //registers
1252 disasmModRMReg(pCpu, pOp, rm, pParam, 0);
1253 break;
1254 }
1255 }
1256 return 0; //everything was already fetched in ParseModRM
1257}
1258//*****************************************************************************
1259// Query the size of the ModRM parameters and fetch the immediate data (if any)
1260//*****************************************************************************
1261int QueryModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, int *pSibInc)
1262{
1263 int mod, rm, sibinc;
1264 int size = 0;
1265
1266 rm = MODRM_RM(pCpu->ModRM);
1267 mod = MODRM_MOD(pCpu->ModRM);
1268
1269 if(!pSibInc)
1270 {
1271 pSibInc = &sibinc;
1272 }
1273
1274 *pSibInc = 0;
1275
1276 if(pCpu->addrmode == CPUMODE_32BIT)
1277 {//32 bits addressing mode
1278 if(mod != 3 && rm == 4)
1279 {//SIB byte follows ModRM
1280 *pSibInc = ParseSIB(lpszCodeBlock, pOp, pParam, pCpu);
1281 lpszCodeBlock += *pSibInc;
1282 size += *pSibInc;
1283 }
1284
1285 switch(mod)
1286 {
1287 case 0: //effective address
1288 if(rm == 5) {//32 bits displacement
1289 pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
1290 size += sizeof(int32_t);
1291 }
1292 //else register address
1293 break;
1294
1295 case 1: //effective address + 8 bits displacement
1296 pCpu->disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);
1297 size += sizeof(char);
1298 break;
1299
1300 case 2: //effective address + 32 bits displacement
1301 pCpu->disp = DISReadDWord(pCpu, lpszCodeBlock);
1302 size += sizeof(int32_t);
1303 break;
1304
1305 case 3: //registers
1306 break;
1307 }
1308 }
1309 else
1310 {//16 bits addressing mode
1311 switch(mod)
1312 {
1313 case 0: //effective address
1314 if(rm == 6) {
1315 pCpu->disp = DISReadWord(pCpu, lpszCodeBlock);
1316 size += sizeof(uint16_t);
1317 }
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 + 16 bits displacement
1326 pCpu->disp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);
1327 size += sizeof(uint16_t);
1328 break;
1329
1330 case 3: //registers
1331 break;
1332 }
1333 }
1334 return size;
1335}
1336//*****************************************************************************
1337// Query the size of the ModRM parameters and fetch the immediate data (if any)
1338//*****************************************************************************
1339int QueryModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu, int *pSibInc)
1340{
1341 int mod, rm, sibinc;
1342 int size = 0;
1343
1344 rm = MODRM_RM(pCpu->ModRM);
1345 mod = MODRM_MOD(pCpu->ModRM);
1346
1347 if(!pSibInc)
1348 {
1349 pSibInc = &sibinc;
1350 }
1351
1352 *pSibInc = 0;
1353
1354 if(pCpu->addrmode == CPUMODE_32BIT)
1355 {//32 bits addressing mode
1356 if(mod != 3 && rm == 4)
1357 {//SIB byte follows ModRM
1358 *pSibInc = ParseSIB_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu);
1359 lpszCodeBlock += *pSibInc;
1360 size += *pSibInc;
1361 }
1362
1363 switch(mod)
1364 {
1365 case 0: //effective address
1366 if(rm == 5) {//32 bits displacement
1367 size += sizeof(int32_t);
1368 }
1369 //else register address
1370 break;
1371
1372 case 1: //effective address + 8 bits displacement
1373 size += sizeof(char);
1374 break;
1375
1376 case 2: //effective address + 32 bits displacement
1377 size += sizeof(int32_t);
1378 break;
1379
1380 case 3: //registers
1381 break;
1382 }
1383 }
1384 else
1385 {//16 bits addressing mode
1386 switch(mod)
1387 {
1388 case 0: //effective address
1389 if(rm == 6) {
1390 size += sizeof(uint16_t);
1391 }
1392 break;
1393
1394 case 1: //effective address + 8 bits displacement
1395 size += sizeof(char);
1396 break;
1397
1398 case 2: //effective address + 16 bits displacement
1399 size += sizeof(uint16_t);
1400 break;
1401
1402 case 3: //registers
1403 break;
1404 }
1405 }
1406 return size;
1407}
1408//*****************************************************************************
1409//*****************************************************************************
1410int ParseIllegal(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1411{
1412 AssertFailed();
1413 return 0;
1414}
1415//*****************************************************************************
1416//*****************************************************************************
1417int ParseModRM(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1418{
1419 int size = sizeof(uint8_t); //ModRM byte
1420 int sibinc;
1421
1422 pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
1423 lpszCodeBlock += sizeof(uint8_t);
1424
1425 size += QueryModRM(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
1426 lpszCodeBlock += sibinc;
1427
1428 UseModRM(lpszCodeBlock, pOp, pParam, pCpu);
1429
1430 return size;
1431}
1432//*****************************************************************************
1433//*****************************************************************************
1434int ParseModRM_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1435{
1436 int size = sizeof(uint8_t); //ModRM byte
1437 int sibinc;
1438
1439 pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
1440 lpszCodeBlock += sizeof(uint8_t);
1441
1442 size += QueryModRM_SizeOnly(lpszCodeBlock, pOp, pParam, pCpu, &sibinc);
1443 lpszCodeBlock += sibinc;
1444
1445 /* UseModRM is not necessary here; we're only interested in the opcode size */
1446 return size;
1447}
1448//*****************************************************************************
1449//*****************************************************************************
1450int ParseModFence(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1451{
1452 ////AssertMsgFailed(("??\n"));
1453 //nothing to do apparently
1454 return 0;
1455}
1456//*****************************************************************************
1457//*****************************************************************************
1458int ParseImmByte(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1459{
1460 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1461 pParam->flags |= USE_IMMEDIATE8;
1462
1463 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%02Xh", (uint32_t)pParam->parval);
1464 return sizeof(uint8_t);
1465}
1466//*****************************************************************************
1467//*****************************************************************************
1468int ParseImmByte_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1469{
1470 return sizeof(uint8_t);
1471}
1472//*****************************************************************************
1473//*****************************************************************************
1474int ParseImmByteSX(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1475{
1476 if(pCpu->opmode == CPUMODE_32BIT)
1477 {
1478 pParam->parval = (uint32_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1479 pParam->flags |= USE_IMMEDIATE32_SX8;
1480 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1481 }
1482 else
1483 {
1484 pParam->parval = (uint16_t)(int8_t)DISReadByte(pCpu, lpszCodeBlock);
1485 pParam->flags |= USE_IMMEDIATE16_SX8;
1486 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
1487 }
1488 return sizeof(uint8_t);
1489}
1490//*****************************************************************************
1491//*****************************************************************************
1492int ParseImmByteSX_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1493{
1494 return sizeof(uint8_t);
1495}
1496//*****************************************************************************
1497//*****************************************************************************
1498int ParseImmUshort(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1499{
1500 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1501 pParam->flags |= USE_IMMEDIATE16;
1502
1503 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint16_t)pParam->parval);
1504 return sizeof(uint16_t);
1505}
1506//*****************************************************************************
1507//*****************************************************************************
1508int ParseImmUshort_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1509{
1510 return sizeof(uint16_t);
1511}
1512//*****************************************************************************
1513//*****************************************************************************
1514int ParseImmUlong(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1515{
1516 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1517 pParam->flags |= USE_IMMEDIATE32;
1518
1519 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1520 return sizeof(uint32_t);
1521}
1522//*****************************************************************************
1523//*****************************************************************************
1524int ParseImmUlong_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1525{
1526 return sizeof(uint32_t);
1527}
1528//*****************************************************************************
1529//*****************************************************************************
1530int ParseImmQword(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1531{
1532 pParam->parval = DISReadQWord(pCpu, lpszCodeBlock);
1533 pParam->flags |= USE_IMMEDIATE64;
1534
1535 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08X", (uint32_t)pParam->parval);
1536 disasmAddStringF(&pParam->szParam[9], sizeof(pParam->szParam)-9, "%08Xh", (uint32_t)(pParam->parval >> 32));
1537 return sizeof(uint64_t);
1538}
1539//*****************************************************************************
1540//*****************************************************************************
1541int ParseImmQword_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1542{
1543 return sizeof(uint64_t);
1544}
1545//*****************************************************************************
1546//*****************************************************************************
1547int ParseImmV(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1548{
1549 if(pCpu->opmode == CPUMODE_32BIT)
1550 {
1551 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1552 pParam->flags |= USE_IMMEDIATE32;
1553
1554 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%08Xh", (uint32_t)pParam->parval);
1555 return sizeof(uint32_t);
1556 }
1557 else
1558 {
1559 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1560 pParam->flags |= USE_IMMEDIATE16;
1561
1562 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04Xh", (uint32_t)pParam->parval);
1563 return sizeof(uint16_t);
1564 }
1565}
1566//*****************************************************************************
1567//*****************************************************************************
1568int ParseImmV_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1569{
1570 if(pCpu->opmode == CPUMODE_32BIT)
1571 {
1572 return sizeof(uint32_t);
1573 }
1574 else
1575 {
1576 return sizeof(uint16_t);
1577 }
1578}
1579//*****************************************************************************
1580// Relative displacement for branches (rel. to next instruction)
1581//*****************************************************************************
1582int ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1583{
1584 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1585 pParam->flags |= USE_IMMEDIATE8_REL;
1586
1587 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%02Xh)", (uint32_t)pParam->parval);
1588 return sizeof(char);
1589}
1590//*****************************************************************************
1591// Relative displacement for branches (rel. to next instruction)
1592//*****************************************************************************
1593int ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1594{
1595 return sizeof(char);
1596}
1597//*****************************************************************************
1598// Relative displacement for branches (rel. to next instruction)
1599//*****************************************************************************
1600int ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1601{
1602 if(pCpu->opmode == CPUMODE_32BIT)
1603 {
1604 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1605 pParam->flags |= USE_IMMEDIATE32_REL;
1606
1607 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%08Xh)", (uint32_t)pParam->parval);
1608 return sizeof(int32_t);
1609 }
1610 else
1611 {
1612 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1613 pParam->flags |= USE_IMMEDIATE16_REL;
1614
1615 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%04Xh)", (uint32_t)pParam->parval);
1616 return sizeof(uint16_t);
1617 }
1618}
1619//*****************************************************************************
1620// Relative displacement for branches (rel. to next instruction)
1621//*****************************************************************************
1622int ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1623{
1624 if(pCpu->opmode == CPUMODE_32BIT)
1625 {
1626 return sizeof(int32_t);
1627 }
1628 else
1629 {
1630 return sizeof(uint16_t);
1631 }
1632}
1633//*****************************************************************************
1634//*****************************************************************************
1635int ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1636{
1637 disasmGetPtrString(pCpu, pOp, pParam);
1638 if(pCpu->addrmode == CPUMODE_32BIT)
1639 {
1640 if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1641 {// far 16:32 pointer
1642 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1643 *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
1644 pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
1645
1646 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
1647 return sizeof(uint32_t) + sizeof(uint16_t);
1648 }
1649 else
1650 {// near 32 bits pointer
1651 /*
1652 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1653 * so we treat it like displacement.
1654 */
1655 pParam->disp32 = DISReadDWord(pCpu, lpszCodeBlock);
1656 pParam->flags |= USE_DISPLACEMENT32;
1657
1658 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08Xh]", pParam->disp32);
1659 return sizeof(uint32_t);
1660 }
1661 }
1662 else
1663 {
1664 if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1665 {// far 16:16 pointer
1666 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1667 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1668
1669 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1670 return sizeof(uint32_t);
1671 }
1672 else
1673 {// near 16 bits pointer
1674 /*
1675 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1676 * so we treat it like displacement.
1677 */
1678 pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
1679 pParam->flags |= USE_DISPLACEMENT16;
1680
1681 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
1682 return sizeof(uint16_t);
1683 }
1684 }
1685}
1686//*****************************************************************************
1687//*****************************************************************************
1688int ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1689{
1690 if(pCpu->addrmode == CPUMODE_32BIT)
1691 {
1692 if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1693 {// far 16:32 pointer
1694 return sizeof(uint32_t) + sizeof(uint16_t);
1695 }
1696 else
1697 {// near 32 bits pointer
1698 return sizeof(uint32_t);
1699 }
1700 }
1701 else
1702 {
1703 if(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1704 {// far 16:16 pointer
1705 return sizeof(uint32_t);
1706 }
1707 else
1708 {// near 16 bits pointer
1709 return sizeof(uint16_t);
1710 }
1711 }
1712}
1713//*****************************************************************************
1714//*****************************************************************************
1715int ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1716{
1717 /*
1718 * Sets up flags for stored in OPC fixed registers.
1719 */
1720
1721 if(pParam->param == OP_PARM_NONE)
1722 {
1723 /* No parameter at all. */
1724 return 0;
1725 }
1726
1727 if(pParam->param < OP_PARM_REG_SEG_START)
1728 {
1729 /* 32-bit EAX..EDI registers. */
1730
1731 if(pCpu->opmode == CPUMODE_32BIT)
1732 {
1733 /* Use 32-bit registers. */
1734 pParam->base.reg_gen32 = pParam->param - OP_PARM_REG_GEN32_START;
1735 pParam->flags |= USE_REG_GEN32;
1736 pParam->size = 4;
1737 }
1738 else
1739 {
1740 /* Use 16-bit registers. */
1741 pParam->base.reg_gen16 = pParam->param - OP_PARM_REG_GEN32_START;
1742 pParam->flags |= USE_REG_GEN16;
1743 pParam->size = 2;
1744 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1745 }
1746 }
1747 else
1748 if(pParam->param < OP_PARM_REG_GEN16_START)
1749 {
1750 /* Segment ES..GS registers. */
1751 pParam->base.reg_seg = pParam->param - OP_PARM_REG_SEG_START;
1752 pParam->flags |= USE_REG_SEG;
1753 pParam->size = 2;
1754 }
1755 else
1756 if(pParam->param < OP_PARM_REG_GEN8_START)
1757 {
1758 /* 16-bit AX..DI registers. */
1759 pParam->base.reg_gen16 = pParam->param - OP_PARM_REG_GEN16_START;
1760 pParam->flags |= USE_REG_GEN16;
1761 pParam->size = 2;
1762 }
1763 else
1764 if(pParam->param < OP_PARM_REG_FP_START)
1765 {
1766 /* 8-bit AL..DL, AH..DH registers. */
1767 pParam->base.reg_gen8 = pParam->param - OP_PARM_REG_GEN8_START;
1768 pParam->flags |= USE_REG_GEN8;
1769 pParam->size = 1;
1770 }
1771 else
1772 if(pParam->param <= OP_PARM_REGFP_7)
1773 {
1774 /* FPU registers. */
1775 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1776 pParam->flags |= USE_REG_FP;
1777 pParam->size = 10;
1778 }
1779 /* else - not supported for now registers. */
1780
1781 return 0;
1782}
1783//*****************************************************************************
1784//*****************************************************************************
1785int ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1786{
1787 disasmGetPtrString(pCpu, pOp, pParam);
1788 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1789
1790 pParam->flags |= USE_POINTER_DS_BASED;
1791 if(pCpu->addrmode == CPUMODE_32BIT)
1792 {
1793 pParam->base.reg_gen32 = USE_REG_ESI;
1794 pParam->flags |= USE_REG_GEN32;
1795 }
1796 else
1797 {
1798 pParam->base.reg_gen16 = USE_REG_SI;
1799 pParam->flags |= USE_REG_GEN16;
1800 }
1801 return 0; //no additional opcode bytes
1802}
1803//*****************************************************************************
1804//*****************************************************************************
1805int ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1806{
1807 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1808
1809 pParam->flags |= USE_POINTER_DS_BASED;
1810 if(pCpu->addrmode == CPUMODE_32BIT)
1811 {
1812 pParam->base.reg_gen32 = USE_REG_ESI;
1813 pParam->flags |= USE_REG_GEN32;
1814 }
1815 else
1816 {
1817 pParam->base.reg_gen16 = USE_REG_SI;
1818 pParam->flags |= USE_REG_GEN16;
1819 }
1820 return 0; //no additional opcode bytes
1821}
1822//*****************************************************************************
1823//*****************************************************************************
1824int ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1825{
1826 disasmGetPtrString(pCpu, pOp, pParam);
1827 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1828
1829 pParam->flags |= USE_POINTER_ES_BASED;
1830 if(pCpu->addrmode == CPUMODE_32BIT)
1831 {
1832 pParam->base.reg_gen32 = USE_REG_EDI;
1833 pParam->flags |= USE_REG_GEN32;
1834 }
1835 else
1836 {
1837 pParam->base.reg_gen16 = USE_REG_DI;
1838 pParam->flags |= USE_REG_GEN16;
1839 }
1840 return 0; //no additional opcode bytes
1841}
1842//*****************************************************************************
1843//*****************************************************************************
1844int ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1845{
1846 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1847
1848 pParam->flags |= USE_POINTER_ES_BASED;
1849 if(pCpu->addrmode == CPUMODE_32BIT)
1850 {
1851 pParam->base.reg_gen32 = USE_REG_EDI;
1852 pParam->flags |= USE_REG_GEN32;
1853 }
1854 else
1855 {
1856 pParam->base.reg_gen16 = USE_REG_DI;
1857 pParam->flags |= USE_REG_GEN16;
1858 }
1859 return 0; //no additional opcode bytes
1860}
1861//*****************************************************************************
1862//*****************************************************************************
1863int ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1864{
1865 const OPCODE *pOpcode;
1866 int size = sizeof(uint8_t);
1867
1868 //2nd byte
1869 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1870 pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
1871
1872 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1873 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1874 if (pCpu->lastprefix)
1875 {
1876 switch(pCpu->lastprefix)
1877 {
1878 case OP_OPSIZE: /* 0x66 */
1879 if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
1880 {
1881 /* Table entry is valid, so use the extension table. */
1882 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
1883
1884 /* Cancel prefix changes. */
1885 pCpu->prefix &= ~PREFIX_OPSIZE;
1886 pCpu->opmode = pCpu->mode;
1887 }
1888 break;
1889
1890 case OP_REPNE: /* 0xF2 */
1891 if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
1892 {
1893 /* Table entry is valid, so use the extension table. */
1894 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
1895
1896 /* Cancel prefix changes. */
1897 pCpu->prefix &= ~PREFIX_REPNE;
1898 }
1899 break;
1900
1901 case OP_REPE: /* 0xF3 */
1902 if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
1903 {
1904 /* Table entry is valid, so use the extension table. */
1905 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
1906
1907 /* Cancel prefix changes. */
1908 pCpu->prefix &= ~PREFIX_REP;
1909 }
1910 break;
1911 }
1912 }
1913
1914 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1915 return size;
1916}
1917//*****************************************************************************
1918//*****************************************************************************
1919int ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1920{
1921 int size = 0;
1922
1923 if (pCpu->prefix & PREFIX_REP)
1924 {
1925 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1926 pCpu->prefix &= ~PREFIX_REP;
1927 }
1928 else
1929 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1930
1931 size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
1932 return size;
1933}
1934//*****************************************************************************
1935//*****************************************************************************
1936int ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1937{
1938 int idx = (pCpu->opcode - 0x80) * 8;
1939 int size = 0, modrm, reg;
1940
1941 modrm = DISReadByte(pCpu, lpszCodeBlock);
1942 reg = MODRM_REG(modrm);
1943
1944 pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
1945 //little hack to make sure the ModRM byte is included in the returned size
1946 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1947 {
1948 size = sizeof(uint8_t); //ModRM byte
1949 }
1950
1951 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1952
1953 return size;
1954}
1955//*****************************************************************************
1956//*****************************************************************************
1957int ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1958{
1959 int idx;
1960 int size = 0, modrm, reg;
1961
1962 switch(pCpu->opcode)
1963 {
1964 case 0xC0:
1965 case 0xC1:
1966 idx = (pCpu->opcode - 0xC0)*8;
1967 break;
1968
1969 case 0xD0:
1970 case 0xD1:
1971 case 0xD2:
1972 case 0xD3:
1973 idx = (pCpu->opcode - 0xD0 + 2)*8;
1974 break;
1975
1976 default:
1977 AssertMsgFailed(("Oops\n"));
1978 return sizeof(uint8_t);
1979 }
1980
1981 modrm = DISReadByte(pCpu, lpszCodeBlock);
1982 reg = MODRM_REG(modrm);
1983
1984 pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
1985
1986 //little hack to make sure the ModRM byte is included in the returned size
1987 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1988 {
1989 size = sizeof(uint8_t); //ModRM byte
1990 }
1991
1992 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1993
1994 return size;
1995}
1996//*****************************************************************************
1997//*****************************************************************************
1998int ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1999{
2000 int idx = (pCpu->opcode - 0xF6) * 8;
2001 int size = 0, modrm, reg;
2002
2003 modrm = DISReadByte(pCpu, lpszCodeBlock);
2004 reg = MODRM_REG(modrm);
2005
2006 pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
2007
2008 //little hack to make sure the ModRM byte is included in the returned size
2009 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2010 {
2011 size = sizeof(uint8_t); //ModRM byte
2012 }
2013
2014 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2015
2016 return size;
2017}
2018//*****************************************************************************
2019//*****************************************************************************
2020int ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2021{
2022 int size = 0, modrm, reg;
2023
2024 modrm = DISReadByte(pCpu, lpszCodeBlock);
2025 reg = MODRM_REG(modrm);
2026
2027 pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
2028
2029 //little hack to make sure the ModRM byte is included in the returned size
2030 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2031 {
2032 size = sizeof(uint8_t); //ModRM byte
2033 }
2034
2035 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2036
2037 return size;
2038}
2039//*****************************************************************************
2040//*****************************************************************************
2041int ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2042{
2043 int size = 0, modrm, reg;
2044
2045 modrm = DISReadByte(pCpu, lpszCodeBlock);
2046 reg = MODRM_REG(modrm);
2047
2048 pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
2049
2050 //little hack to make sure the ModRM byte is included in the returned size
2051 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2052 {
2053 size = sizeof(uint8_t); //ModRM byte
2054 }
2055
2056 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2057
2058 return size;
2059}
2060//*****************************************************************************
2061// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
2062// It would appear the ModRM byte must always be present. How else can you
2063// determine the offset of the imm8_opcode byte otherwise?
2064//
2065//*****************************************************************************
2066int Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2067{
2068 int size = 0, modrmsize;
2069
2070#ifdef DEBUG_Sander
2071 //needs testing
2072 AssertMsgFailed(("Test me\n"));
2073#endif
2074
2075 pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
2076
2077 modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
2078
2079 uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
2080
2081 pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
2082
2083 //little hack to make sure the ModRM byte is included in the returned size
2084 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2085 {
2086#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
2087 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
2088#endif
2089 size = sizeof(uint8_t); //ModRM byte
2090 }
2091
2092 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2093 size += sizeof(uint8_t); //imm8_opcode uint8_t
2094
2095 return size;
2096}
2097//*****************************************************************************
2098//*****************************************************************************
2099int ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2100{
2101 int size = 0, modrm, reg;
2102
2103 modrm = DISReadByte(pCpu, lpszCodeBlock);
2104 reg = MODRM_REG(modrm);
2105
2106 pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
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 size = sizeof(uint8_t); //ModRM byte
2112 }
2113
2114 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2115
2116 return size;
2117}
2118//*****************************************************************************
2119//*****************************************************************************
2120int ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2121{
2122 int size = 0, modrm, reg, rm, mod;
2123
2124 modrm = DISReadByte(pCpu, lpszCodeBlock);
2125 mod = MODRM_MOD(modrm);
2126 reg = MODRM_REG(modrm);
2127 rm = MODRM_RM(modrm);
2128
2129 if (mod == 3 && rm == 0)
2130 {
2131 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
2132 }
2133 else
2134 if (mod == 3 && rm == 1)
2135 {
2136 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
2137 }
2138 else
2139 pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
2140
2141 //little hack to make sure the ModRM byte is included in the returned size
2142 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2143 {
2144 size = sizeof(uint8_t); //ModRM byte
2145 }
2146
2147 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2148
2149 return size;
2150}
2151//*****************************************************************************
2152//*****************************************************************************
2153int ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2154{
2155 int size = 0, modrm, reg;
2156
2157 modrm = DISReadByte(pCpu, lpszCodeBlock);
2158 reg = MODRM_REG(modrm);
2159
2160 pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
2161
2162 //little hack to make sure the ModRM byte is included in the returned size
2163 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2164 {
2165 size = sizeof(uint8_t); //ModRM byte
2166 }
2167
2168 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2169
2170 return size;
2171}
2172//*****************************************************************************
2173//*****************************************************************************
2174int ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2175{
2176 int size = 0, modrm, reg;
2177
2178 modrm = DISReadByte(pCpu, lpszCodeBlock);
2179 reg = MODRM_REG(modrm);
2180
2181 pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
2182
2183 //little hack to make sure the ModRM byte is included in the returned size
2184 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2185 {
2186 size = sizeof(uint8_t); //ModRM byte
2187 }
2188
2189 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2190
2191 return size;
2192}
2193//*****************************************************************************
2194//*****************************************************************************
2195int ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2196{
2197 int size = 0, modrm, reg;
2198
2199 modrm = DISReadByte(pCpu, lpszCodeBlock);
2200 reg = MODRM_REG(modrm);
2201
2202 pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
2203
2204 //little hack to make sure the ModRM byte is included in the returned size
2205 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2206 {
2207 size = sizeof(uint8_t); //ModRM byte
2208 }
2209
2210 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2211
2212 return size;
2213}
2214//*****************************************************************************
2215//*****************************************************************************
2216int ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2217{
2218 int size = 0, modrm, reg;
2219
2220 modrm = DISReadByte(pCpu, lpszCodeBlock);
2221 reg = MODRM_REG(modrm);
2222
2223 if(pCpu->prefix & PREFIX_OPSIZE)
2224 {
2225 reg += 8; //2nd table
2226 }
2227
2228 pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
2229
2230 //little hack to make sure the ModRM byte is included in the returned size
2231 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2232 {
2233 size = sizeof(uint8_t); //ModRM byte
2234 }
2235
2236 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2237
2238 return size;
2239}
2240//*****************************************************************************
2241//*****************************************************************************
2242int ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2243{
2244 int size = 0, modrm, reg;
2245
2246 modrm = DISReadByte(pCpu, lpszCodeBlock);
2247 reg = MODRM_REG(modrm);
2248 if(pCpu->prefix & PREFIX_OPSIZE)
2249 {
2250 reg += 8; //2nd table
2251 }
2252
2253 pOp = (PCOPCODE)&g_aMapX86_Group13[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 ParseGrp14(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_Group14[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 ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2293{
2294 int size = 0, modrm, reg, mod, rm;
2295
2296 modrm = DISReadByte(pCpu, lpszCodeBlock);
2297 mod = MODRM_MOD(modrm);
2298 reg = MODRM_REG(modrm);
2299 rm = MODRM_RM(modrm);
2300
2301 if (mod == 3 && rm == 0)
2302 pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
2303 else
2304 pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
2305
2306 //little hack to make sure the ModRM byte is included in the returned size
2307 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2308 {
2309 size = sizeof(uint8_t); //ModRM byte
2310 }
2311
2312 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2313
2314 return size;
2315}
2316//*****************************************************************************
2317//*****************************************************************************
2318int ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
2319{
2320 int size = 0, modrm, reg;
2321
2322 modrm = DISReadByte(pCpu, lpszCodeBlock);
2323 reg = MODRM_REG(modrm);
2324
2325 pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
2326
2327 //little hack to make sure the ModRM byte is included in the returned size
2328 if(pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2329 {
2330 size = sizeof(uint8_t); //ModRM byte
2331 }
2332
2333 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
2334
2335 return size;
2336}
2337//*****************************************************************************
2338char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
2339char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
2340char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
2341//*****************************************************************************
2342void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam, int fRegAddr)
2343{
2344 int subtype, type, mod;
2345
2346 mod = MODRM_MOD(pCpu->ModRM);
2347
2348 type = OP_PARM_VTYPE(pParam->param);
2349 subtype = OP_PARM_VSUBTYPE(pParam->param);
2350 if (fRegAddr)
2351 {
2352 subtype = OP_PARM_d;
2353 }
2354 else
2355 if(subtype == OP_PARM_v || subtype == OP_PARM_NONE)
2356 {
2357 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
2358 }
2359
2360 switch(subtype)
2361 {
2362 case OP_PARM_b:
2363 disasmAddString(pParam->szParam, szModRMReg8[idx]);
2364 pParam->flags |= USE_REG_GEN8;
2365 pParam->base.reg_gen8 = idx;
2366 break;
2367
2368 case OP_PARM_w:
2369 disasmAddString(pParam->szParam, szModRMReg16[idx]);
2370 pParam->flags |= USE_REG_GEN16;
2371 pParam->base.reg_gen16 = idx;
2372 break;
2373
2374 case OP_PARM_d:
2375 disasmAddString(pParam->szParam, szModRMReg32[idx]);
2376 pParam->flags |= USE_REG_GEN32;
2377 pParam->base.reg_gen32 = idx;
2378 break;
2379
2380 default:
2381#ifdef IN_RING3
2382 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
2383 DIS_THROW(ExceptionInvalidModRM);
2384#else
2385 AssertMsgFailed(("Oops!\n"));
2386#endif
2387 break;
2388 }
2389}
2390//*****************************************************************************
2391char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
2392int 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};
2393int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
2394//*****************************************************************************
2395void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
2396{
2397 disasmAddString(pParam->szParam, szModRMReg1616[idx]);
2398 pParam->flags |= USE_REG_GEN16;
2399 pParam->base.reg_gen16 = BaseModRMReg16[idx];
2400 if(idx < 4)
2401 {
2402 pParam->flags |= USE_INDEX;
2403 pParam->index.reg_gen = IndexModRMReg16[idx];
2404 }
2405}
2406//*****************************************************************************
2407char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
2408//*****************************************************************************
2409void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
2410{
2411#if 0 //def DEBUG_Sander
2412 AssertMsg(idx < (int)ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
2413#endif
2414#ifdef IN_RING3
2415 if(idx >= (int)ELEMENTS(szModRMSegReg))
2416 {
2417 Log(("disasmModRMSReg %d failed!!\n", idx));
2418 DIS_THROW(ExceptionInvalidParameter);
2419 }
2420#endif
2421
2422 idx = RT_MIN(idx, (int)ELEMENTS(szModRMSegReg)-1);
2423 disasmAddString(pParam->szParam, szModRMSegReg[idx]);
2424 pParam->flags |= USE_REG_SEG;
2425 pParam->base.reg_seg = idx;
2426}
2427//*****************************************************************************
2428//*****************************************************************************
2429void disasmPrintAbs32(POP_PARAMETER pParam)
2430{
2431 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2432}
2433//*****************************************************************************
2434//*****************************************************************************
2435void disasmPrintDisp32(POP_PARAMETER pParam)
2436{
2437 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2438}
2439//*****************************************************************************
2440//*****************************************************************************
2441void disasmPrintDisp8(POP_PARAMETER pParam)
2442{
2443 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
2444}
2445//*****************************************************************************
2446//*****************************************************************************
2447void disasmPrintDisp16(POP_PARAMETER pParam)
2448{
2449 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
2450}
2451//*****************************************************************************
2452//*****************************************************************************
2453void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
2454{
2455 int subtype = OP_PARM_VSUBTYPE(pParam->param);
2456
2457 if(subtype == OP_PARM_v)
2458 {
2459 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
2460 }
2461
2462 switch(subtype)
2463 {
2464 case OP_PARM_a: //two words or dwords depending on operand size (bound only)
2465 break;
2466
2467 case OP_PARM_b:
2468 disasmAddString(pParam->szParam, "byte ptr ");
2469 break;
2470
2471 case OP_PARM_w:
2472 disasmAddString(pParam->szParam, "word ptr ");
2473 break;
2474
2475 case OP_PARM_d:
2476 disasmAddString(pParam->szParam, "dword ptr ");
2477 break;
2478
2479 case OP_PARM_q:
2480 case OP_PARM_dq:
2481 disasmAddString(pParam->szParam, "qword ptr ");
2482 break;
2483
2484 case OP_PARM_p:
2485 disasmAddString(pParam->szParam, "far ptr ");
2486 break;
2487
2488 case OP_PARM_s:
2489 break; //??
2490
2491 case OP_PARM_z:
2492 break;
2493 default:
2494 break; //no pointer type specified/necessary
2495 }
2496 if (pCpu->prefix & PREFIX_SEG)
2497 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->prefix_seg]);
2498}
2499#ifndef IN_GC
2500//*****************************************************************************
2501/* Read functions for getting the opcode bytes */
2502//*****************************************************************************
2503uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2504{
2505 if(pCpu->pfnReadBytes)
2506 {
2507 uint8_t temp = 0;
2508 int rc;
2509
2510 rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), (RTUINTPTR)pCpu);
2511 if(VBOX_FAILURE(rc))
2512 {
2513 Log(("DISReadByte failed!!\n"));
2514 DIS_THROW(ExceptionMemRead);
2515 }
2516 return temp;
2517 }
2518#ifdef IN_RING0
2519 AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
2520 return 0;
2521#else
2522 else return *(uint8_t *)pAddress;
2523#endif
2524}
2525//*****************************************************************************
2526//*****************************************************************************
2527uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2528{
2529 if(pCpu->pfnReadBytes)
2530 {
2531 uint16_t temp = 0;
2532 int rc;
2533
2534 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), (RTUINTPTR)pCpu);
2535 if(VBOX_FAILURE(rc))
2536 {
2537 Log(("DISReadWord failed!!\n"));
2538 DIS_THROW(ExceptionMemRead);
2539 }
2540 return temp;
2541 }
2542#ifdef IN_RING0
2543 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
2544 return 0;
2545#else
2546 else return *(uint16_t *)pAddress;
2547#endif
2548}
2549//*****************************************************************************
2550//*****************************************************************************
2551uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2552{
2553 if(pCpu->pfnReadBytes)
2554 {
2555 uint32_t temp = 0;
2556 int rc;
2557
2558 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), (RTUINTPTR)pCpu);
2559 if(VBOX_FAILURE(rc))
2560 {
2561 Log(("DISReadDWord failed!!\n"));
2562 DIS_THROW(ExceptionMemRead);
2563 }
2564 return temp;
2565 }
2566#ifdef IN_RING0
2567 AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
2568 return 0;
2569#else
2570 else return *(uint32_t *)pAddress;
2571#endif
2572}
2573//*****************************************************************************
2574//*****************************************************************************
2575uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2576{
2577 if(pCpu->pfnReadBytes)
2578 {
2579 uint64_t temp = 0;
2580 int rc;
2581
2582 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), (RTUINTPTR)pCpu);
2583 if(VBOX_FAILURE(rc))
2584 {
2585 Log(("DISReadQWord %x failed!!\n", pAddress));
2586 DIS_THROW(ExceptionMemRead);
2587 }
2588
2589 return temp;
2590 }
2591#ifdef IN_RING0
2592 AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
2593 return 0;
2594#else
2595 else return *(uint64_t *)pAddress;
2596#endif
2597}
2598#endif /* IN_GC */
2599
2600#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2601//*****************************************************************************
2602//*****************************************************************************
2603void disasmAddString(char *psz, const char *pszAdd)
2604{
2605 strcat(psz, pszAdd);
2606}
2607//*****************************************************************************
2608//*****************************************************************************
2609void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
2610{
2611 va_list args;
2612 va_start(args, pszFormat);
2613 RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
2614 va_end(args);
2615}
2616
2617//*****************************************************************************
2618//*****************************************************************************
2619void disasmAddChar(char *psz, char ch)
2620{
2621 char sz[2];
2622
2623 sz[0] = ch;
2624 sz[1] = '\0';
2625 strcat(psz, sz);
2626}
2627#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