VirtualBox

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

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

Disassembler updates for 64 bits support

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