VirtualBox

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

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

More 64 bits disassembler updates

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

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