VirtualBox

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

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

More disassembler updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 75.4 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 if (pCpu->addrmode == CPUMODE_64BIT)
1225 {
1226 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1227 /* near 64 bits pointer */
1228 /*
1229 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1230 * so we treat it like displacement.
1231 */
1232 pParam->disp64 = DISReadQWord(pCpu, lpszCodeBlock);
1233 pParam->flags |= USE_DISPLACEMENT64;
1234
1235 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64);
1236 return sizeof(uint32_t);
1237 }
1238 else
1239 {
1240 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1241 {// far 16:16 pointer
1242 pParam->parval = DISReadDWord(pCpu, lpszCodeBlock);
1243 pParam->flags |= USE_IMMEDIATE_ADDR_16_16;
1244
1245 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );
1246 return sizeof(uint32_t);
1247 }
1248 else
1249 {// near 16 bits pointer
1250 /*
1251 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1252 * so we treat it like displacement.
1253 */
1254 pParam->disp16 = DISReadWord(pCpu, lpszCodeBlock);
1255 pParam->flags |= USE_DISPLACEMENT16;
1256
1257 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "[0%04Xh]", (uint32_t)pParam->disp16);
1258 return sizeof(uint16_t);
1259 }
1260 }
1261}
1262//*****************************************************************************
1263//*****************************************************************************
1264unsigned ParseImmAddr_SizeOnly(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1265{
1266 if (pCpu->addrmode == CPUMODE_32BIT)
1267 {
1268 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1269 {// far 16:32 pointer
1270 return sizeof(uint32_t) + sizeof(uint16_t);
1271 }
1272 else
1273 {// near 32 bits pointer
1274 return sizeof(uint32_t);
1275 }
1276 }
1277 if (pCpu->addrmode == CPUMODE_64BIT)
1278 {
1279 return sizeof(uint64_t);
1280 }
1281 else
1282 {
1283 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1284 {// far 16:16 pointer
1285 return sizeof(uint32_t);
1286 }
1287 else
1288 {// near 16 bits pointer
1289 return sizeof(uint16_t);
1290 }
1291 }
1292}
1293//*****************************************************************************
1294//*****************************************************************************
1295unsigned ParseFixedReg(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1296{
1297 /*
1298 * Sets up flags for stored in OPC fixed registers.
1299 */
1300
1301 if (pParam->param == OP_PARM_NONE)
1302 {
1303 /* No parameter at all. */
1304 return 0;
1305 }
1306
1307 if (pParam->param <= OP_PARM_REG_GEN32_END)
1308 {
1309 /* 32-bit EAX..EDI registers. */
1310
1311 if (pCpu->opmode == CPUMODE_32BIT)
1312 {
1313 /* Use 32-bit registers. */
1314 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1315 pParam->flags |= USE_REG_GEN32;
1316 pParam->size = 4;
1317 }
1318 else
1319 if (pCpu->opmode == CPUMODE_64BIT)
1320 {
1321 /* Use 64-bit registers. */
1322 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1323 if ( (pCpu->prefix & PREFIX_REX)
1324 && (pCpu->prefix_rex & PREFIX_REX_FLAGS))
1325 pParam->base.reg_gen += 8;
1326
1327 pParam->flags |= USE_REG_GEN64;
1328 pParam->size = 8;
1329 }
1330 else
1331 {
1332 /* Use 16-bit registers. */
1333 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1334 pParam->flags |= USE_REG_GEN16;
1335 pParam->size = 2;
1336 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1337 }
1338 }
1339 else
1340 if (pParam->param <= OP_PARM_REG_SEG_END)
1341 {
1342 /* Segment ES..GS registers. */
1343 pParam->base.reg_seg = pParam->param - OP_PARM_REG_SEG_START;
1344 pParam->flags |= USE_REG_SEG;
1345 pParam->size = 2;
1346 }
1347 else
1348 if (pParam->param <= OP_PARM_REG_GEN16_END)
1349 {
1350 /* 16-bit AX..DI registers. */
1351 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN16_START;
1352 pParam->flags |= USE_REG_GEN16;
1353 pParam->size = 2;
1354 }
1355 else
1356 if (pParam->param <= OP_PARM_REG_GEN8_END)
1357 {
1358 /* 8-bit AL..DL, AH..DH registers. */
1359 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN8_START;
1360 pParam->flags |= USE_REG_GEN8;
1361 pParam->size = 1;
1362 }
1363 else
1364 if (pParam->param <= OP_PARM_REG_FP_END)
1365 {
1366 /* FPU registers. */
1367 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1368 pParam->flags |= USE_REG_FP;
1369 pParam->size = 10;
1370 }
1371 /* else - not supported for now registers. */
1372
1373 return 0;
1374}
1375//*****************************************************************************
1376//*****************************************************************************
1377unsigned ParseXv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1378{
1379 disasmGetPtrString(pCpu, pOp, pParam);
1380 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1381
1382 pParam->flags |= USE_POINTER_DS_BASED;
1383 if (pCpu->addrmode == CPUMODE_32BIT)
1384 {
1385 pParam->base.reg_gen = USE_REG_ESI;
1386 pParam->flags |= USE_REG_GEN32;
1387 }
1388 else
1389 if (pCpu->addrmode == CPUMODE_64BIT)
1390 {
1391 pParam->base.reg_gen = USE_REG_RSI;
1392 pParam->flags |= USE_REG_GEN64;
1393 }
1394 else
1395 {
1396 pParam->base.reg_gen = USE_REG_SI;
1397 pParam->flags |= USE_REG_GEN16;
1398 }
1399 return 0; //no additional opcode bytes
1400}
1401//*****************************************************************************
1402//*****************************************************************************
1403unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1404{
1405 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");
1406
1407 pParam->flags |= USE_POINTER_DS_BASED;
1408 if (pCpu->addrmode == CPUMODE_32BIT)
1409 {
1410 pParam->base.reg_gen = USE_REG_ESI;
1411 pParam->flags |= USE_REG_GEN32;
1412 }
1413 else
1414 if (pCpu->addrmode == CPUMODE_64BIT)
1415 {
1416 pParam->base.reg_gen = USE_REG_RSI;
1417 pParam->flags |= USE_REG_GEN64;
1418 }
1419 else
1420 {
1421 pParam->base.reg_gen = USE_REG_SI;
1422 pParam->flags |= USE_REG_GEN16;
1423 }
1424 return 0; //no additional opcode bytes
1425}
1426//*****************************************************************************
1427//*****************************************************************************
1428unsigned ParseYv(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1429{
1430 disasmGetPtrString(pCpu, pOp, pParam);
1431 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1432
1433 pParam->flags |= USE_POINTER_ES_BASED;
1434 if (pCpu->addrmode == CPUMODE_32BIT)
1435 {
1436 pParam->base.reg_gen = USE_REG_EDI;
1437 pParam->flags |= USE_REG_GEN32;
1438 }
1439 else
1440 if (pCpu->addrmode == CPUMODE_64BIT)
1441 {
1442 pParam->base.reg_gen = USE_REG_RDI;
1443 pParam->flags |= USE_REG_GEN64;
1444 }
1445 else
1446 {
1447 pParam->base.reg_gen = USE_REG_DI;
1448 pParam->flags |= USE_REG_GEN16;
1449 }
1450 return 0; //no additional opcode bytes
1451}
1452//*****************************************************************************
1453//*****************************************************************************
1454unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1455{
1456 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");
1457
1458 pParam->flags |= USE_POINTER_ES_BASED;
1459 if (pCpu->addrmode == CPUMODE_32BIT)
1460 {
1461 pParam->base.reg_gen = USE_REG_EDI;
1462 pParam->flags |= USE_REG_GEN32;
1463 }
1464 else
1465 if (pCpu->addrmode == CPUMODE_64BIT)
1466 {
1467 pParam->base.reg_gen = USE_REG_RDI;
1468 pParam->flags |= USE_REG_GEN64;
1469 }
1470 else
1471 {
1472 pParam->base.reg_gen = USE_REG_DI;
1473 pParam->flags |= USE_REG_GEN16;
1474 }
1475 return 0; //no additional opcode bytes
1476}
1477//*****************************************************************************
1478//*****************************************************************************
1479unsigned ParseTwoByteEsc(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1480{
1481 const OPCODE *pOpcode;
1482 int size = sizeof(uint8_t);
1483
1484 //2nd byte
1485 pCpu->opcode = DISReadByte(pCpu, lpszCodeBlock);
1486 pOpcode = &g_aTwoByteMapX86[pCpu->opcode];
1487
1488 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1489 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1490 if (pCpu->lastprefix)
1491 {
1492 switch (pCpu->lastprefix)
1493 {
1494 case OP_OPSIZE: /* 0x66 */
1495 if (g_aTwoByteMapX86_PF66[pCpu->opcode].opcode != OP_INVALID)
1496 {
1497 /* Table entry is valid, so use the extension table. */
1498 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->opcode];
1499
1500 /* Cancel prefix changes. */
1501 pCpu->prefix &= ~PREFIX_OPSIZE;
1502 pCpu->opmode = pCpu->mode;
1503 }
1504 break;
1505
1506 case OP_REPNE: /* 0xF2 */
1507 if (g_aTwoByteMapX86_PFF2[pCpu->opcode].opcode != OP_INVALID)
1508 {
1509 /* Table entry is valid, so use the extension table. */
1510 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->opcode];
1511
1512 /* Cancel prefix changes. */
1513 pCpu->prefix &= ~PREFIX_REPNE;
1514 }
1515 break;
1516
1517 case OP_REPE: /* 0xF3 */
1518 if (g_aTwoByteMapX86_PFF3[pCpu->opcode].opcode != OP_INVALID)
1519 {
1520 /* Table entry is valid, so use the extension table. */
1521 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->opcode];
1522
1523 /* Cancel prefix changes. */
1524 pCpu->prefix &= ~PREFIX_REP;
1525 }
1526 break;
1527 }
1528 }
1529
1530 size += ParseInstruction(lpszCodeBlock+size, pOpcode, pCpu);
1531 return size;
1532}
1533//*****************************************************************************
1534//*****************************************************************************
1535unsigned ParseNopPause(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1536{
1537 unsigned size = 0;
1538
1539 if (pCpu->prefix & PREFIX_REP)
1540 {
1541 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1542 pCpu->prefix &= ~PREFIX_REP;
1543 }
1544 else
1545 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1546
1547 size += ParseInstruction(pu8CodeBlock, pOp, pCpu);
1548 return size;
1549}
1550//*****************************************************************************
1551//*****************************************************************************
1552unsigned ParseImmGrpl(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1553{
1554 int idx = (pCpu->opcode - 0x80) * 8;
1555 unsigned size = 0, modrm, reg;
1556
1557 modrm = DISReadByte(pCpu, lpszCodeBlock);
1558 reg = MODRM_REG(modrm);
1559
1560 pOp = (PCOPCODE)&g_aMapX86_Group1[idx+reg];
1561 //little hack to make sure the ModRM byte is included in the returned size
1562 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1563 size = sizeof(uint8_t); //ModRM byte
1564
1565 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1566
1567 return size;
1568}
1569//*****************************************************************************
1570//*****************************************************************************
1571unsigned ParseShiftGrp2(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1572{
1573 int idx;
1574 unsigned size = 0, modrm, reg;
1575
1576 switch (pCpu->opcode)
1577 {
1578 case 0xC0:
1579 case 0xC1:
1580 idx = (pCpu->opcode - 0xC0)*8;
1581 break;
1582
1583 case 0xD0:
1584 case 0xD1:
1585 case 0xD2:
1586 case 0xD3:
1587 idx = (pCpu->opcode - 0xD0 + 2)*8;
1588 break;
1589
1590 default:
1591 AssertMsgFailed(("Oops\n"));
1592 return sizeof(uint8_t);
1593 }
1594
1595 modrm = DISReadByte(pCpu, lpszCodeBlock);
1596 reg = MODRM_REG(modrm);
1597
1598 pOp = (PCOPCODE)&g_aMapX86_Group2[idx+reg];
1599
1600 //little hack to make sure the ModRM byte is included in the returned size
1601 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1602 size = sizeof(uint8_t); //ModRM byte
1603
1604 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1605
1606 return size;
1607}
1608//*****************************************************************************
1609//*****************************************************************************
1610unsigned ParseGrp3(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1611{
1612 int idx = (pCpu->opcode - 0xF6) * 8;
1613 unsigned size = 0, modrm, reg;
1614
1615 modrm = DISReadByte(pCpu, lpszCodeBlock);
1616 reg = MODRM_REG(modrm);
1617
1618 pOp = (PCOPCODE)&g_aMapX86_Group3[idx+reg];
1619
1620 //little hack to make sure the ModRM byte is included in the returned size
1621 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1622 size = sizeof(uint8_t); //ModRM byte
1623
1624 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1625
1626 return size;
1627}
1628//*****************************************************************************
1629//*****************************************************************************
1630unsigned ParseGrp4(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1631{
1632 unsigned size = 0, modrm, reg;
1633
1634 modrm = DISReadByte(pCpu, lpszCodeBlock);
1635 reg = MODRM_REG(modrm);
1636
1637 pOp = (PCOPCODE)&g_aMapX86_Group4[reg];
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 size = sizeof(uint8_t); //ModRM byte
1642
1643 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1644
1645 return size;
1646}
1647//*****************************************************************************
1648//*****************************************************************************
1649unsigned ParseGrp5(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1650{
1651 unsigned size = 0, modrm, reg;
1652
1653 modrm = DISReadByte(pCpu, lpszCodeBlock);
1654 reg = MODRM_REG(modrm);
1655
1656 pOp = (PCOPCODE)&g_aMapX86_Group5[reg];
1657
1658 //little hack to make sure the ModRM byte is included in the returned size
1659 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1660 size = sizeof(uint8_t); //ModRM byte
1661
1662 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1663
1664 return size;
1665}
1666//*****************************************************************************
1667// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
1668// It would appear the ModRM byte must always be present. How else can you
1669// determine the offset of the imm8_opcode byte otherwise?
1670//
1671//*****************************************************************************
1672unsigned Parse3DNow(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1673{
1674 unsigned size = 0, modrmsize;
1675
1676#ifdef DEBUG_Sander
1677 //needs testing
1678 AssertMsgFailed(("Test me\n"));
1679#endif
1680
1681 unsigned ModRM = DISReadByte(pCpu, lpszCodeBlock);
1682 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1683 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1684 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1685
1686 modrmsize = QueryModRM(lpszCodeBlock+sizeof(uint8_t), pOp, pParam, pCpu);
1687
1688 uint8_t opcode = DISReadByte(pCpu, lpszCodeBlock+sizeof(uint8_t)+modrmsize);
1689
1690 pOp = (PCOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
1691
1692 //little hack to make sure the ModRM byte is included in the returned size
1693 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1694 {
1695#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
1696 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
1697#endif
1698 size = sizeof(uint8_t); //ModRM byte
1699 }
1700
1701 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1702 size += sizeof(uint8_t); //imm8_opcode uint8_t
1703
1704 return size;
1705}
1706//*****************************************************************************
1707//*****************************************************************************
1708unsigned ParseGrp6(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1709{
1710 unsigned size = 0, modrm, reg;
1711
1712 modrm = DISReadByte(pCpu, lpszCodeBlock);
1713 reg = MODRM_REG(modrm);
1714
1715 pOp = (PCOPCODE)&g_aMapX86_Group6[reg];
1716
1717 //little hack to make sure the ModRM byte is included in the returned size
1718 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1719 size = sizeof(uint8_t); //ModRM byte
1720
1721 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1722
1723 return size;
1724}
1725//*****************************************************************************
1726//*****************************************************************************
1727unsigned ParseGrp7(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1728{
1729 unsigned size = 0, modrm, reg, rm, mod;
1730
1731 modrm = DISReadByte(pCpu, lpszCodeBlock);
1732 mod = MODRM_MOD(modrm);
1733 reg = MODRM_REG(modrm);
1734 rm = MODRM_RM(modrm);
1735
1736 if (mod == 3 && rm == 0)
1737 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
1738 else
1739 if (mod == 3 && rm == 1)
1740 pOp = (PCOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
1741 else
1742 pOp = (PCOPCODE)&g_aMapX86_Group7_mem[reg];
1743
1744 //little hack to make sure the ModRM byte is included in the returned size
1745 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1746 size = sizeof(uint8_t); //ModRM byte
1747
1748 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1749
1750 return size;
1751}
1752//*****************************************************************************
1753//*****************************************************************************
1754unsigned ParseGrp8(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1755{
1756 unsigned size = 0, modrm, reg;
1757
1758 modrm = DISReadByte(pCpu, lpszCodeBlock);
1759 reg = MODRM_REG(modrm);
1760
1761 pOp = (PCOPCODE)&g_aMapX86_Group8[reg];
1762
1763 //little hack to make sure the ModRM byte is included in the returned size
1764 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1765 size = sizeof(uint8_t); //ModRM byte
1766
1767 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1768
1769 return size;
1770}
1771//*****************************************************************************
1772//*****************************************************************************
1773unsigned ParseGrp9(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1774{
1775 unsigned size = 0, modrm, reg;
1776
1777 modrm = DISReadByte(pCpu, lpszCodeBlock);
1778 reg = MODRM_REG(modrm);
1779
1780 pOp = (PCOPCODE)&g_aMapX86_Group9[reg];
1781
1782 //little hack to make sure the ModRM byte is included in the returned size
1783 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1784 size = sizeof(uint8_t); //ModRM byte
1785
1786 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1787
1788 return size;
1789}
1790//*****************************************************************************
1791//*****************************************************************************
1792unsigned ParseGrp10(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1793{
1794 unsigned size = 0, modrm, reg;
1795
1796 modrm = DISReadByte(pCpu, lpszCodeBlock);
1797 reg = MODRM_REG(modrm);
1798
1799 pOp = (PCOPCODE)&g_aMapX86_Group10[reg];
1800
1801 //little hack to make sure the ModRM byte is included in the returned size
1802 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1803 size = sizeof(uint8_t); //ModRM byte
1804
1805 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1806
1807 return size;
1808}
1809//*****************************************************************************
1810//*****************************************************************************
1811unsigned ParseGrp12(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1812{
1813 unsigned size = 0, modrm, reg;
1814
1815 modrm = DISReadByte(pCpu, lpszCodeBlock);
1816 reg = MODRM_REG(modrm);
1817
1818 if (pCpu->prefix & PREFIX_OPSIZE)
1819 reg += 8; //2nd table
1820
1821 pOp = (PCOPCODE)&g_aMapX86_Group12[reg];
1822
1823 //little hack to make sure the ModRM byte is included in the returned size
1824 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1825 size = sizeof(uint8_t); //ModRM byte
1826
1827 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1828 return size;
1829}
1830//*****************************************************************************
1831//*****************************************************************************
1832unsigned ParseGrp13(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1833{
1834 unsigned size = 0, modrm, reg;
1835
1836 modrm = DISReadByte(pCpu, lpszCodeBlock);
1837 reg = MODRM_REG(modrm);
1838 if (pCpu->prefix & PREFIX_OPSIZE)
1839 reg += 8; //2nd table
1840
1841 pOp = (PCOPCODE)&g_aMapX86_Group13[reg];
1842
1843 //little hack to make sure the ModRM byte is included in the returned size
1844 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1845 size = sizeof(uint8_t); //ModRM byte
1846
1847 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1848
1849 return size;
1850}
1851//*****************************************************************************
1852//*****************************************************************************
1853unsigned ParseGrp14(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1854{
1855 unsigned size = 0, modrm, reg;
1856
1857 modrm = DISReadByte(pCpu, lpszCodeBlock);
1858 reg = MODRM_REG(modrm);
1859 if (pCpu->prefix & PREFIX_OPSIZE)
1860 reg += 8; //2nd table
1861
1862 pOp = (PCOPCODE)&g_aMapX86_Group14[reg];
1863
1864 //little hack to make sure the ModRM byte is included in the returned size
1865 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1866 size = sizeof(uint8_t); //ModRM byte
1867
1868 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1869
1870 return size;
1871}
1872//*****************************************************************************
1873//*****************************************************************************
1874unsigned ParseGrp15(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1875{
1876 unsigned size = 0, modrm, reg, mod, rm;
1877
1878 modrm = DISReadByte(pCpu, lpszCodeBlock);
1879 mod = MODRM_MOD(modrm);
1880 reg = MODRM_REG(modrm);
1881 rm = MODRM_RM(modrm);
1882
1883 if (mod == 3 && rm == 0)
1884 pOp = (PCOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
1885 else
1886 pOp = (PCOPCODE)&g_aMapX86_Group15_mem[reg];
1887
1888 //little hack to make sure the ModRM byte is included in the returned size
1889 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1890 size = sizeof(uint8_t); //ModRM byte
1891
1892 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1893 return size;
1894}
1895//*****************************************************************************
1896//*****************************************************************************
1897unsigned ParseGrp16(RTUINTPTR lpszCodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu)
1898{
1899 unsigned size = 0, modrm, reg;
1900
1901 modrm = DISReadByte(pCpu, lpszCodeBlock);
1902 reg = MODRM_REG(modrm);
1903
1904 pOp = (PCOPCODE)&g_aMapX86_Group16[reg];
1905
1906 //little hack to make sure the ModRM byte is included in the returned size
1907 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1908 size = sizeof(uint8_t); //ModRM byte
1909
1910 size += ParseInstruction(lpszCodeBlock, pOp, pCpu);
1911 return size;
1912}
1913//*****************************************************************************
1914#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
1915const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
1916const char *szModRMReg8_64[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8L", "R9L", "R10L", "R11L", "R12L", "R13L", "R14L", "R15L"};
1917const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
1918const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
1919const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
1920const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
1921#endif
1922const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
1923const 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};
1924const int IndexModRMReg16[4] = { USE_REG_SI, USE_REG_DI, USE_REG_SI, USE_REG_DI};
1925//*****************************************************************************
1926void disasmModRMReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam, int fRegAddr)
1927{
1928 int subtype, type, mod;
1929
1930 mod = pCpu->ModRM.Bits.Mod;
1931
1932 type = OP_PARM_VTYPE(pParam->param);
1933 subtype = OP_PARM_VSUBTYPE(pParam->param);
1934 if (fRegAddr)
1935 subtype = OP_PARM_d;
1936 else
1937 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
1938 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
1939
1940 switch (subtype)
1941 {
1942 case OP_PARM_b:
1943 disasmAddString(pParam->szParam, szModRMReg8[idx]);
1944 pParam->flags |= USE_REG_GEN8;
1945 pParam->base.reg_gen = idx;
1946 break;
1947
1948 case OP_PARM_w:
1949 disasmAddString(pParam->szParam, szModRMReg16[idx]);
1950 pParam->flags |= USE_REG_GEN16;
1951 pParam->base.reg_gen = idx;
1952 break;
1953
1954 case OP_PARM_d:
1955 disasmAddString(pParam->szParam, szModRMReg32[idx]);
1956 pParam->flags |= USE_REG_GEN32;
1957 pParam->base.reg_gen = idx;
1958 break;
1959
1960 default:
1961#ifdef IN_RING3
1962 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
1963 DIS_THROW(ExceptionInvalidModRM);
1964#else
1965 AssertMsgFailed(("Oops!\n"));
1966#endif
1967 break;
1968 }
1969}
1970//*****************************************************************************
1971//*****************************************************************************
1972void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
1973{
1974 disasmAddString(pParam->szParam, szModRMReg1616[idx]);
1975 pParam->flags |= USE_REG_GEN16;
1976 pParam->base.reg_gen = BaseModRMReg16[idx];
1977 if (idx < 4)
1978 {
1979 pParam->flags |= USE_INDEX;
1980 pParam->index.reg_gen = IndexModRMReg16[idx];
1981 }
1982}
1983//*****************************************************************************
1984//*****************************************************************************
1985void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, int idx, POP_PARAMETER pParam)
1986{
1987#if 0 //def DEBUG_Sander
1988 AssertMsg(idx < (int)ELEMENTS(szModRMSegReg), ("idx=%d\n", idx));
1989#endif
1990#ifdef IN_RING3
1991 if (idx >= (int)ELEMENTS(szModRMSegReg))
1992 {
1993 Log(("disasmModRMSReg %d failed!!\n", idx));
1994 DIS_THROW(ExceptionInvalidParameter);
1995 }
1996#endif
1997
1998 idx = RT_MIN(idx, (int)ELEMENTS(szModRMSegReg)-1);
1999 disasmAddString(pParam->szParam, szModRMSegReg[idx]);
2000 pParam->flags |= USE_REG_SEG;
2001 pParam->base.reg_seg = idx;
2002}
2003//*****************************************************************************
2004//*****************************************************************************
2005void disasmPrintAbs32(POP_PARAMETER pParam)
2006{
2007 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2008}
2009//*****************************************************************************
2010//*****************************************************************************
2011void disasmPrintDisp32(POP_PARAMETER pParam)
2012{
2013 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%08Xh", pParam->disp32);
2014}
2015//*****************************************************************************
2016//*****************************************************************************
2017void disasmPrintDisp8(POP_PARAMETER pParam)
2018{
2019 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%d", pParam->disp8);
2020}
2021//*****************************************************************************
2022//*****************************************************************************
2023void disasmPrintDisp16(POP_PARAMETER pParam)
2024{
2025 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%04Xh", pParam->disp16);
2026}
2027//*****************************************************************************
2028//*****************************************************************************
2029void disasmGetPtrString(PDISCPUSTATE pCpu, PCOPCODE pOp, POP_PARAMETER pParam)
2030{
2031 int subtype = OP_PARM_VSUBTYPE(pParam->param);
2032
2033 if (subtype == OP_PARM_v)
2034 {
2035 subtype = (pCpu->opmode == CPUMODE_32BIT) ? OP_PARM_d : OP_PARM_w;
2036 }
2037
2038 switch (subtype)
2039 {
2040 case OP_PARM_a: //two words or dwords depending on operand size (bound only)
2041 break;
2042
2043 case OP_PARM_b:
2044 disasmAddString(pParam->szParam, "byte ptr ");
2045 break;
2046
2047 case OP_PARM_w:
2048 disasmAddString(pParam->szParam, "word ptr ");
2049 break;
2050
2051 case OP_PARM_d:
2052 disasmAddString(pParam->szParam, "dword ptr ");
2053 break;
2054
2055 case OP_PARM_q:
2056 case OP_PARM_dq:
2057 disasmAddString(pParam->szParam, "qword ptr ");
2058 break;
2059
2060 case OP_PARM_p:
2061 disasmAddString(pParam->szParam, "far ptr ");
2062 break;
2063
2064 case OP_PARM_s:
2065 break; //??
2066
2067 case OP_PARM_z:
2068 break;
2069 default:
2070 break; //no pointer type specified/necessary
2071 }
2072 if (pCpu->prefix & PREFIX_SEG)
2073 disasmAddStringF(pParam->szParam, sizeof(pParam->szParam), "%s:", szModRMSegReg[pCpu->prefix_seg]);
2074}
2075#ifndef IN_GC
2076//*****************************************************************************
2077/* Read functions for getting the opcode bytes */
2078//*****************************************************************************
2079uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2080{
2081 if (pCpu->pfnReadBytes)
2082 {
2083 uint8_t temp = 0;
2084 int rc;
2085
2086 rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu);
2087 if (VBOX_FAILURE(rc))
2088 {
2089 Log(("DISReadByte failed!!\n"));
2090 DIS_THROW(ExceptionMemRead);
2091 }
2092 return temp;
2093 }
2094#ifdef IN_RING0
2095 AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n"));
2096 return 0;
2097#else
2098 else return *(uint8_t *)pAddress;
2099#endif
2100}
2101//*****************************************************************************
2102//*****************************************************************************
2103uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2104{
2105 if (pCpu->pfnReadBytes)
2106 {
2107 uint16_t temp = 0;
2108 int rc;
2109
2110 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2111 if (VBOX_FAILURE(rc))
2112 {
2113 Log(("DISReadWord failed!!\n"));
2114 DIS_THROW(ExceptionMemRead);
2115 }
2116 return temp;
2117 }
2118#ifdef IN_RING0
2119 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n"));
2120 return 0;
2121#else
2122 else return *(uint16_t *)pAddress;
2123#endif
2124}
2125//*****************************************************************************
2126//*****************************************************************************
2127uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2128{
2129 if (pCpu->pfnReadBytes)
2130 {
2131 uint32_t temp = 0;
2132 int rc;
2133
2134 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2135 if (VBOX_FAILURE(rc))
2136 {
2137 Log(("DISReadDWord failed!!\n"));
2138 DIS_THROW(ExceptionMemRead);
2139 }
2140 return temp;
2141 }
2142#ifdef IN_RING0
2143 AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n"));
2144 return 0;
2145#else
2146 else return *(uint32_t *)pAddress;
2147#endif
2148}
2149//*****************************************************************************
2150//*****************************************************************************
2151uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress)
2152{
2153 if (pCpu->pfnReadBytes)
2154 {
2155 uint64_t temp = 0;
2156 int rc;
2157
2158 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu);
2159 if (VBOX_FAILURE(rc))
2160 {
2161 Log(("DISReadQWord %x failed!!\n", pAddress));
2162 DIS_THROW(ExceptionMemRead);
2163 }
2164
2165 return temp;
2166 }
2167#ifdef IN_RING0
2168 AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n"));
2169 return 0;
2170#else
2171 else return *(uint64_t *)pAddress;
2172#endif
2173}
2174#endif /* IN_GC */
2175
2176#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2177//*****************************************************************************
2178//*****************************************************************************
2179void disasmAddString(char *psz, const char *pszAdd)
2180{
2181 strcat(psz, pszAdd);
2182}
2183//*****************************************************************************
2184//*****************************************************************************
2185void disasmAddStringF(char *psz, uint32_t size, const char *pszFormat, ...)
2186{
2187 va_list args;
2188 va_start(args, pszFormat);
2189 RTStrPrintfV(psz + strlen(psz), size, pszFormat, args);
2190 va_end(args);
2191}
2192
2193//*****************************************************************************
2194//*****************************************************************************
2195void disasmAddChar(char *psz, char ch)
2196{
2197 char sz[2];
2198
2199 sz[0] = ch;
2200 sz[1] = '\0';
2201 strcat(psz, sz);
2202}
2203#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