VirtualBox

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

Last change on this file since 41737 was 41737, checked in by vboxsync, 12 years ago

DISOPCODE: s/opcode/uOpcode/

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.9 KB
Line 
1/* $Id: DisasmCore.cpp 41737 2012-06-15 01:01:49Z vboxsync $ */
2/** @file
3 * VBox Disassembler - Core Components.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DIS
23#include <VBox/dis.h>
24#include <VBox/disopcode.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <iprt/assert.h>
28#include <iprt/string.h>
29#include <iprt/stdarg.h>
30#include "DisasmInternal.h"
31
32
33/*******************************************************************************
34* Internal Functions *
35*******************************************************************************/
36static int disInstrWorker(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr);
37static unsigned disParseInstruction(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISCPUSTATE pCpu);
38
39static unsigned QueryModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
40static unsigned QueryModRM_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc = NULL);
41static void UseSIB(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
42static unsigned ParseSIB_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu);
43
44static void disasmModRMReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam, int fRegAddr);
45static void disasmModRMReg16(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam);
46static void disasmModRMSReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam);
47
48static void disValidateLockSequence(PDISCPUSTATE pCpu);
49
50/* Read functions */
51static uint8_t disReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
52static uint16_t disReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
53static uint32_t disReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
54static uint64_t disReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress);
55static DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead);
56
57
58/** @name Parsers
59 * @{ */
60static FNDISPARSE ParseIllegal;
61static FNDISPARSE ParseModRM;
62static FNDISPARSE ParseModRM_SizeOnly;
63static FNDISPARSE UseModRM;
64static FNDISPARSE ParseImmByte;
65static FNDISPARSE ParseImmByte_SizeOnly;
66static FNDISPARSE ParseImmByteSX;
67static FNDISPARSE ParseImmByteSX_SizeOnly;
68static FNDISPARSE ParseImmBRel;
69static FNDISPARSE ParseImmBRel_SizeOnly;
70static FNDISPARSE ParseImmUshort;
71static FNDISPARSE ParseImmUshort_SizeOnly;
72static FNDISPARSE ParseImmV;
73static FNDISPARSE ParseImmV_SizeOnly;
74static FNDISPARSE ParseImmVRel;
75static FNDISPARSE ParseImmVRel_SizeOnly;
76static FNDISPARSE ParseImmZ;
77static FNDISPARSE ParseImmZ_SizeOnly;
78
79static FNDISPARSE ParseImmAddr;
80static FNDISPARSE ParseImmAddr_SizeOnly;
81static FNDISPARSE ParseImmAddrF;
82static FNDISPARSE ParseImmAddrF_SizeOnly;
83static FNDISPARSE ParseFixedReg;
84static FNDISPARSE ParseImmUlong;
85static FNDISPARSE ParseImmUlong_SizeOnly;
86static FNDISPARSE ParseImmQword;
87static FNDISPARSE ParseImmQword_SizeOnly;
88
89static FNDISPARSE ParseTwoByteEsc;
90static FNDISPARSE ParseThreeByteEsc4;
91static FNDISPARSE ParseThreeByteEsc5;
92static FNDISPARSE ParseImmGrpl;
93static FNDISPARSE ParseShiftGrp2;
94static FNDISPARSE ParseGrp3;
95static FNDISPARSE ParseGrp4;
96static FNDISPARSE ParseGrp5;
97static FNDISPARSE Parse3DNow;
98static FNDISPARSE ParseGrp6;
99static FNDISPARSE ParseGrp7;
100static FNDISPARSE ParseGrp8;
101static FNDISPARSE ParseGrp9;
102static FNDISPARSE ParseGrp10;
103static FNDISPARSE ParseGrp12;
104static FNDISPARSE ParseGrp13;
105static FNDISPARSE ParseGrp14;
106static FNDISPARSE ParseGrp15;
107static FNDISPARSE ParseGrp16;
108static FNDISPARSE ParseModFence;
109static FNDISPARSE ParseNopPause;
110
111static FNDISPARSE ParseYv;
112static FNDISPARSE ParseYb;
113static FNDISPARSE ParseXv;
114static FNDISPARSE ParseXb;
115
116/** Floating point parsing */
117static FNDISPARSE ParseEscFP;
118/** @} */
119
120
121/*******************************************************************************
122* Global Variables *
123*******************************************************************************/
124/** Parser opcode table for full disassembly. */
125static PFNDISPARSE const g_apfnFullDisasm[IDX_ParseMax] =
126{
127 ParseIllegal,
128 ParseModRM,
129 UseModRM,
130 ParseImmByte,
131 ParseImmBRel,
132 ParseImmUshort,
133 ParseImmV,
134 ParseImmVRel,
135 ParseImmAddr,
136 ParseFixedReg,
137 ParseImmUlong,
138 ParseImmQword,
139 ParseTwoByteEsc,
140 ParseImmGrpl,
141 ParseShiftGrp2,
142 ParseGrp3,
143 ParseGrp4,
144 ParseGrp5,
145 Parse3DNow,
146 ParseGrp6,
147 ParseGrp7,
148 ParseGrp8,
149 ParseGrp9,
150 ParseGrp10,
151 ParseGrp12,
152 ParseGrp13,
153 ParseGrp14,
154 ParseGrp15,
155 ParseGrp16,
156 ParseModFence,
157 ParseYv,
158 ParseYb,
159 ParseXv,
160 ParseXb,
161 ParseEscFP,
162 ParseNopPause,
163 ParseImmByteSX,
164 ParseImmZ,
165 ParseThreeByteEsc4,
166 ParseThreeByteEsc5,
167 ParseImmAddrF
168};
169
170/** Parser opcode table for only calculating instruction size. */
171static PFNDISPARSE const g_apfnCalcSize[IDX_ParseMax] =
172{
173 ParseIllegal,
174 ParseModRM_SizeOnly,
175 UseModRM,
176 ParseImmByte_SizeOnly,
177 ParseImmBRel_SizeOnly,
178 ParseImmUshort_SizeOnly,
179 ParseImmV_SizeOnly,
180 ParseImmVRel_SizeOnly,
181 ParseImmAddr_SizeOnly,
182 ParseFixedReg,
183 ParseImmUlong_SizeOnly,
184 ParseImmQword_SizeOnly,
185 ParseTwoByteEsc,
186 ParseImmGrpl,
187 ParseShiftGrp2,
188 ParseGrp3,
189 ParseGrp4,
190 ParseGrp5,
191 Parse3DNow,
192 ParseGrp6,
193 ParseGrp7,
194 ParseGrp8,
195 ParseGrp9,
196 ParseGrp10,
197 ParseGrp12,
198 ParseGrp13,
199 ParseGrp14,
200 ParseGrp15,
201 ParseGrp16,
202 ParseModFence,
203 ParseYv,
204 ParseYb,
205 ParseXv,
206 ParseXb,
207 ParseEscFP,
208 ParseNopPause,
209 ParseImmByteSX_SizeOnly,
210 ParseImmZ_SizeOnly,
211 ParseThreeByteEsc4,
212 ParseThreeByteEsc5,
213 ParseImmAddrF_SizeOnly
214};
215
216
217/**
218 * Parses one guest instruction.
219 *
220 * The result is found in pCpu and pcbInstr.
221 *
222 * @returns VBox status code.
223 * @param pvInstr Address of the instruction to decode. This is a
224 * real address in the current context that can be
225 * accessed without faulting. (Consider
226 * DISInstrWithReader if this isn't the case.)
227 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
228 * @param pfnReadBytes Callback for reading instruction bytes.
229 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
230 * @param pCpu Pointer to cpu structure. Will be initialized.
231 * @param pcbInstr Where to store the size of the instruction.
232 * NULL is allowed. This is also stored in
233 * PDISCPUSTATE::cbInstr.
234 */
235DISDECL(int) DISInstr(const void *pvInstr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbInstr)
236{
237 return DISInstEx((uintptr_t)pvInstr, enmCpuMode, DISOPTYPE_ALL, NULL /*pfnReadBytes*/, NULL /*pvUser*/, pCpu, pcbInstr);
238}
239
240
241/**
242 * Parses one guest instruction.
243 *
244 * The result is found in pCpu and pcbInstr.
245 *
246 * @returns VBox status code.
247 * @param uInstrAddr Address of the instruction to decode. What this means
248 * is left to the pfnReadBytes function.
249 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
250 * @param pfnReadBytes Callback for reading instruction bytes.
251 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
252 * @param pCpu Pointer to cpu structure. Will be initialized.
253 * @param pcbInstr Where to store the size of the instruction.
254 * NULL is allowed. This is also stored in
255 * PDISCPUSTATE::cbInstr.
256 */
257DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
258 PDISCPUSTATE pCpu, uint32_t *pcbInstr)
259{
260 return DISInstEx(uInstrAddr, enmCpuMode, DISOPTYPE_ALL, pfnReadBytes, pvUser, pCpu, pcbInstr);
261}
262
263
264/**
265 * Disassembles on instruction, details in @a pCpu and length in @a pcbInstr.
266 *
267 * @returns VBox status code.
268 * @param uInstrAddr Address of the instruction to decode. What this means
269 * is left to the pfnReadBytes function.
270 * @param enmCpuMode The CPU mode. DISCPUMODE_32BIT, DISCPUMODE_16BIT, or DISCPUMODE_64BIT.
271 * @param pfnReadBytes Callback for reading instruction bytes.
272 * @param fFilter Instruction type filter.
273 * @param pvUser User argument for the instruction reader. (Ends up in pvUser.)
274 * @param pCpu Pointer to CPU structure. With the exception of
275 * DISCPUSTATE::pvUser2, the structure will be
276 * completely initialized by this API, i.e. no input is
277 * taken from it.
278 * @param pcbInstr Where to store the size of the instruction. (This
279 * is also stored in PDISCPUSTATE::cbInstr.) Optional.
280 */
281DISDECL(int) DISInstEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
282 PFNDISREADBYTES pfnReadBytes, void *pvUser,
283 PDISCPUSTATE pCpu, uint32_t *pcbInstr)
284{
285 PCDISOPCODE paOneByteMap;
286
287 /*
288 * Initialize the CPU state.
289 * Note! The RT_BZERO make ASSUMPTIONS about the placement of pvUser2.
290 */
291 RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, pvUser2));
292
293 pCpu->uCpuMode = enmCpuMode;
294 if (enmCpuMode == DISCPUMODE_64BIT)
295 {
296 paOneByteMap = g_aOneByteMapX64;
297 pCpu->uAddrMode = DISCPUMODE_64BIT;
298 pCpu->uOpMode = DISCPUMODE_32BIT;
299 }
300 else
301 {
302 paOneByteMap = g_aOneByteMapX86;
303 pCpu->uAddrMode = enmCpuMode;
304 pCpu->uOpMode = enmCpuMode;
305 }
306 pCpu->fPrefix = DISPREFIX_NONE;
307 pCpu->idxSegPrefix = DISSELREG_DS;
308 pCpu->uInstrAddr = uInstrAddr;
309 pCpu->pfnDisasmFnTable = g_apfnFullDisasm;
310 pCpu->fFilter = fFilter;
311 pCpu->rc = VINF_SUCCESS;
312 pCpu->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault;
313 pCpu->pvUser = pvUser;
314
315 return disInstrWorker(pCpu, uInstrAddr, paOneByteMap, pcbInstr);
316}
317
318
319/**
320 * Internal worker for DISInstEx.
321 *
322 * @returns VBox status code.
323 * @param pCpu Initialized cpu state.
324 * @param paOneByteMap The one byte opcode map to use.
325 * @param uInstrAddr Instruction address.
326 * @param pcbInstr Where to store the instruction size. Can be NULL.
327 */
328static int disInstrWorker(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
329{
330 /*
331 * Parse byte by byte.
332 */
333 unsigned iByte = 0;
334 unsigned cbInc;
335 for (;;)
336 {
337 uint8_t codebyte = disReadByte(pCpu, uInstrAddr+iByte);
338 uint8_t opcode = paOneByteMap[codebyte].uOpcode;
339
340 /* Hardcoded assumption about OP_* values!! */
341 if (opcode <= OP_LAST_PREFIX)
342 {
343 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */
344 if (opcode != OP_REX)
345 {
346 /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */
347 pCpu->bLastPrefix = opcode;
348 pCpu->fPrefix &= ~DISPREFIX_REX;
349 }
350
351 switch (opcode)
352 {
353 case OP_INVALID:
354 if (pcbInstr)
355 *pcbInstr = iByte + 1;
356 return pCpu->rc = VERR_DIS_INVALID_OPCODE;
357
358 // segment override prefix byte
359 case OP_SEG:
360 pCpu->idxSegPrefix = (DISSELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START);
361 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */
362 if ( pCpu->uCpuMode != DISCPUMODE_64BIT
363 || pCpu->idxSegPrefix >= DISSELREG_FS)
364 {
365 pCpu->fPrefix |= DISPREFIX_SEG;
366 }
367 iByte += sizeof(uint8_t);
368 continue; //fetch the next byte
369
370 // lock prefix byte
371 case OP_LOCK:
372 pCpu->fPrefix |= DISPREFIX_LOCK;
373 iByte += sizeof(uint8_t);
374 continue; //fetch the next byte
375
376 // address size override prefix byte
377 case OP_ADDRSIZE:
378 pCpu->fPrefix |= DISPREFIX_ADDRSIZE;
379 if (pCpu->uCpuMode == DISCPUMODE_16BIT)
380 pCpu->uAddrMode = DISCPUMODE_32BIT;
381 else
382 if (pCpu->uCpuMode == DISCPUMODE_32BIT)
383 pCpu->uAddrMode = DISCPUMODE_16BIT;
384 else
385 pCpu->uAddrMode = DISCPUMODE_32BIT; /* 64 bits */
386
387 iByte += sizeof(uint8_t);
388 continue; //fetch the next byte
389
390 // operand size override prefix byte
391 case OP_OPSIZE:
392 pCpu->fPrefix |= DISPREFIX_OPSIZE;
393 if (pCpu->uCpuMode == DISCPUMODE_16BIT)
394 pCpu->uOpMode = DISCPUMODE_32BIT;
395 else
396 pCpu->uOpMode = DISCPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */
397
398 iByte += sizeof(uint8_t);
399 continue; //fetch the next byte
400
401 // rep and repne are not really prefixes, but we'll treat them as such
402 case OP_REPE:
403 pCpu->fPrefix |= DISPREFIX_REP;
404 iByte += sizeof(uint8_t);
405 continue; //fetch the next byte
406
407 case OP_REPNE:
408 pCpu->fPrefix |= DISPREFIX_REPNE;
409 iByte += sizeof(uint8_t);
410 continue; //fetch the next byte
411
412 case OP_REX:
413 Assert(pCpu->uCpuMode == DISCPUMODE_64BIT);
414 /* REX prefix byte */
415 pCpu->fPrefix |= DISPREFIX_REX;
416 pCpu->fRexPrefix = DISPREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1);
417 iByte += sizeof(uint8_t);
418
419 if (pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_W)
420 pCpu->uOpMode = DISCPUMODE_64BIT; /* overrides size prefix byte */
421 continue; //fetch the next byte
422 }
423 }
424
425 unsigned uIdx = iByte;
426 iByte += sizeof(uint8_t); //first opcode byte
427
428 pCpu->bOpCode = codebyte;
429
430 cbInc = disParseInstruction(uInstrAddr + iByte, &paOneByteMap[pCpu->bOpCode], pCpu);
431 iByte += cbInc;
432 break;
433 }
434
435 AssertMsg(pCpu->cbInstr == iByte || RT_FAILURE_NP(pCpu->rc), ("%u %u\n", pCpu->cbInstr, iByte));
436 pCpu->cbInstr = iByte;
437 if (pcbInstr)
438 *pcbInstr = iByte;
439
440 if (pCpu->fPrefix & DISPREFIX_LOCK)
441 disValidateLockSequence(pCpu);
442
443 return pCpu->rc;
444}
445//*****************************************************************************
446//*****************************************************************************
447static unsigned disParseInstruction(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISCPUSTATE pCpu)
448{
449 int size = 0;
450 bool fFiltered = false;
451
452 Assert(uCodePtr && pOp && pCpu);
453
454 // Store the opcode format string for disasmPrintf
455 pCpu->pCurInstr = pOp;
456
457 /*
458 * Apply filter to instruction type to determine if a full disassembly is required.
459 * Note! Multibyte opcodes are always marked harmless until the final byte.
460 */
461 if ((pOp->optype & pCpu->fFilter) == 0)
462 {
463 fFiltered = true;
464 pCpu->pfnDisasmFnTable = g_apfnCalcSize;
465 }
466 else
467 {
468 /* Not filtered out -> full disassembly */
469 pCpu->pfnDisasmFnTable = g_apfnFullDisasm;
470 }
471
472 // Should contain the parameter type on input
473 pCpu->param1.param = pOp->param1;
474 pCpu->param2.param = pOp->param2;
475 pCpu->param3.param = pOp->param3;
476
477 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
478 if (pCpu->uCpuMode == DISCPUMODE_64BIT)
479 {
480 if (pOp->optype & DISOPTYPE_FORCED_64_OP_SIZE)
481 pCpu->uOpMode = DISCPUMODE_64BIT;
482 else
483 if ( (pOp->optype & DISOPTYPE_DEFAULT_64_OP_SIZE)
484 && !(pCpu->fPrefix & DISPREFIX_OPSIZE))
485 pCpu->uOpMode = DISCPUMODE_64BIT;
486 }
487 else
488 if (pOp->optype & DISOPTYPE_FORCED_32_OP_SIZE_X86)
489 {
490 /* Forced 32 bits operand size for certain instructions (mov crx, mov drx). */
491 Assert(pCpu->uCpuMode != DISCPUMODE_64BIT);
492 pCpu->uOpMode = DISCPUMODE_32BIT;
493 }
494
495 if (pOp->idxParse1 != IDX_ParseNop)
496 {
497 size += pCpu->pfnDisasmFnTable[pOp->idxParse1](uCodePtr, pOp, &pCpu->param1, pCpu);
498 if (fFiltered == false) pCpu->param1.cb = DISGetParamSize(pCpu, &pCpu->param1);
499 }
500
501 if (pOp->idxParse2 != IDX_ParseNop)
502 {
503 size += pCpu->pfnDisasmFnTable[pOp->idxParse2](uCodePtr+size, pOp, &pCpu->param2, pCpu);
504 if (fFiltered == false) pCpu->param2.cb = DISGetParamSize(pCpu, &pCpu->param2);
505 }
506
507 if (pOp->idxParse3 != IDX_ParseNop)
508 {
509 size += pCpu->pfnDisasmFnTable[pOp->idxParse3](uCodePtr+size, pOp, &pCpu->param3, pCpu);
510 if (fFiltered == false) pCpu->param3.cb = DISGetParamSize(pCpu, &pCpu->param3);
511 }
512 // else simple one byte instruction
513
514 return size;
515}
516//*****************************************************************************
517/* Floating point opcode parsing */
518//*****************************************************************************
519unsigned ParseEscFP(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
520{
521 int index;
522 PCDISOPCODE fpop;
523 unsigned size = 0;
524 unsigned ModRM;
525 NOREF(pOp);
526
527 ModRM = disReadByte(pCpu, uCodePtr);
528
529 index = pCpu->bOpCode - 0xD8;
530 if (ModRM <= 0xBF)
531 {
532 fpop = &(g_apMapX86_FP_Low[index])[MODRM_REG(ModRM)];
533 pCpu->pCurInstr = (PCDISOPCODE)fpop;
534
535 // Should contain the parameter type on input
536 pCpu->param1.param = fpop->param1;
537 pCpu->param2.param = fpop->param2;
538 }
539 else
540 {
541 fpop = &(g_apMapX86_FP_High[index])[ModRM - 0xC0];
542 pCpu->pCurInstr = (PCDISOPCODE)fpop;
543 }
544
545 /*
546 * Apply filter to instruction type to determine if a full disassembly is required.
547 * @note Multibyte opcodes are always marked harmless until the final byte.
548 */
549 if ((fpop->optype & pCpu->fFilter) == 0)
550 pCpu->pfnDisasmFnTable = g_apfnCalcSize;
551 else
552 /* Not filtered out -> full disassembly */
553 pCpu->pfnDisasmFnTable = g_apfnFullDisasm;
554
555 /* Correct the operand size if the instruction is marked as forced or default 64 bits */
556 if (pCpu->uCpuMode == DISCPUMODE_64BIT)
557 {
558 /* Note: redundant, but just in case this ever changes */
559 if (fpop->optype & DISOPTYPE_FORCED_64_OP_SIZE)
560 pCpu->uOpMode = DISCPUMODE_64BIT;
561 else
562 if ( (fpop->optype & DISOPTYPE_DEFAULT_64_OP_SIZE)
563 && !(pCpu->fPrefix & DISPREFIX_OPSIZE))
564 pCpu->uOpMode = DISCPUMODE_64BIT;
565 }
566
567 // Little hack to make sure the ModRM byte is included in the returned size
568 if (fpop->idxParse1 != IDX_ParseModRM && fpop->idxParse2 != IDX_ParseModRM)
569 size = sizeof(uint8_t); //ModRM byte
570
571 if (fpop->idxParse1 != IDX_ParseNop)
572 size += pCpu->pfnDisasmFnTable[fpop->idxParse1](uCodePtr+size, (PCDISOPCODE)fpop, pParam, pCpu);
573
574 if (fpop->idxParse2 != IDX_ParseNop)
575 size += pCpu->pfnDisasmFnTable[fpop->idxParse2](uCodePtr+size, (PCDISOPCODE)fpop, pParam, pCpu);
576
577 return size;
578}
579//*****************************************************************************
580// SIB byte: (32 bits mode only)
581// 7 - 6 5 - 3 2-0
582// Scale Index Base
583//*****************************************************************************
584static const char *szSIBBaseReg[8] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
585static const char *szSIBIndexReg[8] = {"EAX", "ECX", "EDX", "EBX", NULL, "EBP", "ESI", "EDI"};
586static const char *szSIBBaseReg64[16] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
587static const char *szSIBIndexReg64[16]= {"RAX", "RCX", "RDX", "RBX", NULL, "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
588#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED) || defined(_MSC_VER)
589static const char *szSIBScale[4] = {"", "*2", "*4", "*8"};
590#endif
591//*****************************************************************************
592void UseSIB(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
593{
594 unsigned scale, base, index, regtype;
595 const char **ppszSIBIndexReg;
596 const char **ppszSIBBaseReg;
597 NOREF(uCodePtr); NOREF(pOp);
598
599 scale = pCpu->SIB.Bits.Scale;
600 base = pCpu->SIB.Bits.Base;
601 index = pCpu->SIB.Bits.Index;
602
603 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
604 {
605 ppszSIBIndexReg = szSIBIndexReg;
606 ppszSIBBaseReg = szSIBBaseReg;
607 regtype = DISUSE_REG_GEN32;
608 }
609 else
610 {
611 ppszSIBIndexReg = szSIBIndexReg64;
612 ppszSIBBaseReg = szSIBBaseReg64;
613 regtype = DISUSE_REG_GEN64;
614 }
615
616 if (ppszSIBIndexReg[index])
617 {
618 pParam->fUse |= DISUSE_INDEX | regtype;
619 pParam->index.reg_gen = index;
620
621 if (scale != 0)
622 {
623 pParam->fUse |= DISUSE_SCALE;
624 pParam->scale = (1<<scale);
625 }
626 }
627
628 if (base == 5 && pCpu->ModRM.Bits.Mod == 0)
629 {
630 // [scaled index] + disp32
631 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
632 {
633 pParam->fUse |= DISUSE_DISPLACEMENT32;
634 pParam->uDisp.i32 = pCpu->i32SibDisp;
635 }
636 else
637 { /* sign-extend to 64 bits */
638 pParam->fUse |= DISUSE_DISPLACEMENT64;
639 pParam->uDisp.i64 = pCpu->i32SibDisp;
640 }
641 }
642 else
643 {
644 pParam->fUse |= DISUSE_BASE | regtype;
645 pParam->base.reg_gen = base;
646 }
647 return; /* Already fetched everything in ParseSIB; no size returned */
648}
649//*****************************************************************************
650//*****************************************************************************
651unsigned ParseSIB(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
652{
653 unsigned size = sizeof(uint8_t);
654 unsigned SIB;
655 NOREF(pOp); NOREF(pParam);
656
657 SIB = disReadByte(pCpu, uCodePtr);
658 uCodePtr += size;
659
660 pCpu->SIB.Bits.Base = SIB_BASE(SIB);
661 pCpu->SIB.Bits.Index = SIB_INDEX(SIB);
662 pCpu->SIB.Bits.Scale = SIB_SCALE(SIB);
663
664 if (pCpu->fPrefix & DISPREFIX_REX)
665 {
666 /* REX.B extends the Base field if not scaled index + disp32 */
667 if (!(pCpu->SIB.Bits.Base == 5 && pCpu->ModRM.Bits.Mod == 0))
668 pCpu->SIB.Bits.Base |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
669
670 pCpu->SIB.Bits.Index |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
671 }
672
673 if ( pCpu->SIB.Bits.Base == 5
674 && pCpu->ModRM.Bits.Mod == 0)
675 {
676 /* Additional 32 bits displacement. No change in long mode. */
677 pCpu->i32SibDisp = disReadDWord(pCpu, uCodePtr);
678 size += sizeof(int32_t);
679 }
680 return size;
681}
682//*****************************************************************************
683//*****************************************************************************
684unsigned ParseSIB_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
685{
686 unsigned size = sizeof(uint8_t);
687 unsigned SIB;
688 NOREF(pOp); NOREF(pParam);
689
690 SIB = disReadByte(pCpu, uCodePtr);
691 uCodePtr += size;
692
693 pCpu->SIB.Bits.Base = SIB_BASE(SIB);
694 pCpu->SIB.Bits.Index = SIB_INDEX(SIB);
695 pCpu->SIB.Bits.Scale = SIB_SCALE(SIB);
696
697 if (pCpu->fPrefix & DISPREFIX_REX)
698 {
699 /* REX.B extends the Base field. */
700 pCpu->SIB.Bits.Base |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
701 /* REX.X extends the Index field. */
702 pCpu->SIB.Bits.Index |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_X)) << 3);
703 }
704
705 if ( pCpu->SIB.Bits.Base == 5
706 && pCpu->ModRM.Bits.Mod == 0)
707 {
708 /* Additional 32 bits displacement. No change in long mode. */
709 size += sizeof(int32_t);
710 }
711 return size;
712}
713//*****************************************************************************
714// ModR/M byte:
715// 7 - 6 5 - 3 2-0
716// Mod Reg/Opcode R/M
717//*****************************************************************************
718unsigned UseModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
719{
720 int vtype = OP_PARM_VTYPE(pParam->param);
721 unsigned reg = pCpu->ModRM.Bits.Reg;
722 unsigned mod = pCpu->ModRM.Bits.Mod;
723 unsigned rm = pCpu->ModRM.Bits.Rm;
724
725 switch (vtype)
726 {
727 case OP_PARM_G: //general purpose register
728 disasmModRMReg(pCpu, pOp, reg, pParam, 0);
729 return 0;
730
731 default:
732 if (IS_OP_PARM_RARE(vtype))
733 {
734 switch (vtype)
735 {
736 case OP_PARM_C: //control register
737 pParam->fUse |= DISUSE_REG_CR;
738
739 if ( pCpu->pCurInstr->uOpcode == OP_MOV_CR
740 && pCpu->uOpMode == DISCPUMODE_32BIT
741 && (pCpu->fPrefix & DISPREFIX_LOCK))
742 {
743 pCpu->fPrefix &= ~DISPREFIX_LOCK;
744 pParam->base.reg_ctrl = DISCREG_CR8;
745 }
746 else
747 pParam->base.reg_ctrl = reg;
748 return 0;
749
750 case OP_PARM_D: //debug register
751 pParam->fUse |= DISUSE_REG_DBG;
752 pParam->base.reg_dbg = reg;
753 return 0;
754
755 case OP_PARM_P: //MMX register
756 reg &= 7; /* REX.R has no effect here */
757 pParam->fUse |= DISUSE_REG_MMX;
758 pParam->base.reg_mmx = reg;
759 return 0;
760
761 case OP_PARM_S: //segment register
762 reg &= 7; /* REX.R has no effect here */
763 disasmModRMSReg(pCpu, pOp, reg, pParam);
764 pParam->fUse |= DISUSE_REG_SEG;
765 return 0;
766
767 case OP_PARM_T: //test register
768 reg &= 7; /* REX.R has no effect here */
769 pParam->fUse |= DISUSE_REG_TEST;
770 pParam->base.reg_test = reg;
771 return 0;
772
773 case OP_PARM_W: //XMM register or memory operand
774 if (mod != 3)
775 break; /* memory operand */
776 reg = rm; /* the RM field specifies the xmm register */
777 /* else no break */
778
779 case OP_PARM_V: //XMM register
780 pParam->fUse |= DISUSE_REG_XMM;
781 pParam->base.reg_xmm = reg;
782 return 0;
783 }
784 }
785 }
786
787 /* @todo bound */
788
789 if (pCpu->uAddrMode != DISCPUMODE_16BIT)
790 {
791 Assert(pCpu->uAddrMode == DISCPUMODE_32BIT || pCpu->uAddrMode == DISCPUMODE_64BIT);
792
793 /*
794 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
795 */
796 switch (mod)
797 {
798 case 0: //effective address
799 if (rm == 4)
800 { /* SIB byte follows ModRM */
801 UseSIB(uCodePtr, pOp, pParam, pCpu);
802 }
803 else
804 if (rm == 5)
805 {
806 /* 32 bits displacement */
807 if (pCpu->uCpuMode != DISCPUMODE_64BIT)
808 {
809 pParam->fUse |= DISUSE_DISPLACEMENT32;
810 pParam->uDisp.i32 = pCpu->i32SibDisp;
811 }
812 else
813 {
814 pParam->fUse |= DISUSE_RIPDISPLACEMENT32;
815 pParam->uDisp.i32 = pCpu->i32SibDisp;
816 }
817 }
818 else
819 { //register address
820 pParam->fUse |= DISUSE_BASE;
821 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
822 }
823 break;
824
825 case 1: //effective address + 8 bits displacement
826 if (rm == 4) {//SIB byte follows ModRM
827 UseSIB(uCodePtr, pOp, pParam, pCpu);
828 }
829 else
830 {
831 pParam->fUse |= DISUSE_BASE;
832 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
833 }
834 pParam->uDisp.i8 = pCpu->i32SibDisp;
835 pParam->fUse |= DISUSE_DISPLACEMENT8;
836 break;
837
838 case 2: //effective address + 32 bits displacement
839 if (rm == 4) {//SIB byte follows ModRM
840 UseSIB(uCodePtr, pOp, pParam, pCpu);
841 }
842 else
843 {
844 pParam->fUse |= DISUSE_BASE;
845 disasmModRMReg(pCpu, pOp, rm, pParam, 1);
846 }
847 pParam->uDisp.i32 = pCpu->i32SibDisp;
848 pParam->fUse |= DISUSE_DISPLACEMENT32;
849 break;
850
851 case 3: //registers
852 disasmModRMReg(pCpu, pOp, rm, pParam, 0);
853 break;
854 }
855 }
856 else
857 {//16 bits addressing mode
858 switch (mod)
859 {
860 case 0: //effective address
861 if (rm == 6)
862 {//16 bits displacement
863 pParam->uDisp.i16 = pCpu->i32SibDisp;
864 pParam->fUse |= DISUSE_DISPLACEMENT16;
865 }
866 else
867 {
868 pParam->fUse |= DISUSE_BASE;
869 disasmModRMReg16(pCpu, pOp, rm, pParam);
870 }
871 break;
872
873 case 1: //effective address + 8 bits displacement
874 disasmModRMReg16(pCpu, pOp, rm, pParam);
875 pParam->uDisp.i8 = pCpu->i32SibDisp;
876 pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT8;
877 break;
878
879 case 2: //effective address + 16 bits displacement
880 disasmModRMReg16(pCpu, pOp, rm, pParam);
881 pParam->uDisp.i16 = pCpu->i32SibDisp;
882 pParam->fUse |= DISUSE_BASE | DISUSE_DISPLACEMENT16;
883 break;
884
885 case 3: //registers
886 disasmModRMReg(pCpu, pOp, rm, pParam, 0);
887 break;
888 }
889 }
890 return 0; //everything was already fetched in ParseModRM
891}
892//*****************************************************************************
893// Query the size of the ModRM parameters and fetch the immediate data (if any)
894//*****************************************************************************
895unsigned QueryModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
896{
897 unsigned sibinc;
898 unsigned size = 0;
899 // unsigned reg = pCpu->ModRM.Bits.Reg;
900 unsigned mod = pCpu->ModRM.Bits.Mod;
901 unsigned rm = pCpu->ModRM.Bits.Rm;
902
903 if (!pSibInc)
904 pSibInc = &sibinc;
905
906 *pSibInc = 0;
907
908 if (pCpu->uAddrMode != DISCPUMODE_16BIT)
909 {
910 Assert(pCpu->uAddrMode == DISCPUMODE_32BIT || pCpu->uAddrMode == DISCPUMODE_64BIT);
911
912 /*
913 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
914 */
915 if (mod != 3 && rm == 4)
916 { /* SIB byte follows ModRM */
917 *pSibInc = ParseSIB(uCodePtr, pOp, pParam, pCpu);
918 uCodePtr += *pSibInc;
919 size += *pSibInc;
920 }
921
922 switch (mod)
923 {
924 case 0: /* Effective address */
925 if (rm == 5) { /* 32 bits displacement */
926 pCpu->i32SibDisp = disReadDWord(pCpu, uCodePtr);
927 size += sizeof(int32_t);
928 }
929 /* else register address */
930 break;
931
932 case 1: /* Effective address + 8 bits displacement */
933 pCpu->i32SibDisp = (int8_t)disReadByte(pCpu, uCodePtr);
934 size += sizeof(char);
935 break;
936
937 case 2: /* Effective address + 32 bits displacement */
938 pCpu->i32SibDisp = disReadDWord(pCpu, uCodePtr);
939 size += sizeof(int32_t);
940 break;
941
942 case 3: /* registers */
943 break;
944 }
945 }
946 else
947 {
948 /* 16 bits mode */
949 switch (mod)
950 {
951 case 0: /* Effective address */
952 if (rm == 6) {
953 pCpu->i32SibDisp = disReadWord(pCpu, uCodePtr);
954 size += sizeof(uint16_t);
955 }
956 /* else register address */
957 break;
958
959 case 1: /* Effective address + 8 bits displacement */
960 pCpu->i32SibDisp = (int8_t)disReadByte(pCpu, uCodePtr);
961 size += sizeof(char);
962 break;
963
964 case 2: /* Effective address + 32 bits displacement */
965 pCpu->i32SibDisp = (int16_t)disReadWord(pCpu, uCodePtr);
966 size += sizeof(uint16_t);
967 break;
968
969 case 3: /* registers */
970 break;
971 }
972 }
973 return size;
974}
975//*****************************************************************************
976// Query the size of the ModRM parameters and fetch the immediate data (if any)
977//*****************************************************************************
978unsigned QueryModRM_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu, unsigned *pSibInc)
979{
980 unsigned sibinc;
981 unsigned size = 0;
982 // unsigned reg = pCpu->ModRM.Bits.Reg;
983 unsigned mod = pCpu->ModRM.Bits.Mod;
984 unsigned rm = pCpu->ModRM.Bits.Rm;
985
986 if (!pSibInc)
987 pSibInc = &sibinc;
988
989 *pSibInc = 0;
990
991 if (pCpu->uAddrMode != DISCPUMODE_16BIT)
992 {
993 Assert(pCpu->uAddrMode == DISCPUMODE_32BIT || pCpu->uAddrMode == DISCPUMODE_64BIT);
994 /*
995 * Note: displacements in long mode are 8 or 32 bits and sign-extended to 64 bits
996 */
997 if (mod != 3 && rm == 4)
998 { /* SIB byte follows ModRM */
999 *pSibInc = ParseSIB_SizeOnly(uCodePtr, pOp, pParam, pCpu);
1000 uCodePtr += *pSibInc;
1001 size += *pSibInc;
1002 }
1003
1004 switch (mod)
1005 {
1006 case 0: //effective address
1007 if (rm == 5) { /* 32 bits displacement */
1008 size += sizeof(int32_t);
1009 }
1010 /* else register address */
1011 break;
1012
1013 case 1: /* Effective address + 8 bits displacement */
1014 size += sizeof(char);
1015 break;
1016
1017 case 2: /* Effective address + 32 bits displacement */
1018 size += sizeof(int32_t);
1019 break;
1020
1021 case 3: /* registers */
1022 break;
1023 }
1024 }
1025 else
1026 {
1027 /* 16 bits mode */
1028 switch (mod)
1029 {
1030 case 0: //effective address
1031 if (rm == 6) {
1032 size += sizeof(uint16_t);
1033 }
1034 /* else register address */
1035 break;
1036
1037 case 1: /* Effective address + 8 bits displacement */
1038 size += sizeof(char);
1039 break;
1040
1041 case 2: /* Effective address + 32 bits displacement */
1042 size += sizeof(uint16_t);
1043 break;
1044
1045 case 3: /* registers */
1046 break;
1047 }
1048 }
1049 return size;
1050}
1051//*****************************************************************************
1052//*****************************************************************************
1053unsigned ParseIllegal(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1054{
1055 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1056 AssertFailed();
1057 return 0;
1058}
1059//*****************************************************************************
1060//*****************************************************************************
1061unsigned ParseModRM(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1062{
1063 unsigned size = sizeof(uint8_t); //ModRM byte
1064 unsigned sibinc, ModRM;
1065
1066 ModRM = disReadByte(pCpu, uCodePtr);
1067 uCodePtr += sizeof(uint8_t);
1068
1069 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1070 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1071 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1072
1073 /* Disregard the mod bits for certain instructions (mov crx, mov drx).
1074 *
1075 * From the AMD manual:
1076 * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
1077 * encoding of the MOD field in the MODR/M byte.
1078 */
1079 if (pOp->optype & DISOPTYPE_MOD_FIXED_11)
1080 pCpu->ModRM.Bits.Mod = 3;
1081
1082 if (pCpu->fPrefix & DISPREFIX_REX)
1083 {
1084 Assert(pCpu->uCpuMode == DISCPUMODE_64BIT);
1085
1086 /* REX.R extends the Reg field. */
1087 pCpu->ModRM.Bits.Reg |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
1088
1089 /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
1090 if (!( pCpu->ModRM.Bits.Mod != 3
1091 && pCpu->ModRM.Bits.Rm == 4)
1092 &&
1093 !( pCpu->ModRM.Bits.Mod == 0
1094 && pCpu->ModRM.Bits.Rm == 5))
1095 {
1096 pCpu->ModRM.Bits.Rm |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
1097 }
1098 }
1099 size += QueryModRM(uCodePtr, pOp, pParam, pCpu, &sibinc);
1100 uCodePtr += sibinc;
1101
1102 UseModRM(uCodePtr, pOp, pParam, pCpu);
1103 return size;
1104}
1105//*****************************************************************************
1106//*****************************************************************************
1107unsigned ParseModRM_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1108{
1109 unsigned size = sizeof(uint8_t); //ModRM byte
1110 unsigned sibinc, ModRM;
1111
1112 ModRM = disReadByte(pCpu, uCodePtr);
1113 uCodePtr += sizeof(uint8_t);
1114
1115 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
1116 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
1117 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
1118
1119 /* Disregard the mod bits for certain instructions (mov crx, mov drx).
1120 *
1121 * From the AMD manual:
1122 * This instruction is always treated as a register-to-register (MOD = 11) instruction, regardless of the
1123 * encoding of the MOD field in the MODR/M byte.
1124 */
1125 if (pOp->optype & DISOPTYPE_MOD_FIXED_11)
1126 pCpu->ModRM.Bits.Mod = 3;
1127
1128 if (pCpu->fPrefix & DISPREFIX_REX)
1129 {
1130 Assert(pCpu->uCpuMode == DISCPUMODE_64BIT);
1131
1132 /* REX.R extends the Reg field. */
1133 pCpu->ModRM.Bits.Reg |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
1134
1135 /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
1136 if (!( pCpu->ModRM.Bits.Mod != 3
1137 && pCpu->ModRM.Bits.Rm == 4)
1138 &&
1139 !( pCpu->ModRM.Bits.Mod == 0
1140 && pCpu->ModRM.Bits.Rm == 5))
1141 {
1142 pCpu->ModRM.Bits.Rm |= ((!!(pCpu->fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
1143 }
1144 }
1145
1146 size += QueryModRM_SizeOnly(uCodePtr, pOp, pParam, pCpu, &sibinc);
1147 uCodePtr += sibinc;
1148
1149 /* UseModRM is not necessary here; we're only interested in the opcode size */
1150 return size;
1151}
1152//*****************************************************************************
1153//*****************************************************************************
1154unsigned ParseModFence(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1155{
1156 ////AssertMsgFailed(("??\n"));
1157 //nothing to do apparently
1158 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1159 return 0;
1160}
1161//*****************************************************************************
1162//*****************************************************************************
1163unsigned ParseImmByte(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1164{
1165 NOREF(pOp);
1166 pParam->parval = disReadByte(pCpu, uCodePtr);
1167 pParam->fUse |= DISUSE_IMMEDIATE8;
1168 pParam->cb = sizeof(uint8_t);
1169 return sizeof(uint8_t);
1170}
1171//*****************************************************************************
1172//*****************************************************************************
1173unsigned ParseImmByte_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1174{
1175 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1176 return sizeof(uint8_t);
1177}
1178//*****************************************************************************
1179//*****************************************************************************
1180unsigned ParseImmByteSX(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1181{
1182 NOREF(pOp);
1183 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1184 {
1185 pParam->parval = (uint32_t)(int8_t)disReadByte(pCpu, uCodePtr);
1186 pParam->fUse |= DISUSE_IMMEDIATE32_SX8;
1187 pParam->cb = sizeof(uint32_t);
1188 }
1189 else
1190 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1191 {
1192 pParam->parval = (uint64_t)(int8_t)disReadByte(pCpu, uCodePtr);
1193 pParam->fUse |= DISUSE_IMMEDIATE64_SX8;
1194 pParam->cb = sizeof(uint64_t);
1195 }
1196 else
1197 {
1198 pParam->parval = (uint16_t)(int8_t)disReadByte(pCpu, uCodePtr);
1199 pParam->fUse |= DISUSE_IMMEDIATE16_SX8;
1200 pParam->cb = sizeof(uint16_t);
1201 }
1202 return sizeof(uint8_t);
1203}
1204//*****************************************************************************
1205//*****************************************************************************
1206unsigned ParseImmByteSX_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1207{
1208 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1209 return sizeof(uint8_t);
1210}
1211//*****************************************************************************
1212//*****************************************************************************
1213unsigned ParseImmUshort(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1214{
1215 NOREF(pOp);
1216 pParam->parval = disReadWord(pCpu, uCodePtr);
1217 pParam->fUse |= DISUSE_IMMEDIATE16;
1218 pParam->cb = sizeof(uint16_t);
1219 return sizeof(uint16_t);
1220}
1221//*****************************************************************************
1222//*****************************************************************************
1223unsigned ParseImmUshort_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1224{
1225 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1226 return sizeof(uint16_t);
1227}
1228//*****************************************************************************
1229//*****************************************************************************
1230unsigned ParseImmUlong(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1231{
1232 NOREF(pOp);
1233 pParam->parval = disReadDWord(pCpu, uCodePtr);
1234 pParam->fUse |= DISUSE_IMMEDIATE32;
1235 pParam->cb = sizeof(uint32_t);
1236 return sizeof(uint32_t);
1237}
1238//*****************************************************************************
1239//*****************************************************************************
1240unsigned ParseImmUlong_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1241{
1242 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1243 return sizeof(uint32_t);
1244}
1245//*****************************************************************************
1246//*****************************************************************************
1247unsigned ParseImmQword(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1248{
1249 NOREF(pOp);
1250 pParam->parval = disReadQWord(pCpu, uCodePtr);
1251 pParam->fUse |= DISUSE_IMMEDIATE64;
1252 pParam->cb = sizeof(uint64_t);
1253 return sizeof(uint64_t);
1254}
1255//*****************************************************************************
1256//*****************************************************************************
1257unsigned ParseImmQword_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1258{
1259 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1260 return sizeof(uint64_t);
1261}
1262//*****************************************************************************
1263//*****************************************************************************
1264unsigned ParseImmV(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1265{
1266 NOREF(pOp);
1267 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1268 {
1269 pParam->parval = disReadDWord(pCpu, uCodePtr);
1270 pParam->fUse |= DISUSE_IMMEDIATE32;
1271 pParam->cb = sizeof(uint32_t);
1272 return sizeof(uint32_t);
1273 }
1274
1275 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1276 {
1277 pParam->parval = disReadQWord(pCpu, uCodePtr);
1278 pParam->fUse |= DISUSE_IMMEDIATE64;
1279 pParam->cb = sizeof(uint64_t);
1280 return sizeof(uint64_t);
1281 }
1282
1283 pParam->parval = disReadWord(pCpu, uCodePtr);
1284 pParam->fUse |= DISUSE_IMMEDIATE16;
1285 pParam->cb = sizeof(uint16_t);
1286 return sizeof(uint16_t);
1287}
1288//*****************************************************************************
1289//*****************************************************************************
1290unsigned ParseImmV_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1291{
1292 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam);
1293 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1294 return sizeof(uint32_t);
1295 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1296 return sizeof(uint64_t);
1297 return sizeof(uint16_t);
1298}
1299//*****************************************************************************
1300//*****************************************************************************
1301unsigned ParseImmZ(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1302{
1303 NOREF(pOp);
1304 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1305 if (pCpu->uOpMode == DISCPUMODE_16BIT)
1306 {
1307 pParam->parval = disReadWord(pCpu, uCodePtr);
1308 pParam->fUse |= DISUSE_IMMEDIATE16;
1309 pParam->cb = sizeof(uint16_t);
1310 return sizeof(uint16_t);
1311 }
1312
1313 /* 64 bits op mode means *sign* extend to 64 bits. */
1314 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1315 {
1316 pParam->parval = (uint64_t)(int32_t)disReadDWord(pCpu, uCodePtr);
1317 pParam->fUse |= DISUSE_IMMEDIATE64;
1318 pParam->cb = sizeof(uint64_t);
1319 }
1320 else
1321 {
1322 pParam->parval = disReadDWord(pCpu, uCodePtr);
1323 pParam->fUse |= DISUSE_IMMEDIATE32;
1324 pParam->cb = sizeof(uint32_t);
1325 }
1326 return sizeof(uint32_t);
1327}
1328//*****************************************************************************
1329//*****************************************************************************
1330unsigned ParseImmZ_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1331{
1332 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam);
1333 /* Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size. */
1334 if (pCpu->uOpMode == DISCPUMODE_16BIT)
1335 return sizeof(uint16_t);
1336 return sizeof(uint32_t);
1337}
1338
1339//*****************************************************************************
1340// Relative displacement for branches (rel. to next instruction)
1341//*****************************************************************************
1342unsigned ParseImmBRel(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1343{
1344 NOREF(pOp);
1345 pParam->parval = disReadByte(pCpu, uCodePtr);
1346 pParam->fUse |= DISUSE_IMMEDIATE8_REL;
1347 pParam->cb = sizeof(uint8_t);
1348 return sizeof(char);
1349}
1350//*****************************************************************************
1351// Relative displacement for branches (rel. to next instruction)
1352//*****************************************************************************
1353unsigned ParseImmBRel_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1354{
1355 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam); NOREF(pCpu);
1356 return sizeof(char);
1357}
1358//*****************************************************************************
1359// Relative displacement for branches (rel. to next instruction)
1360//*****************************************************************************
1361unsigned ParseImmVRel(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1362{
1363 NOREF(pOp);
1364 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1365 {
1366 pParam->parval = disReadDWord(pCpu, uCodePtr);
1367 pParam->fUse |= DISUSE_IMMEDIATE32_REL;
1368 pParam->cb = sizeof(int32_t);
1369 return sizeof(int32_t);
1370 }
1371
1372 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1373 {
1374 /* 32 bits relative immediate sign extended to 64 bits. */
1375 pParam->parval = (uint64_t)(int32_t)disReadDWord(pCpu, uCodePtr);
1376 pParam->fUse |= DISUSE_IMMEDIATE64_REL;
1377 pParam->cb = sizeof(int64_t);
1378 return sizeof(int32_t);
1379 }
1380
1381 pParam->parval = disReadWord(pCpu, uCodePtr);
1382 pParam->fUse |= DISUSE_IMMEDIATE16_REL;
1383 pParam->cb = sizeof(int16_t);
1384 return sizeof(int16_t);
1385}
1386//*****************************************************************************
1387// Relative displacement for branches (rel. to next instruction)
1388//*****************************************************************************
1389unsigned ParseImmVRel_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1390{
1391 NOREF(uCodePtr); NOREF(pOp); NOREF(pParam);
1392 if (pCpu->uOpMode == DISCPUMODE_16BIT)
1393 return sizeof(int16_t);
1394 /* Both 32 & 64 bits mode use 32 bits relative immediates. */
1395 return sizeof(int32_t);
1396}
1397//*****************************************************************************
1398//*****************************************************************************
1399unsigned ParseImmAddr(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1400{
1401 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
1402 {
1403 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1404 {
1405 /* far 16:32 pointer */
1406 pParam->parval = disReadDWord(pCpu, uCodePtr);
1407 *((uint32_t*)&pParam->parval+1) = disReadWord(pCpu, uCodePtr+sizeof(uint32_t));
1408 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1409 pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1410 return sizeof(uint32_t) + sizeof(uint16_t);
1411 }
1412
1413 /*
1414 * near 32 bits pointer
1415 *
1416 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1417 * so we treat it like displacement.
1418 */
1419 pParam->uDisp.i32 = disReadDWord(pCpu, uCodePtr);
1420 pParam->fUse |= DISUSE_DISPLACEMENT32;
1421 pParam->cb = sizeof(uint32_t);
1422 return sizeof(uint32_t);
1423 }
1424
1425 if (pCpu->uAddrMode == DISCPUMODE_64BIT)
1426 {
1427 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1428 /*
1429 * near 64 bits pointer
1430 *
1431 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1432 * so we treat it like displacement.
1433 */
1434 pParam->uDisp.i64 = disReadQWord(pCpu, uCodePtr);
1435 pParam->fUse |= DISUSE_DISPLACEMENT64;
1436 pParam->cb = sizeof(uint64_t);
1437 return sizeof(uint64_t);
1438 }
1439 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1440 {
1441 /* far 16:16 pointer */
1442 pParam->parval = disReadDWord(pCpu, uCodePtr);
1443 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1444 pParam->cb = 2*sizeof(uint16_t);
1445 return sizeof(uint32_t);
1446 }
1447
1448 /*
1449 * near 16 bits pointer
1450 *
1451 * Note: used only in "mov al|ax|eax, [Addr]" and "mov [Addr], al|ax|eax"
1452 * so we treat it like displacement.
1453 */
1454 pParam->uDisp.i16 = disReadWord(pCpu, uCodePtr);
1455 pParam->fUse |= DISUSE_DISPLACEMENT16;
1456 pParam->cb = sizeof(uint16_t);
1457 return sizeof(uint16_t);
1458}
1459//*****************************************************************************
1460//*****************************************************************************
1461unsigned ParseImmAddr_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1462{
1463 NOREF(uCodePtr); NOREF(pOp);
1464 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
1465 {
1466 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1467 {// far 16:32 pointer
1468 return sizeof(uint32_t) + sizeof(uint16_t);
1469 }
1470 else
1471 {// near 32 bits pointer
1472 return sizeof(uint32_t);
1473 }
1474 }
1475 if (pCpu->uAddrMode == DISCPUMODE_64BIT)
1476 {
1477 Assert(OP_PARM_VSUBTYPE(pParam->param) != OP_PARM_p);
1478 return sizeof(uint64_t);
1479 }
1480 else
1481 {
1482 if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p)
1483 {// far 16:16 pointer
1484 return sizeof(uint32_t);
1485 }
1486 else
1487 {// near 16 bits pointer
1488 return sizeof(uint16_t);
1489 }
1490 }
1491}
1492//*****************************************************************************
1493//*****************************************************************************
1494unsigned ParseImmAddrF(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1495{
1496 // immediate far pointers - only 16:16 or 16:32; determined by operand, *not* address size!
1497 Assert(pCpu->uOpMode == DISCPUMODE_16BIT || pCpu->uOpMode == DISCPUMODE_32BIT);
1498 Assert(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p);
1499 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1500 {
1501 // far 16:32 pointer
1502 pParam->parval = disReadDWord(pCpu, uCodePtr);
1503 *((uint32_t*)&pParam->parval+1) = disReadWord(pCpu, uCodePtr+sizeof(uint32_t));
1504 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_32;
1505 pParam->cb = sizeof(uint16_t) + sizeof(uint32_t);
1506 return sizeof(uint32_t) + sizeof(uint16_t);
1507 }
1508
1509 // far 16:16 pointer
1510 pParam->parval = disReadDWord(pCpu, uCodePtr);
1511 pParam->fUse |= DISUSE_IMMEDIATE_ADDR_16_16;
1512 pParam->cb = 2*sizeof(uint16_t);
1513 return sizeof(uint32_t);
1514}
1515//*****************************************************************************
1516//*****************************************************************************
1517unsigned ParseImmAddrF_SizeOnly(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1518{
1519 NOREF(uCodePtr); NOREF(pOp);
1520 // immediate far pointers - only 16:16 or 16:32
1521 Assert(pCpu->uOpMode == DISCPUMODE_16BIT || pCpu->uOpMode == DISCPUMODE_32BIT);
1522 Assert(OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p);
1523 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1524 {
1525 // far 16:32 pointer
1526 return sizeof(uint32_t) + sizeof(uint16_t);
1527 }
1528 else
1529 {
1530 // far 16:16 pointer
1531 return sizeof(uint32_t);
1532 }
1533}
1534//*****************************************************************************
1535//*****************************************************************************
1536unsigned ParseFixedReg(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1537{
1538 NOREF(uCodePtr);
1539
1540 /*
1541 * Sets up flags for stored in OPC fixed registers.
1542 */
1543
1544 if (pParam->param == OP_PARM_NONE)
1545 {
1546 /* No parameter at all. */
1547 return 0;
1548 }
1549
1550 AssertCompile(OP_PARM_REG_GEN32_END < OP_PARM_REG_SEG_END);
1551 AssertCompile(OP_PARM_REG_SEG_END < OP_PARM_REG_GEN16_END);
1552 AssertCompile(OP_PARM_REG_GEN16_END < OP_PARM_REG_GEN8_END);
1553 AssertCompile(OP_PARM_REG_GEN8_END < OP_PARM_REG_FP_END);
1554
1555 if (pParam->param <= OP_PARM_REG_GEN32_END)
1556 {
1557 /* 32-bit EAX..EDI registers. */
1558 if (pCpu->uOpMode == DISCPUMODE_32BIT)
1559 {
1560 /* Use 32-bit registers. */
1561 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1562 pParam->fUse |= DISUSE_REG_GEN32;
1563 pParam->cb = 4;
1564 }
1565 else
1566 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1567 {
1568 /* Use 64-bit registers. */
1569 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1570 if ( (pOp->optype & DISOPTYPE_REXB_EXTENDS_OPREG)
1571 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1572 && (pCpu->fPrefix & DISPREFIX_REX)
1573 && (pCpu->fRexPrefix & DISPREFIX_REX_FLAGS))
1574 pParam->base.reg_gen += 8;
1575
1576 pParam->fUse |= DISUSE_REG_GEN64;
1577 pParam->cb = 8;
1578 }
1579 else
1580 {
1581 /* Use 16-bit registers. */
1582 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN32_START;
1583 pParam->fUse |= DISUSE_REG_GEN16;
1584 pParam->cb = 2;
1585 pParam->param = pParam->param - OP_PARM_REG_GEN32_START + OP_PARM_REG_GEN16_START;
1586 }
1587 }
1588 else
1589 if (pParam->param <= OP_PARM_REG_SEG_END)
1590 {
1591 /* Segment ES..GS registers. */
1592 pParam->base.reg_seg = (DISSELREG)(pParam->param - OP_PARM_REG_SEG_START);
1593 pParam->fUse |= DISUSE_REG_SEG;
1594 pParam->cb = 2;
1595 }
1596 else
1597 if (pParam->param <= OP_PARM_REG_GEN16_END)
1598 {
1599 /* 16-bit AX..DI registers. */
1600 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN16_START;
1601 pParam->fUse |= DISUSE_REG_GEN16;
1602 pParam->cb = 2;
1603 }
1604 else
1605 if (pParam->param <= OP_PARM_REG_GEN8_END)
1606 {
1607 /* 8-bit AL..DL, AH..DH registers. */
1608 pParam->base.reg_gen = pParam->param - OP_PARM_REG_GEN8_START;
1609 pParam->fUse |= DISUSE_REG_GEN8;
1610 pParam->cb = 1;
1611
1612 if (pCpu->uOpMode == DISCPUMODE_64BIT)
1613 {
1614 if ( (pOp->optype & DISOPTYPE_REXB_EXTENDS_OPREG)
1615 && pParam == &pCpu->param1 /* ugly assumption that it only applies to the first parameter */
1616 && (pCpu->fPrefix & DISPREFIX_REX)
1617 && (pCpu->fRexPrefix & DISPREFIX_REX_FLAGS))
1618 pParam->base.reg_gen += 8; /* least significant byte of R8-R15 */
1619 }
1620 }
1621 else
1622 if (pParam->param <= OP_PARM_REG_FP_END)
1623 {
1624 /* FPU registers. */
1625 pParam->base.reg_fp = pParam->param - OP_PARM_REG_FP_START;
1626 pParam->fUse |= DISUSE_REG_FP;
1627 pParam->cb = 10;
1628 }
1629 Assert(!(pParam->param >= OP_PARM_REG_GEN64_START && pParam->param <= OP_PARM_REG_GEN64_END));
1630
1631 /* else - not supported for now registers. */
1632
1633 return 0;
1634}
1635//*****************************************************************************
1636//*****************************************************************************
1637unsigned ParseXv(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1638{
1639 NOREF(uCodePtr);
1640
1641 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1642 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
1643 {
1644 pParam->base.reg_gen = DISGREG_ESI;
1645 pParam->fUse |= DISUSE_REG_GEN32;
1646 }
1647 else
1648 if (pCpu->uAddrMode == DISCPUMODE_64BIT)
1649 {
1650 pParam->base.reg_gen = DISGREG_RSI;
1651 pParam->fUse |= DISUSE_REG_GEN64;
1652 }
1653 else
1654 {
1655 pParam->base.reg_gen = DISGREG_SI;
1656 pParam->fUse |= DISUSE_REG_GEN16;
1657 }
1658 return 0; //no additional opcode bytes
1659}
1660//*****************************************************************************
1661//*****************************************************************************
1662unsigned ParseXb(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1663{
1664 NOREF(uCodePtr); NOREF(pOp);
1665
1666 pParam->fUse |= DISUSE_POINTER_DS_BASED;
1667 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
1668 {
1669 pParam->base.reg_gen = DISGREG_ESI;
1670 pParam->fUse |= DISUSE_REG_GEN32;
1671 }
1672 else
1673 if (pCpu->uAddrMode == DISCPUMODE_64BIT)
1674 {
1675 pParam->base.reg_gen = DISGREG_RSI;
1676 pParam->fUse |= DISUSE_REG_GEN64;
1677 }
1678 else
1679 {
1680 pParam->base.reg_gen = DISGREG_SI;
1681 pParam->fUse |= DISUSE_REG_GEN16;
1682 }
1683 return 0; //no additional opcode bytes
1684}
1685//*****************************************************************************
1686//*****************************************************************************
1687unsigned ParseYv(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1688{
1689 NOREF(uCodePtr);
1690
1691 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1692 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
1693 {
1694 pParam->base.reg_gen = DISGREG_EDI;
1695 pParam->fUse |= DISUSE_REG_GEN32;
1696 }
1697 else
1698 if (pCpu->uAddrMode == DISCPUMODE_64BIT)
1699 {
1700 pParam->base.reg_gen = DISGREG_RDI;
1701 pParam->fUse |= DISUSE_REG_GEN64;
1702 }
1703 else
1704 {
1705 pParam->base.reg_gen = DISGREG_DI;
1706 pParam->fUse |= DISUSE_REG_GEN16;
1707 }
1708 return 0; //no additional opcode bytes
1709}
1710//*****************************************************************************
1711//*****************************************************************************
1712unsigned ParseYb(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1713{
1714 NOREF(uCodePtr); NOREF(pOp);
1715
1716 pParam->fUse |= DISUSE_POINTER_ES_BASED;
1717 if (pCpu->uAddrMode == DISCPUMODE_32BIT)
1718 {
1719 pParam->base.reg_gen = DISGREG_EDI;
1720 pParam->fUse |= DISUSE_REG_GEN32;
1721 }
1722 else
1723 if (pCpu->uAddrMode == DISCPUMODE_64BIT)
1724 {
1725 pParam->base.reg_gen = DISGREG_RDI;
1726 pParam->fUse |= DISUSE_REG_GEN64;
1727 }
1728 else
1729 {
1730 pParam->base.reg_gen = DISGREG_DI;
1731 pParam->fUse |= DISUSE_REG_GEN16;
1732 }
1733 return 0; //no additional opcode bytes
1734}
1735//*****************************************************************************
1736//*****************************************************************************
1737unsigned ParseTwoByteEsc(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1738{
1739 PCDISOPCODE pOpcode;
1740 int size = sizeof(uint8_t);
1741 NOREF(pOp); NOREF(pParam);
1742
1743 /* 2nd byte */
1744 pCpu->bOpCode = disReadByte(pCpu, uCodePtr);
1745
1746 /* default to the non-prefixed table. */
1747 pOpcode = &g_aTwoByteMapX86[pCpu->bOpCode];
1748
1749 /* Handle opcode table extensions that rely on the address, repe or repne prefix byte. */
1750 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1751 if (pCpu->bLastPrefix)
1752 {
1753 switch (pCpu->bLastPrefix)
1754 {
1755 case OP_OPSIZE: /* 0x66 */
1756 if (g_aTwoByteMapX86_PF66[pCpu->bOpCode].uOpcode != OP_INVALID)
1757 {
1758 /* Table entry is valid, so use the extension table. */
1759 pOpcode = &g_aTwoByteMapX86_PF66[pCpu->bOpCode];
1760
1761 /* Cancel prefix changes. */
1762 pCpu->fPrefix &= ~DISPREFIX_OPSIZE;
1763 pCpu->uOpMode = pCpu->uCpuMode;
1764 }
1765 break;
1766
1767 case OP_REPNE: /* 0xF2 */
1768 if (g_aTwoByteMapX86_PFF2[pCpu->bOpCode].uOpcode != OP_INVALID)
1769 {
1770 /* Table entry is valid, so use the extension table. */
1771 pOpcode = &g_aTwoByteMapX86_PFF2[pCpu->bOpCode];
1772
1773 /* Cancel prefix changes. */
1774 pCpu->fPrefix &= ~DISPREFIX_REPNE;
1775 }
1776 break;
1777
1778 case OP_REPE: /* 0xF3 */
1779 if (g_aTwoByteMapX86_PFF3[pCpu->bOpCode].uOpcode != OP_INVALID)
1780 {
1781 /* Table entry is valid, so use the extension table. */
1782 pOpcode = &g_aTwoByteMapX86_PFF3[pCpu->bOpCode];
1783
1784 /* Cancel prefix changes. */
1785 pCpu->fPrefix &= ~DISPREFIX_REP;
1786 }
1787 break;
1788 }
1789 }
1790
1791 size += disParseInstruction(uCodePtr+size, pOpcode, pCpu);
1792 return size;
1793}
1794//*****************************************************************************
1795//*****************************************************************************
1796unsigned ParseThreeByteEsc4(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1797{
1798 PCDISOPCODE pOpcode;
1799 int size = sizeof(uint8_t);
1800 NOREF(pOp); NOREF(pParam);
1801
1802 /* 3rd byte */
1803 pCpu->bOpCode = disReadByte(pCpu, uCodePtr);
1804
1805 /* default to the non-prefixed table. */
1806 if (g_apThreeByteMapX86_0F38[pCpu->bOpCode >> 4])
1807 {
1808 pOpcode = g_apThreeByteMapX86_0F38[pCpu->bOpCode >> 4];
1809 pOpcode = &pOpcode[pCpu->bOpCode & 0xf];
1810 }
1811 else
1812 pOpcode = &g_InvalidOpcode[0];
1813
1814 /* Handle opcode table extensions that rely on the address, repne prefix byte. */
1815 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1816 switch (pCpu->bLastPrefix)
1817 {
1818 case OP_OPSIZE: /* 0x66 */
1819 if (g_apThreeByteMapX86_660F38[pCpu->bOpCode >> 4])
1820 {
1821 pOpcode = g_apThreeByteMapX86_660F38[pCpu->bOpCode >> 4];
1822 pOpcode = &pOpcode[pCpu->bOpCode & 0xf];
1823
1824 if (pOpcode->uOpcode != OP_INVALID)
1825 {
1826 /* Table entry is valid, so use the extension table. */
1827
1828 /* Cancel prefix changes. */
1829 pCpu->fPrefix &= ~DISPREFIX_OPSIZE;
1830 pCpu->uOpMode = pCpu->uCpuMode;
1831 }
1832 }
1833 break;
1834
1835 case OP_REPNE: /* 0xF2 */
1836 if (g_apThreeByteMapX86_F20F38[pCpu->bOpCode >> 4])
1837 {
1838 pOpcode = g_apThreeByteMapX86_F20F38[pCpu->bOpCode >> 4];
1839 pOpcode = &pOpcode[pCpu->bOpCode & 0xf];
1840
1841 if (pOpcode->uOpcode != OP_INVALID)
1842 {
1843 /* Table entry is valid, so use the extension table. */
1844
1845 /* Cancel prefix changes. */
1846 pCpu->fPrefix &= ~DISPREFIX_REPNE;
1847 }
1848 }
1849 break;
1850 }
1851
1852 size += disParseInstruction(uCodePtr+size, pOpcode, pCpu);
1853 return size;
1854}
1855//*****************************************************************************
1856//*****************************************************************************
1857unsigned ParseThreeByteEsc5(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1858{
1859 PCDISOPCODE pOpcode;
1860 int size = sizeof(uint8_t);
1861 NOREF(pOp); NOREF(pParam);
1862
1863 /* 3rd byte */
1864 pCpu->bOpCode = disReadByte(pCpu, uCodePtr);
1865
1866 /** @todo Should we take the first or last prefix byte in case of multiple prefix bytes??? */
1867 Assert(pCpu->bLastPrefix == OP_OPSIZE);
1868
1869 /* default to the non-prefixed table. */
1870 if (g_apThreeByteMapX86_660F3A[pCpu->bOpCode >> 4])
1871 {
1872 pOpcode = g_apThreeByteMapX86_660F3A[pCpu->bOpCode >> 4];
1873 pOpcode = &pOpcode[pCpu->bOpCode & 0xf];
1874
1875 if (pOpcode->uOpcode != OP_INVALID)
1876 {
1877 /* Table entry is valid, so use the extension table. */
1878
1879 /* Cancel prefix changes. */
1880 pCpu->fPrefix &= ~DISPREFIX_OPSIZE;
1881 pCpu->uOpMode = pCpu->uCpuMode;
1882 }
1883 }
1884 else
1885 pOpcode = &g_InvalidOpcode[0];
1886
1887 size += disParseInstruction(uCodePtr+size, pOpcode, pCpu);
1888 return size;
1889}
1890//*****************************************************************************
1891//*****************************************************************************
1892unsigned ParseNopPause(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1893{
1894 unsigned size = 0;
1895 NOREF(pParam);
1896
1897 if (pCpu->fPrefix & DISPREFIX_REP)
1898 {
1899 pOp = &g_aMapX86_NopPause[1]; /* PAUSE */
1900 pCpu->fPrefix &= ~DISPREFIX_REP;
1901 }
1902 else
1903 pOp = &g_aMapX86_NopPause[0]; /* NOP */
1904
1905 size += disParseInstruction(uCodePtr, pOp, pCpu);
1906 return size;
1907}
1908//*****************************************************************************
1909//*****************************************************************************
1910unsigned ParseImmGrpl(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1911{
1912 int idx = (pCpu->bOpCode - 0x80) * 8;
1913 unsigned size = 0, modrm, reg;
1914 NOREF(pParam);
1915
1916 modrm = disReadByte(pCpu, uCodePtr);
1917 reg = MODRM_REG(modrm);
1918
1919 pOp = (PCDISOPCODE)&g_aMapX86_Group1[idx+reg];
1920 //little hack to make sure the ModRM byte is included in the returned size
1921 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1922 size = sizeof(uint8_t); //ModRM byte
1923
1924 size += disParseInstruction(uCodePtr, pOp, pCpu);
1925
1926 return size;
1927}
1928//*****************************************************************************
1929//*****************************************************************************
1930unsigned ParseShiftGrp2(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1931{
1932 int idx;
1933 unsigned size = 0, modrm, reg;
1934 NOREF(pParam);
1935
1936 switch (pCpu->bOpCode)
1937 {
1938 case 0xC0:
1939 case 0xC1:
1940 idx = (pCpu->bOpCode - 0xC0)*8;
1941 break;
1942
1943 case 0xD0:
1944 case 0xD1:
1945 case 0xD2:
1946 case 0xD3:
1947 idx = (pCpu->bOpCode - 0xD0 + 2)*8;
1948 break;
1949
1950 default:
1951 AssertMsgFailed(("Oops\n"));
1952 return sizeof(uint8_t);
1953 }
1954
1955 modrm = disReadByte(pCpu, uCodePtr);
1956 reg = MODRM_REG(modrm);
1957
1958 pOp = (PCDISOPCODE)&g_aMapX86_Group2[idx+reg];
1959
1960 //little hack to make sure the ModRM byte is included in the returned size
1961 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1962 size = sizeof(uint8_t); //ModRM byte
1963
1964 size += disParseInstruction(uCodePtr, pOp, pCpu);
1965
1966 return size;
1967}
1968//*****************************************************************************
1969//*****************************************************************************
1970unsigned ParseGrp3(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1971{
1972 int idx = (pCpu->bOpCode - 0xF6) * 8;
1973 unsigned size = 0, modrm, reg;
1974 NOREF(pParam);
1975
1976 modrm = disReadByte(pCpu, uCodePtr);
1977 reg = MODRM_REG(modrm);
1978
1979 pOp = (PCDISOPCODE)&g_aMapX86_Group3[idx+reg];
1980
1981 //little hack to make sure the ModRM byte is included in the returned size
1982 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
1983 size = sizeof(uint8_t); //ModRM byte
1984
1985 size += disParseInstruction(uCodePtr, pOp, pCpu);
1986
1987 return size;
1988}
1989//*****************************************************************************
1990//*****************************************************************************
1991unsigned ParseGrp4(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
1992{
1993 unsigned size = 0, modrm, reg;
1994 NOREF(pParam);
1995
1996 modrm = disReadByte(pCpu, uCodePtr);
1997 reg = MODRM_REG(modrm);
1998
1999 pOp = (PCDISOPCODE)&g_aMapX86_Group4[reg];
2000
2001 //little hack to make sure the ModRM byte is included in the returned size
2002 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2003 size = sizeof(uint8_t); //ModRM byte
2004
2005 size += disParseInstruction(uCodePtr, pOp, pCpu);
2006
2007 return size;
2008}
2009//*****************************************************************************
2010//*****************************************************************************
2011unsigned ParseGrp5(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2012{
2013 unsigned size = 0, modrm, reg;
2014 NOREF(pParam);
2015
2016 modrm = disReadByte(pCpu, uCodePtr);
2017 reg = MODRM_REG(modrm);
2018
2019 pOp = (PCDISOPCODE)&g_aMapX86_Group5[reg];
2020
2021 //little hack to make sure the ModRM byte is included in the returned size
2022 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2023 size = sizeof(uint8_t); //ModRM byte
2024
2025 size += disParseInstruction(uCodePtr, pOp, pCpu);
2026
2027 return size;
2028}
2029//*****************************************************************************
2030// 0xF 0xF [ModRM] [SIB] [displacement] imm8_opcode
2031// It would appear the ModRM byte must always be present. How else can you
2032// determine the offset of the imm8_opcode byte otherwise?
2033//
2034//*****************************************************************************
2035unsigned Parse3DNow(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2036{
2037 unsigned size = 0, modrmsize;
2038
2039#ifdef DEBUG_Sander
2040 //needs testing
2041 AssertMsgFailed(("Test me\n"));
2042#endif
2043
2044 unsigned ModRM = disReadByte(pCpu, uCodePtr);
2045 pCpu->ModRM.Bits.Rm = MODRM_RM(ModRM);
2046 pCpu->ModRM.Bits.Mod = MODRM_MOD(ModRM);
2047 pCpu->ModRM.Bits.Reg = MODRM_REG(ModRM);
2048
2049 modrmsize = QueryModRM(uCodePtr+sizeof(uint8_t), pOp, pParam, pCpu);
2050
2051 uint8_t opcode = disReadByte(pCpu, uCodePtr+sizeof(uint8_t)+modrmsize);
2052
2053 pOp = (PCDISOPCODE)&g_aTwoByteMapX86_3DNow[opcode];
2054
2055 //little hack to make sure the ModRM byte is included in the returned size
2056 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2057 {
2058#ifdef DEBUG_Sander /* bird, 2005-06-28: Alex is getting this during full installation of win2ksp4. */
2059 AssertMsgFailed(("Oops!\n")); //shouldn't happen!
2060#endif
2061 size = sizeof(uint8_t); //ModRM byte
2062 }
2063
2064 size += disParseInstruction(uCodePtr, pOp, pCpu);
2065 size += sizeof(uint8_t); //imm8_opcode uint8_t
2066
2067 return size;
2068}
2069//*****************************************************************************
2070//*****************************************************************************
2071unsigned ParseGrp6(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2072{
2073 unsigned size = 0, modrm, reg;
2074 NOREF(pParam);
2075
2076 modrm = disReadByte(pCpu, uCodePtr);
2077 reg = MODRM_REG(modrm);
2078
2079 pOp = (PCDISOPCODE)&g_aMapX86_Group6[reg];
2080
2081 //little hack to make sure the ModRM byte is included in the returned size
2082 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2083 size = sizeof(uint8_t); //ModRM byte
2084
2085 size += disParseInstruction(uCodePtr, pOp, pCpu);
2086
2087 return size;
2088}
2089//*****************************************************************************
2090//*****************************************************************************
2091unsigned ParseGrp7(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2092{
2093 unsigned size = 0, modrm, reg, rm, mod;
2094 NOREF(pParam);
2095
2096 modrm = disReadByte(pCpu, uCodePtr);
2097 mod = MODRM_MOD(modrm);
2098 reg = MODRM_REG(modrm);
2099 rm = MODRM_RM(modrm);
2100
2101 if (mod == 3 && rm == 0)
2102 pOp = (PCDISOPCODE)&g_aMapX86_Group7_mod11_rm000[reg];
2103 else
2104 if (mod == 3 && rm == 1)
2105 pOp = (PCDISOPCODE)&g_aMapX86_Group7_mod11_rm001[reg];
2106 else
2107 pOp = (PCDISOPCODE)&g_aMapX86_Group7_mem[reg];
2108
2109 //little hack to make sure the ModRM byte is included in the returned size
2110 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2111 size = sizeof(uint8_t); //ModRM byte
2112
2113 size += disParseInstruction(uCodePtr, pOp, pCpu);
2114
2115 return size;
2116}
2117//*****************************************************************************
2118//*****************************************************************************
2119unsigned ParseGrp8(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2120{
2121 unsigned size = 0, modrm, reg;
2122 NOREF(pParam);
2123
2124 modrm = disReadByte(pCpu, uCodePtr);
2125 reg = MODRM_REG(modrm);
2126
2127 pOp = (PCDISOPCODE)&g_aMapX86_Group8[reg];
2128
2129 //little hack to make sure the ModRM byte is included in the returned size
2130 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2131 size = sizeof(uint8_t); //ModRM byte
2132
2133 size += disParseInstruction(uCodePtr, pOp, pCpu);
2134
2135 return size;
2136}
2137//*****************************************************************************
2138//*****************************************************************************
2139unsigned ParseGrp9(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2140{
2141 unsigned size = 0, modrm, reg;
2142 NOREF(pParam);
2143
2144 modrm = disReadByte(pCpu, uCodePtr);
2145 reg = MODRM_REG(modrm);
2146
2147 pOp = (PCDISOPCODE)&g_aMapX86_Group9[reg];
2148
2149 //little hack to make sure the ModRM byte is included in the returned size
2150 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2151 size = sizeof(uint8_t); //ModRM byte
2152
2153 size += disParseInstruction(uCodePtr, pOp, pCpu);
2154
2155 return size;
2156}
2157//*****************************************************************************
2158//*****************************************************************************
2159unsigned ParseGrp10(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2160{
2161 unsigned size = 0, modrm, reg;
2162 NOREF(pParam);
2163
2164 modrm = disReadByte(pCpu, uCodePtr);
2165 reg = MODRM_REG(modrm);
2166
2167 pOp = (PCDISOPCODE)&g_aMapX86_Group10[reg];
2168
2169 //little hack to make sure the ModRM byte is included in the returned size
2170 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2171 size = sizeof(uint8_t); //ModRM byte
2172
2173 size += disParseInstruction(uCodePtr, pOp, pCpu);
2174
2175 return size;
2176}
2177//*****************************************************************************
2178//*****************************************************************************
2179unsigned ParseGrp12(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2180{
2181 unsigned size = 0, modrm, reg;
2182 NOREF(pParam);
2183
2184 modrm = disReadByte(pCpu, uCodePtr);
2185 reg = MODRM_REG(modrm);
2186
2187 if (pCpu->fPrefix & DISPREFIX_OPSIZE)
2188 reg += 8; //2nd table
2189
2190 pOp = (PCDISOPCODE)&g_aMapX86_Group12[reg];
2191
2192 //little hack to make sure the ModRM byte is included in the returned size
2193 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2194 size = sizeof(uint8_t); //ModRM byte
2195
2196 size += disParseInstruction(uCodePtr, pOp, pCpu);
2197 return size;
2198}
2199//*****************************************************************************
2200//*****************************************************************************
2201unsigned ParseGrp13(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2202{
2203 unsigned size = 0, modrm, reg;
2204 NOREF(pParam);
2205
2206 modrm = disReadByte(pCpu, uCodePtr);
2207 reg = MODRM_REG(modrm);
2208 if (pCpu->fPrefix & DISPREFIX_OPSIZE)
2209 reg += 8; //2nd table
2210
2211 pOp = (PCDISOPCODE)&g_aMapX86_Group13[reg];
2212
2213 //little hack to make sure the ModRM byte is included in the returned size
2214 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2215 size = sizeof(uint8_t); //ModRM byte
2216
2217 size += disParseInstruction(uCodePtr, pOp, pCpu);
2218
2219 return size;
2220}
2221//*****************************************************************************
2222//*****************************************************************************
2223unsigned ParseGrp14(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2224{
2225 unsigned size = 0, modrm, reg;
2226 NOREF(pParam);
2227
2228 modrm = disReadByte(pCpu, uCodePtr);
2229 reg = MODRM_REG(modrm);
2230 if (pCpu->fPrefix & DISPREFIX_OPSIZE)
2231 reg += 8; //2nd table
2232
2233 pOp = (PCDISOPCODE)&g_aMapX86_Group14[reg];
2234
2235 //little hack to make sure the ModRM byte is included in the returned size
2236 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2237 size = sizeof(uint8_t); //ModRM byte
2238
2239 size += disParseInstruction(uCodePtr, pOp, pCpu);
2240
2241 return size;
2242}
2243//*****************************************************************************
2244//*****************************************************************************
2245unsigned ParseGrp15(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2246{
2247 unsigned size = 0, modrm, reg, mod, rm;
2248 NOREF(pParam);
2249
2250 modrm = disReadByte(pCpu, uCodePtr);
2251 mod = MODRM_MOD(modrm);
2252 reg = MODRM_REG(modrm);
2253 rm = MODRM_RM(modrm);
2254
2255 if (mod == 3 && rm == 0)
2256 pOp = (PCDISOPCODE)&g_aMapX86_Group15_mod11_rm000[reg];
2257 else
2258 pOp = (PCDISOPCODE)&g_aMapX86_Group15_mem[reg];
2259
2260 //little hack to make sure the ModRM byte is included in the returned size
2261 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2262 size = sizeof(uint8_t); //ModRM byte
2263
2264 size += disParseInstruction(uCodePtr, pOp, pCpu);
2265 return size;
2266}
2267//*****************************************************************************
2268//*****************************************************************************
2269unsigned ParseGrp16(RTUINTPTR uCodePtr, PCDISOPCODE pOp, PDISOPPARAM pParam, PDISCPUSTATE pCpu)
2270{
2271 unsigned size = 0, modrm, reg;
2272 NOREF(pParam);
2273
2274 modrm = disReadByte(pCpu, uCodePtr);
2275 reg = MODRM_REG(modrm);
2276
2277 pOp = (PCDISOPCODE)&g_aMapX86_Group16[reg];
2278
2279 //little hack to make sure the ModRM byte is included in the returned size
2280 if (pOp->idxParse1 != IDX_ParseModRM && pOp->idxParse2 != IDX_ParseModRM)
2281 size = sizeof(uint8_t); //ModRM byte
2282
2283 size += disParseInstruction(uCodePtr, pOp, pCpu);
2284 return size;
2285}
2286//*****************************************************************************
2287#if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED)
2288static const char *szModRMReg8[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "SPL", "BPL", "SIL", "DIL"};
2289static const char *szModRMReg16[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"};
2290static const char *szModRMReg32[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"};
2291static const char *szModRMReg64[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"};
2292static const char *szModRMReg1616[8] = {"BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX"};
2293#endif
2294static const char *szModRMSegReg[6] = {"ES", "CS", "SS", "DS", "FS", "GS"};
2295static const int BaseModRMReg16[8] = { DISGREG_BX, DISGREG_BX, DISGREG_BP, DISGREG_BP, DISGREG_SI, DISGREG_DI, DISGREG_BP, DISGREG_BX};
2296static const int IndexModRMReg16[4] = { DISGREG_SI, DISGREG_DI, DISGREG_SI, DISGREG_DI};
2297//*****************************************************************************
2298static void disasmModRMReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam, int fRegAddr)
2299{
2300 int subtype, type, mod;
2301 NOREF(pOp); NOREF(pCpu);
2302
2303 mod = pCpu->ModRM.Bits.Mod;
2304
2305 type = OP_PARM_VTYPE(pParam->param);
2306 subtype = OP_PARM_VSUBTYPE(pParam->param);
2307 if (fRegAddr)
2308 subtype = (pCpu->uAddrMode == DISCPUMODE_64BIT) ? OP_PARM_q : OP_PARM_d;
2309 else
2310 if (subtype == OP_PARM_v || subtype == OP_PARM_NONE)
2311 {
2312 switch (pCpu->uOpMode)
2313 {
2314 case DISCPUMODE_32BIT:
2315 subtype = OP_PARM_d;
2316 break;
2317 case DISCPUMODE_64BIT:
2318 subtype = OP_PARM_q;
2319 break;
2320 case DISCPUMODE_16BIT:
2321 subtype = OP_PARM_w;
2322 break;
2323 default:
2324 /* make gcc happy */
2325 break;
2326 }
2327 }
2328
2329 switch (subtype)
2330 {
2331 case OP_PARM_b:
2332 Assert(idx < (pCpu->fPrefix & DISPREFIX_REX ? 16U : 8U));
2333
2334 /* AH, BH, CH & DH map to DIL, SIL, EBL & SPL when a rex prefix is present. */
2335 /* Intel® 64 and IA-32 Architectures Software Developer’s Manual: 3.4.1.1 */
2336 if ( (pCpu->fPrefix & DISPREFIX_REX)
2337 && idx >= DISGREG_AH
2338 && idx <= DISGREG_BH)
2339 {
2340 idx += (DISGREG_SPL - DISGREG_AH);
2341 }
2342
2343 pParam->fUse |= DISUSE_REG_GEN8;
2344 pParam->base.reg_gen = idx;
2345 break;
2346
2347 case OP_PARM_w:
2348 Assert(idx < (pCpu->fPrefix & DISPREFIX_REX ? 16U : 8U));
2349
2350 pParam->fUse |= DISUSE_REG_GEN16;
2351 pParam->base.reg_gen = idx;
2352 break;
2353
2354 case OP_PARM_d:
2355 Assert(idx < (pCpu->fPrefix & DISPREFIX_REX ? 16U : 8U));
2356
2357 pParam->fUse |= DISUSE_REG_GEN32;
2358 pParam->base.reg_gen = idx;
2359 break;
2360
2361 case OP_PARM_q:
2362 pParam->fUse |= DISUSE_REG_GEN64;
2363 pParam->base.reg_gen = idx;
2364 break;
2365
2366 default:
2367 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype));
2368 pCpu->rc = VERR_DIS_INVALID_MODRM;
2369 break;
2370 }
2371}
2372//*****************************************************************************
2373//*****************************************************************************
2374static void disasmModRMReg16(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam)
2375{
2376 NOREF(pCpu); NOREF(pOp);
2377 pParam->fUse |= DISUSE_REG_GEN16;
2378 pParam->base.reg_gen = BaseModRMReg16[idx];
2379 if (idx < 4)
2380 {
2381 pParam->fUse |= DISUSE_INDEX;
2382 pParam->index.reg_gen = IndexModRMReg16[idx];
2383 }
2384}
2385//*****************************************************************************
2386//*****************************************************************************
2387static void disasmModRMSReg(PDISCPUSTATE pCpu, PCDISOPCODE pOp, unsigned idx, PDISOPPARAM pParam)
2388{
2389 NOREF(pOp);
2390 if (idx >= RT_ELEMENTS(szModRMSegReg))
2391 {
2392 Log(("disasmModRMSReg %d failed!!\n", idx));
2393 pCpu->rc = VERR_DIS_INVALID_PARAMETER;
2394 return;
2395 }
2396
2397 pParam->fUse |= DISUSE_REG_SEG;
2398 pParam->base.reg_seg = (DISSELREG)idx;
2399}
2400
2401
2402/**
2403 * Slow path for storing instruction bytes.
2404 *
2405 * @param pCpu The disassembler state.
2406 * @param uAddress The address.
2407 * @param pbSrc The bytes.
2408 * @param cbSrc The number of bytes.
2409 */
2410DECL_NO_INLINE(static, void)
2411disStoreInstrBytesSlow(PDISCPUSTATE pCpu, RTUINTPTR uAddress, const uint8_t *pbSrc, size_t cbSrc)
2412{
2413 /*
2414 * Figure out which case it is.
2415 */
2416 uint32_t cbInstr = pCpu->cbInstr;
2417 RTUINTPTR off = uAddress - pCpu->uInstrAddr;
2418 if (off < cbInstr)
2419 {
2420 if (off + cbSrc <= cbInstr)
2421 {
2422 AssertMsg(memcmp(&pCpu->abInstr[off], pbSrc, cbSrc) == 0,
2423 ("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
2424 return; /* fully re-reading old stuff. */
2425 }
2426
2427 /* Only partially re-reading stuff, skip ahead and add the rest. */
2428 uint32_t cbAlreadyRead = cbInstr - (uint32_t)off;
2429 Assert(memcmp(&pCpu->abInstr[off], pbSrc, cbAlreadyRead) == 0);
2430 uAddress += cbAlreadyRead;
2431 pbSrc += cbAlreadyRead;
2432 cbSrc -= cbAlreadyRead;
2433 }
2434
2435 if (off >= sizeof(cbInstr))
2436 {
2437 /* The instruction is too long! This shouldn't happen. */
2438 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
2439 return;
2440 }
2441 else if (off > cbInstr)
2442 {
2443 /* Mind the gap - this shouldn't happen, but read the gap bytes if it does. */
2444 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.16Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr));
2445 uint32_t cbGap = off - cbInstr;
2446 int rc = pCpu->pfnReadBytes(pCpu, &pCpu->abInstr[cbInstr], uAddress - cbGap, cbGap);
2447 if (RT_FAILURE(rc))
2448 {
2449 pCpu->rc = VERR_DIS_MEM_READ;
2450 RT_BZERO(&pCpu->abInstr[cbInstr], cbGap);
2451 }
2452 pCpu->cbInstr = cbInstr = off;
2453 }
2454
2455 /*
2456 * Copy the bytes.
2457 */
2458 if (off + cbSrc <= sizeof(pCpu->abInstr))
2459 {
2460 memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbSrc);
2461 pCpu->cbInstr = cbInstr + (uint32_t)cbSrc;
2462 }
2463 else
2464 {
2465 size_t cbToCopy = sizeof(pCpu->abInstr) - off;
2466 memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbToCopy);
2467 pCpu->cbInstr = sizeof(pCpu->abInstr);
2468 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, sizeof(pCpu->abInstr), pCpu->abInstr));
2469 }
2470}
2471
2472DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
2473{
2474#ifdef IN_RING0
2475 AssertMsgFailed(("disReadWord with no read callback in ring 0!!\n"));
2476 RT_BZERO(pbDst, cbToRead);
2477 return VERR_DIS_NO_READ_CALLBACK;
2478#else
2479 memcpy(pbDst, (void const *)(uintptr_t)uSrcAddr, cbToRead);
2480 return VINF_SUCCESS;
2481#endif
2482}
2483
2484//*****************************************************************************
2485/* Read functions for getting the opcode bytes */
2486//*****************************************************************************
2487uint8_t disReadByte(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2488{
2489 uint8_t bTemp = 0;
2490 int rc = pCpu->pfnReadBytes(pCpu, &bTemp, uAddress, sizeof(bTemp));
2491 if (RT_FAILURE(rc))
2492 {
2493 Log(("disReadByte failed!!\n"));
2494 pCpu->rc = VERR_DIS_MEM_READ;
2495 }
2496
2497/** @todo change this into reading directly into abInstr and use it as a
2498 * cache. */
2499 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->cbInstr == uAddress
2500 && pCpu->cbInstr + sizeof(bTemp) < sizeof(pCpu->abInstr)))
2501 pCpu->abInstr[pCpu->cbInstr++] = bTemp;
2502 else
2503 disStoreInstrBytesSlow(pCpu, uAddress, &bTemp, sizeof(bTemp));
2504
2505 return bTemp;
2506}
2507//*****************************************************************************
2508//*****************************************************************************
2509uint16_t disReadWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2510{
2511 RTUINT16U uTemp;
2512 uTemp.u = 0;
2513 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
2514 if (RT_FAILURE(rc))
2515 {
2516 Log(("disReadWord failed!!\n"));
2517 pCpu->rc = VERR_DIS_MEM_READ;
2518 }
2519
2520 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->cbInstr == uAddress
2521 && pCpu->cbInstr + sizeof(uTemp) < sizeof(pCpu->abInstr)))
2522 {
2523 pCpu->abInstr[pCpu->cbInstr ] = uTemp.au8[0];
2524 pCpu->abInstr[pCpu->cbInstr + 1] = uTemp.au8[1];
2525 pCpu->cbInstr += 2;
2526 }
2527 else
2528 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
2529
2530 return uTemp.u;
2531}
2532//*****************************************************************************
2533//*****************************************************************************
2534uint32_t disReadDWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2535{
2536 RTUINT32U uTemp;
2537 uTemp.u = 0;
2538 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
2539 if (RT_FAILURE(rc))
2540 {
2541 Log(("disReadDWord failed!!\n"));
2542 pCpu->rc = VERR_DIS_MEM_READ;
2543 }
2544
2545 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->cbInstr == uAddress
2546 && pCpu->cbInstr + sizeof(uTemp) < sizeof(pCpu->abInstr)))
2547 {
2548 pCpu->abInstr[pCpu->cbInstr ] = uTemp.au8[0];
2549 pCpu->abInstr[pCpu->cbInstr + 1] = uTemp.au8[1];
2550 pCpu->abInstr[pCpu->cbInstr + 2] = uTemp.au8[2];
2551 pCpu->abInstr[pCpu->cbInstr + 3] = uTemp.au8[3];
2552 pCpu->cbInstr += 4;
2553 }
2554 else
2555 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
2556
2557 return uTemp.u;
2558}
2559//*****************************************************************************
2560//*****************************************************************************
2561uint64_t disReadQWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress)
2562{
2563 RTUINT64U uTemp;
2564 uTemp.u = 0;
2565 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp));
2566 if (RT_FAILURE(rc))
2567 {
2568 Log(("disReadQWord %x failed!!\n", uAddress));
2569 pCpu->rc = VERR_DIS_MEM_READ;
2570 }
2571
2572 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->cbInstr == uAddress
2573 && pCpu->cbInstr + sizeof(uTemp) < sizeof(pCpu->abInstr)))
2574 {
2575 pCpu->abInstr[pCpu->cbInstr ] = uTemp.au8[0];
2576 pCpu->abInstr[pCpu->cbInstr + 1] = uTemp.au8[1];
2577 pCpu->abInstr[pCpu->cbInstr + 2] = uTemp.au8[2];
2578 pCpu->abInstr[pCpu->cbInstr + 3] = uTemp.au8[3];
2579 pCpu->abInstr[pCpu->cbInstr + 4] = uTemp.au8[4];
2580 pCpu->abInstr[pCpu->cbInstr + 5] = uTemp.au8[5];
2581 pCpu->abInstr[pCpu->cbInstr + 6] = uTemp.au8[6];
2582 pCpu->abInstr[pCpu->cbInstr + 7] = uTemp.au8[7];
2583 pCpu->cbInstr += 8;
2584 }
2585 else
2586 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp));
2587
2588 return uTemp.u;
2589}
2590
2591
2592/**
2593 * Validates the lock sequence.
2594 *
2595 * The AMD manual lists the following instructions:
2596 * ADC
2597 * ADD
2598 * AND
2599 * BTC
2600 * BTR
2601 * BTS
2602 * CMPXCHG
2603 * CMPXCHG8B
2604 * CMPXCHG16B
2605 * DEC
2606 * INC
2607 * NEG
2608 * NOT
2609 * OR
2610 * SBB
2611 * SUB
2612 * XADD
2613 * XCHG
2614 * XOR
2615 *
2616 * @param pCpu Fully disassembled instruction.
2617 */
2618static void disValidateLockSequence(PDISCPUSTATE pCpu)
2619{
2620 Assert(pCpu->fPrefix & DISPREFIX_LOCK);
2621
2622 /*
2623 * Filter out the valid lock sequences.
2624 */
2625 switch (pCpu->pCurInstr->uOpcode)
2626 {
2627 /* simple: no variations */
2628 case OP_CMPXCHG8B: /* == OP_CMPXCHG16B? */
2629 return;
2630
2631 /* simple: /r - reject register destination. */
2632 case OP_BTC:
2633 case OP_BTR:
2634 case OP_BTS:
2635 case OP_CMPXCHG:
2636 case OP_XADD:
2637 if (pCpu->ModRM.Bits.Mod == 3)
2638 break;
2639 return;
2640
2641 /*
2642 * Lots of variants but its sufficient to check that param 1
2643 * is a memory operand.
2644 */
2645 case OP_ADC:
2646 case OP_ADD:
2647 case OP_AND:
2648 case OP_DEC:
2649 case OP_INC:
2650 case OP_NEG:
2651 case OP_NOT:
2652 case OP_OR:
2653 case OP_SBB:
2654 case OP_SUB:
2655 case OP_XCHG:
2656 case OP_XOR:
2657 if (pCpu->param1.fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32
2658 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT8 | DISUSE_RIPDISPLACEMENT32))
2659 return;
2660 break;
2661
2662 default:
2663 break;
2664 }
2665
2666 /*
2667 * Invalid lock sequence, make it a OP_ILLUD2.
2668 */
2669 pCpu->pCurInstr = &g_aTwoByteMapX86[11];
2670 Assert(pCpu->pCurInstr->uOpcode == OP_ILLUD2);
2671}
2672
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