VirtualBox

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

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

Cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 71.1 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.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 (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 return sizeof(uint32_t);
1086 return sizeof(uint16_t);
1087}
1088//*****************************************************************************
1089// Relative displacement for branches (rel. to next instruction)
1090//*****************************************************************************
1091unsigned ParseImmBRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1092{
1093 pParam->parval = DISReadByte(pCpu, lpszCodeBlock);
1094 pParam->flags |= USE_IMMEDIATE8_REL;
1095
1096 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%02Xh)", (uint32_t)pParam->parval);
1097 return sizeof(char);
1098}
1099//*****************************************************************************
1100// Relative displacement for branches (rel. to next instruction)
1101//*****************************************************************************
1102unsigned ParseImmBRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1103{
1104 return sizeof(char);
1105}
1106//*****************************************************************************
1107// Relative displacement for branches (rel. to next instruction)
1108//*****************************************************************************
1109unsigned ParseImmVRel(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1110{
1111 if (pCpu->opmode == CPUMODE_32BIT)
1112 {
1113 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1114 pParam->flags |= USE_IMMEDIATE32_REL;
1115
1116 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%08Xh)", (uint32_t)pParam->parval);
1117 return sizeof(int32_t);
1118 }
1119 else
1120 {
1121 pParam->parval = DISReadWord(pCpu, lpszCodeBlock);
1122 pParam->flags |= USE_IMMEDIATE16_REL;
1123
1124 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), " (0%04Xh)", (uint32_t)pParam->parval);
1125 return sizeof(uint16_t);
1126 }
1127}
1128//*****************************************************************************
1129// Relative displacement for branches (rel. to next instruction)
1130//*****************************************************************************
1131unsigned ParseImmVRel_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1132{
1133 if (pCpu->opmode == CPUMODE_32BIT)
1134 return sizeof(int32_t);
1135 return sizeof(uint16_t);
1136}
1137//*****************************************************************************
1138//*****************************************************************************
1139unsigned ParseImmAddr(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1140{
1141 disasmGetPtrString(pCpu, pOp, pParam);
1142 if (pCpu->addrmode == CPUMODE_32BIT)
1143 {
1144 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1145 {// far 16:32 pointer
1146 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1147 *((uint32_t*)&pParam->parval+1) = DISReadWord(pCpu, lpszCodeBlock+sizeof(uint32_t));
1148 pParam->flags |= USE_IMMEDIATE_ADDR_16_32;
1149
1150 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);
1151 return sizeof(uint32_t) + sizeof(uint16_t);
1152 }
1153 else
1154 {// near 32 bits pointer
1155 /*
1156 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1157 * so we treat it like displacement.
1158 */
1159 pParam->disp32 = DISReadDWord(pCpu, lpszCodeBlock);
1160 pParam->flags |= USE_DISPLACEMENT32;
1161
1162 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08Xh]", pParam->disp32);
1163 return sizeof(uint32_t);
1164 }
1165 }
1166 else
1167 {
1168 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1169 {// far 16:16 pointer
1170 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1171 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1172
1173 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1174 return sizeof(uint32_t);
1175 }
1176 else
1177 {// near 16 bits pointer
1178 /*
1179 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1180 * so we treat it like displacement.
1181 */
1182 pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
1183 pParam->flags |= USE_DISPLACEMENT16;
1184
1185 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
1186 return sizeof(uint16_t);
1187 }
1188 }
1189}
1190//*****************************************************************************
1191//*****************************************************************************
1192unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1193{
1194 if (pCpu->addrmode == CPUMODE_32BIT)
1195 {
1196 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1197 {// far 16:32 pointer
1198 return sizeof(uint32_t) + sizeof(uint16_t);
1199 }
1200 else
1201 {// near 32 bits pointer
1202 return sizeof(uint32_t);
1203 }
1204 }
1205 else
1206 {
1207 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1208 {// far 16:16 pointer
1209 return sizeof(uint32_t);
1210 }
1211 else
1212 {// near 16 bits pointer
1213 return sizeof(uint16_t);
1214 }
1215 }
1216}
1217//*****************************************************************************
1218//*****************************************************************************
1219unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1220{
1221 /*
1222 * Sets up flags for stored in OPC fixed registers.
1223 */
1224
1225 if (pParam->param == OP_PARM_NONE)
1226 {
1227 /* No parameter at all. */
1228 return 0;
1229 }
1230
1231 if (pParam->param < OP_PARM_REG_SEG_START)
1232 {
1233 /* 32-bit EAX..EDI registers. */
1234
1235 if (pCpu->opmode == CPUMODE_32BIT)
1236 {
1237 /* Use 32-bit registers. */
1238 pParam->base.reg_gen32 = pParam->param - OP_PARM_REG_GEN32_START;
1239 pParam->flags |= USE_REG_GEN32;
1240 pParam->size = 4;
1241 }
1242 else
1243 {
1244 /* Use 16-bit registers. */
1245 pParam->base.reg_gen16 = pParam->param - OP_PARM_REG_GEN32_START;
1246 pParam->flags |= USE_REG_GEN16;
1247 pParam->size = 2;
1248 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1249 }
1250 }
1251 else
1252 if (pParam->param < OP_PARM_REG_GEN16_START)
1253 {
1254 /* Segment ES..GS registers. */
1255 pParam->base.reg_seg = pParam->param - OP_PARM_REG_SEG_START;
1256 pParam->flags |= USE_REG_SEG;
1257 pParam->size = 2;
1258 }
1259 else
1260 if (pParam->param < OP_PARM_REG_GEN8_START)
1261 {
1262 /* 16-bit AX..DI registers. */
1263 pParam->base.reg_gen16 = pParam->param - OP_PARM_REG_GEN16_START;
1264 pParam->flags |= USE_REG_GEN16;
1265 pParam->size = 2;
1266 }
1267 else
1268 if (pParam->param < OP_PARM_REG_FP_START)
1269 {
1270 /* 8-bit AL..DL, AH..DH registers. */
1271 pParam->base.reg_gen8 = pParam->param - OP_PARM_REG_GEN8_START;
1272 pParam->flags |= USE_REG_GEN8;
1273 pParam->size = 1;
1274 }
1275 else
1276 if (pParam->param <= OP_PARM_REGFP_7)
1277 {
1278 /* FPU registers. */
1279 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1280 pParam->flags |= USE_REG_FP;
1281 pParam->size = 10;
1282 }
1283 /* else - not supported for now registers. */
1284
1285 return 0;
1286}
1287//*****************************************************************************
1288//*****************************************************************************
1289unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1290{
1291 disasmGetPtrString(pCpu, pOp, pParam);
1292 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1293
1294 pParam->flags |= USE_POINTER_DS_BASED;
1295 if (pCpu->addrmode == CPUMODE_32BIT)
1296 {
1297 pParam->base.reg_gen32 = USE_REG_ESI;
1298 pParam->flags |= USE_REG_GEN32;
1299 }
1300 else
1301 {
1302 pParam->base.reg_gen16 = USE_REG_SI;
1303 pParam->flags |= USE_REG_GEN16;
1304 }
1305 return 0; //no additional opcode bytes
1306}
1307//*****************************************************************************
1308//*****************************************************************************
1309unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1310{
1311 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1312
1313 pParam->flags |= USE_POINTER_DS_BASED;
1314 if (pCpu->addrmode == CPUMODE_32BIT)
1315 {
1316 pParam->base.reg_gen32 = USE_REG_ESI;
1317 pParam->flags |= USE_REG_GEN32;
1318 }
1319 else
1320 {
1321 pParam->base.reg_gen16 = USE_REG_SI;
1322 pParam->flags |= USE_REG_GEN16;
1323 }
1324 return 0; //no additional opcode bytes
1325}
1326//*****************************************************************************
1327//*****************************************************************************
1328unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1329{
1330 disasmGetPtrString(pCpu, pOp, pParam);
1331 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1332
1333 pParam->flags |= USE_POINTER_ES_BASED;
1334 if (pCpu->addrmode == CPUMODE_32BIT)
1335 {
1336 pParam->base.reg_gen32 = USE_REG_EDI;
1337 pParam->flags |= USE_REG_GEN32;
1338 }
1339 else
1340 {
1341 pParam->base.reg_gen16 = USE_REG_DI;
1342 pParam->flags |= USE_REG_GEN16;
1343 }
1344 return 0; //no additional opcode bytes
1345}
1346//*****************************************************************************
1347//*****************************************************************************
1348unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1349{
1350 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1351
1352 pParam->flags |= USE_POINTER_ES_BASED;
1353 if (pCpu->addrmode == CPUMODE_32BIT)
1354 {
1355 pParam->base.reg_gen32 = USE_REG_EDI;
1356 pParam->flags |= USE_REG_GEN32;
1357 }
1358 else
1359 {
1360 pParam->base.reg_gen16 = USE_REG_DI;
1361 pParam->flags |= USE_REG_GEN16;
1362 }
1363 return 0; //no additional opcode bytes
1364}
1365//*****************************************************************************
1366//*****************************************************************************
1367unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1368{
1369 const OPCODE *pOpcode;
1370 int size = sizeof(uint8_t);
1371
1372 //2nd byte
1373 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1374 pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
1375
1376 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1377 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1378 if (pCpu->lastprefix)
1379 {
1380 switch (pCpu->lastprefix)
1381 {
1382 case OP_OPSIZE: /* 0x66 */
1383 if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
1384 {
1385 /* Table entry is valid, so use the extension table. */
1386 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
1387
1388 /* Cancel prefix changes. */
1389 pCpu->prefix &= ~PREFIX_OPSIZE;
1390 pCpu->opmode = pCpu->mode;
1391 }
1392 break;
1393
1394 case OP_REPNE: /* 0xF2 */
1395 if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
1396 {
1397 /* Table entry is valid, so use the extension table. */
1398 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
1399
1400 /* Cancel prefix changes. */
1401 pCpu->prefix &= ~PREFIX_REPNE;
1402 }
1403 break;
1404
1405 case OP_REPE: /* 0xF3 */
1406 if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
1407 {
1408 /* Table entry is valid, so use the extension table. */
1409 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
1410
1411 /* Cancel prefix changes. */
1412 pCpu->prefix &= ~PREFIX_REP;
1413 }
1414 break;
1415 }
1416 }
1417
1418 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1419 return size;
1420}
1421//*****************************************************************************
1422//*****************************************************************************
1423unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1424{
1425 unsigned size = 0;
1426
1427 if (pCpu->prefix & PREFIX_REP)
1428 {
1429 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1430 pCpu->prefix &= ~PREFIX_REP;
1431 }
1432 else
1433 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1434
1435 size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
1436 return size;
1437}
1438//*****************************************************************************
1439//*****************************************************************************
1440unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1441{
1442 int idx = (pCpu->opcode - 0x80) * 8;
1443 unsigned size = 0, modrm, reg;
1444
1445 modrm = DISReadByte(pCpu, lpszCodeBlock);
1446 reg = MODRM_REG(modrm);
1447
1448 pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
1449 //little hack to make sure the ModRM byte is included in the returned size
1450 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1451 {
1452 size = sizeof(uint8_t); //ModRM byte
1453 }
1454
1455 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1456
1457 return size;
1458}
1459//*****************************************************************************
1460//*****************************************************************************
1461unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1462{
1463 int idx;
1464 unsigned size = 0, modrm, reg;
1465
1466 switch (pCpu->opcode)
1467 {
1468 case 0xC0:
1469 case 0xC1:
1470 idx = (pCpu->opcode - 0xC0)*8;
1471 break;
1472
1473 case 0xD0:
1474 case 0xD1:
1475 case 0xD2:
1476 case 0xD3:
1477 idx = (pCpu->opcode - 0xD0 + 2)*8;
1478 break;
1479
1480 default:
1481 AssertMsgFailed(("Oops\n"));
1482 return sizeof(uint8_t);
1483 }
1484
1485 modrm = DISReadByte(pCpu, lpszCodeBlock);
1486 reg = MODRM_REG(modrm);
1487
1488 pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
1489
1490 //little hack to make sure the ModRM byte is included in the returned size
1491 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1492 size = sizeof(uint8_t); //ModRM byte
1493
1494 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1495
1496 return size;
1497}
1498//*****************************************************************************
1499//*****************************************************************************
1500unsigned ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1501{
1502 int idx = (pCpu->opcode - 0xF6) * 8;
1503 unsigned size = 0, modrm, reg;
1504
1505 modrm = DISReadByte(pCpu, lpszCodeBlock);
1506 reg = MODRM_REG(modrm);
1507
1508 pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
1509
1510 //little hack to make sure the ModRM byte is included in the returned size
1511 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1512 size = sizeof(uint8_t); //ModRM byte
1513
1514 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1515
1516 return size;
1517}
1518//*****************************************************************************
1519//*****************************************************************************
1520unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1521{
1522 unsigned size = 0, modrm, reg;
1523
1524 modrm = DISReadByte(pCpu, lpszCodeBlock);
1525 reg = MODRM_REG(modrm);
1526
1527 pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
1528
1529 //little hack to make sure the ModRM byte is included in the returned size
1530 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1531 size = sizeof(uint8_t); //ModRM byte
1532
1533 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1534
1535 return size;
1536}
1537//*****************************************************************************
1538//*****************************************************************************
1539unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1540{
1541 unsigned size = 0, modrm, reg;
1542
1543 modrm = DISReadByte(pCpu, lpszCodeBlock);
1544 reg = MODRM_REG(modrm);
1545
1546 pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
1547
1548 //little hack to make sure the ModRM byte is included in the returned size
1549 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1550 size = sizeof(uint8_t); //ModRM byte
1551
1552 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1553
1554 return size;
1555}
1556//*****************************************************************************
1557// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
1558// It would appear the ModRM byte must always be present. How else can you
1559// determine the offset of the imm8_opcode byte otherwise?
1560//
1561//*****************************************************************************
1562unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1563{
1564 unsigned size = 0, modrmsize;
1565
1566#ifdef DEBUG_Sander
1567 //needs testing
1568 AssertMsgFailed(("Test me\n"));
1569#endif
1570
1571 pCpu->ModRM = DISReadByte(pCpu, lpszCodeBlock);
1572
1573 modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
1574
1575 uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
1576
1577 pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
1578
1579 //little hack to make sure the ModRM byte is included in the returned size
1580 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1581 {
1582#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
1583 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
1584#endif
1585 size = sizeof(uint8_t); //ModRM byte
1586 }
1587
1588 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1589 size += sizeof(uint8_t); //imm8_opcode uint8_t
1590
1591 return size;
1592}
1593//*****************************************************************************
1594//*****************************************************************************
1595unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1596{
1597 unsigned size = 0, modrm, reg;
1598
1599 modrm = DISReadByte(pCpu, lpszCodeBlock);
1600 reg = MODRM_REG(modrm);
1601
1602 pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
1603
1604 //little hack to make sure the ModRM byte is included in the returned size
1605 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1606 size = sizeof(uint8_t); //ModRM byte
1607
1608 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1609
1610 return size;
1611}
1612//*****************************************************************************
1613//*****************************************************************************
1614unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1615{
1616 unsigned size = 0, modrm, reg, rm, mod;
1617
1618 modrm = DISReadByte(pCpu, lpszCodeBlock);
1619 mod = MODRM_MOD(modrm);
1620 reg = MODRM_REG(modrm);
1621 rm = MODRM_RM(modrm);
1622
1623 if (mod == 3 && rm == 0)
1624 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
1625 else
1626 if (mod == 3 && rm == 1)
1627 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
1628 else
1629 pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
1630
1631 //little hack to make sure the ModRM byte is included in the returned size
1632 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1633 size = sizeof(uint8_t); //ModRM byte
1634
1635 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1636
1637 return size;
1638}
1639//*****************************************************************************
1640//*****************************************************************************
1641unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1642{
1643 unsigned size = 0, modrm, reg;
1644
1645 modrm = DISReadByte(pCpu, lpszCodeBlock);
1646 reg = MODRM_REG(modrm);
1647
1648 pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
1649
1650 //little hack to make sure the ModRM byte is included in the returned size
1651 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1652 size = sizeof(uint8_t); //ModRM byte
1653
1654 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1655
1656 return size;
1657}
1658//*****************************************************************************
1659//*****************************************************************************
1660unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1661{
1662 unsigned size = 0, modrm, reg;
1663
1664 modrm = DISReadByte(pCpu, lpszCodeBlock);
1665 reg = MODRM_REG(modrm);
1666
1667 pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
1668
1669 //little hack to make sure the ModRM byte is included in the returned size
1670 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1671 size = sizeof(uint8_t); //ModRM byte
1672
1673 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1674
1675 return size;
1676}
1677//*****************************************************************************
1678//*****************************************************************************
1679unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1680{
1681 unsigned size = 0, modrm, reg;
1682
1683 modrm = DISReadByte(pCpu, lpszCodeBlock);
1684 reg = MODRM_REG(modrm);
1685
1686 pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
1687
1688 //little hack to make sure the ModRM byte is included in the returned size
1689 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1690 size = sizeof(uint8_t); //ModRM byte
1691
1692 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1693
1694 return size;
1695}
1696//*****************************************************************************
1697//*****************************************************************************
1698unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1699{
1700 unsigned size = 0, modrm, reg;
1701
1702 modrm = DISReadByte(pCpu, lpszCodeBlock);
1703 reg = MODRM_REG(modrm);
1704
1705 if (pCpu->prefix & PREFIX_OPSIZE)
1706 reg += 8; //2nd table
1707
1708 pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
1709
1710 //little hack to make sure the ModRM byte is included in the returned size
1711 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1712 size = sizeof(uint8_t); //ModRM byte
1713
1714 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1715 return size;
1716}
1717//*****************************************************************************
1718//*****************************************************************************
1719unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1720{
1721 unsigned size = 0, modrm, reg;
1722
1723 modrm = DISReadByte(pCpu, lpszCodeBlock);
1724 reg = MODRM_REG(modrm);
1725 if (pCpu->prefix & PREFIX_OPSIZE)
1726 reg += 8; //2nd table
1727
1728 pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
1729
1730 //little hack to make sure the ModRM byte is included in the returned size
1731 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1732 size = sizeof(uint8_t); //ModRM byte
1733
1734 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1735
1736 return size;
1737}
1738//*****************************************************************************
1739//*****************************************************************************
1740unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1741{
1742 unsigned size = 0, modrm, reg;
1743
1744 modrm = DISReadByte(pCpu, lpszCodeBlock);
1745 reg = MODRM_REG(modrm);
1746 if (pCpu->prefix & PREFIX_OPSIZE)
1747 reg += 8; //2nd table
1748
1749 pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
1750
1751 //little hack to make sure the ModRM byte is included in the returned size
1752 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1753 size = sizeof(uint8_t); //ModRM byte
1754
1755 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1756
1757 return size;
1758}
1759//*****************************************************************************
1760//*****************************************************************************
1761unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1762{
1763 unsigned size = 0, modrm, reg, mod, rm;
1764
1765 modrm = DISReadByte(pCpu, lpszCodeBlock);
1766 mod = MODRM_MOD(modrm);
1767 reg = MODRM_REG(modrm);
1768 rm = MODRM_RM(modrm);
1769
1770 if (mod == 3 && rm == 0)
1771 pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
1772 else
1773 pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
1774
1775 //little hack to make sure the ModRM byte is included in the returned size
1776 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1777 size = sizeof(uint8_t); //ModRM byte
1778
1779 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1780 return size;
1781}
1782//*****************************************************************************
1783//*****************************************************************************
1784unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1785{
1786 unsigned size = 0, modrm, reg;
1787
1788 modrm = DISReadByte(pCpu, lpszCodeBlock);
1789 reg = MODRM_REG(modrm);
1790
1791 pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
1792
1793 //little hack to make sure the ModRM byte is included in the returned size
1794 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1795 size = sizeof(uint8_t); //ModRM byte
1796
1797 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1798 return size;
1799}
1800//*****************************************************************************
1801const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
1802const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
1803const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
1804//*****************************************************************************
1805void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam, int fRegAddr)
1806{
1807 int subtype, type, mod;
1808
1809 mod = MODRM_MOD(pCpu->ModRM);
1810
1811 type = OP_PARM_VTYPE(pParam->param);
1812 subtype = OP_PARM_VSUBTYPE(pParam->param);
1813 if (fRegAddr)
1814 subtype = OP_PARM_d;
1815 else
1816 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
1817 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
1818
1819 switch (subtype)
1820 {
1821 case OP_PARM_b:
1822 disasmAddString(pParam->szParam, szModRMReg8[idx]);
1823 pParam->flags |= USE_REG_GEN8;
1824 pParam->base.reg_gen8 = idx;
1825 break;
1826
1827 case OP_PARM_w:
1828 disasmAddString(pParam->szParam, szModRMReg16[idx]);
1829 pParam->flags |= USE_REG_GEN16;
1830 pParam->base.reg_gen16 = idx;
1831 break;
1832
1833 case OP_PARM_d:
1834 disasmAddString(pParam->szParam, szModRMReg32[idx]);
1835 pParam->flags |= USE_REG_GEN32;
1836 pParam->base.reg_gen32 = idx;
1837 break;
1838
1839 default:
1840#ifdef IN_RING3
1841 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
1842 DIS_THROW(ExceptionInvalidModRM);
1843#else
1844 AssertMsgFailed(("Oops!\n"));
1845#endif
1846 break;
1847 }
1848}
1849//*****************************************************************************
1850const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
1851int 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};
1852int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
1853//*****************************************************************************
1854void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
1855{
1856 disasmAddString(pParam->szParam, szModRMReg1616[idx]);
1857 pParam->flags |= USE_REG_GEN16;
1858 pParam->base.reg_gen16 = BaseModRMReg16[idx];
1859 if (idx < 4)
1860 {
1861 pParam->flags |= USE_INDEX;
1862 pParam->index.reg_gen = IndexModRMReg16[idx];
1863 }
1864}
1865//*****************************************************************************
1866const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
1867//*****************************************************************************
1868void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
1869{
1870#if 0 //def DEBUG_Sander
1871 AssertMsg(idx < (int)ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
1872#endif
1873#ifdef IN_RING3
1874 if (idx >= (int)ELEMENTS(szModRMSegReg))
1875 {
1876 Log(("disasmModRMSReg %d failed!!\n", idx));
1877 DIS_THROW(ExceptionInvalidParameter);
1878 }
1879#endif
1880
1881 idx = RT_MIN(idx, (int)ELEMENTS(szModRMSegReg)-1);
1882 disasmAddString(pParam->szParam, szModRMSegReg[idx]);
1883 pParam->flags |= USE_REG_SEG;
1884 pParam->base.reg_seg = idx;
1885}
1886//*****************************************************************************
1887//*****************************************************************************
1888void disasmPrintAbs32(POP_PARAMETER pParam)
1889{
1890 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
1891}
1892//*****************************************************************************
1893//*****************************************************************************
1894void disasmPrintDisp32(POP_PARAMETER pParam)
1895{
1896 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
1897}
1898//*****************************************************************************
1899//*****************************************************************************
1900void disasmPrintDisp8(POP_PARAMETER pParam)
1901{
1902 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
1903}
1904//*****************************************************************************
1905//*****************************************************************************
1906void disasmPrintDisp16(POP_PARAMETER pParam)
1907{
1908 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
1909}
1910//*****************************************************************************
1911//*****************************************************************************
1912void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
1913{
1914 int subtype = OP_PARM_VSUBTYPE(pParam->param);
1915
1916 if (subtype == OP_PARM_v)
1917 {
1918 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
1919 }
1920
1921 switch (subtype)
1922 {
1923 case OP_PARM_a: //two words or dwords depending on operand size (bound only)
1924 break;
1925
1926 case OP_PARM_b:
1927 disasmAddString(pParam->szParam, "byte ptr ");
1928 break;
1929
1930 case OP_PARM_w:
1931 disasmAddString(pParam->szParam, "word ptr ");
1932 break;
1933
1934 case OP_PARM_d:
1935 disasmAddString(pParam->szParam, "dword ptr ");
1936 break;
1937
1938 case OP_PARM_q:
1939 case OP_PARM_dq:
1940 disasmAddString(pParam->szParam, "qword ptr ");
1941 break;
1942
1943 case OP_PARM_p:
1944 disasmAddString(pParam->szParam, "far ptr ");
1945 break;
1946
1947 case OP_PARM_s:
1948 break; //??
1949
1950 case OP_PARM_z:
1951 break;
1952 default:
1953 break; //no pointer type specified/necessary
1954 }
1955 if (pCpu->prefix & PREFIX_SEG)
1956 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->prefix_seg]);
1957}
1958#ifndef IN_GC
1959//*****************************************************************************
1960/* Read functions for getting the opcode bytes */
1961//*****************************************************************************
1962uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
1963{
1964 if (pCpu->pfnReadBytes)
1965 {
1966 uint8_t temp = 0;
1967 int rc;
1968
1969 rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
1970 if (VBOX_FAILURE(rc))
1971 {
1972 Log(("DISReadByte failed!!\n"));
1973 DIS_THROW(ExceptionMemRead);
1974 }
1975 return temp;
1976 }
1977#ifdef IN_RING0
1978 AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
1979 return 0;
1980#else
1981 else return *(uint8_t *)pAddress;
1982#endif
1983}
1984//*****************************************************************************
1985//*****************************************************************************
1986uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
1987{
1988 if (pCpu->pfnReadBytes)
1989 {
1990 uint16_t temp = 0;
1991 int rc;
1992
1993 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
1994 if (VBOX_FAILURE(rc))
1995 {
1996 Log(("DISReadWord failed!!\n"));
1997 DIS_THROW(ExceptionMemRead);
1998 }
1999 return temp;
2000 }
2001#ifdef IN_RING0
2002 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
2003 return 0;
2004#else
2005 else return *(uint16_t *)pAddress;
2006#endif
2007}
2008//*****************************************************************************
2009//*****************************************************************************
2010uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2011{
2012 if (pCpu->pfnReadBytes)
2013 {
2014 uint32_t temp = 0;
2015 int rc;
2016
2017 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2018 if (VBOX_FAILURE(rc))
2019 {
2020 Log(("DISReadDWord failed!!\n"));
2021 DIS_THROW(ExceptionMemRead);
2022 }
2023 return temp;
2024 }
2025#ifdef IN_RING0
2026 AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
2027 return 0;
2028#else
2029 else return *(uint32_t *)pAddress;
2030#endif
2031}
2032//*****************************************************************************
2033//*****************************************************************************
2034uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2035{
2036 if (pCpu->pfnReadBytes)
2037 {
2038 uint64_t temp = 0;
2039 int rc;
2040
2041 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2042 if (VBOX_FAILURE(rc))
2043 {
2044 Log(("DISReadQWord %x failed!!\n", pAddress));
2045 DIS_THROW(ExceptionMemRead);
2046 }
2047
2048 return temp;
2049 }
2050#ifdef IN_RING0
2051 AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
2052 return 0;
2053#else
2054 else return *(uint64_t *)pAddress;
2055#endif
2056}
2057#endif /* IN_GC */
2058
2059#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2060//*****************************************************************************
2061//*****************************************************************************
2062void disasmAddString(char *psz, const char *pszAdd)
2063{
2064 strcat(psz, pszAdd);
2065}
2066//*****************************************************************************
2067//*****************************************************************************
2068void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
2069{
2070 va_list args;
2071 va_start(args, pszFormat);
2072 RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
2073 va_end(args);
2074}
2075
2076//*****************************************************************************
2077//*****************************************************************************
2078void disasmAddChar(char *psz, char ch)
2079{
2080 char sz[2];
2081
2082 sz[0] = ch;
2083 sz[1] = '\0';
2084 strcat(psz, sz);
2085}
2086#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