VirtualBox

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

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

The Big Sun Rebranding Header Change

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

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