VirtualBox

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

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

Some updates for 64 bits disassembly

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