tstDisasm-2.cpp revision 8599686860198730ae53d5895386d1b57dbc060e
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/* $Id$ */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/** @file
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Testcase - Generic Disassembler Tool.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * available from http://www.virtualbox.org. This file is free software;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * General Public License (GPL) as published by the Free Software
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * additional information or have any questions.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/*******************************************************************************
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync* Header Files *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync*******************************************************************************/
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync#include <VBox/dis.h>
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync#include <iprt/stream.h>
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync#include <iprt/getopt.h>
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync#include <iprt/file.h>
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync#include <iprt/string.h>
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync#include <iprt/runtime.h>
8599686860198730ae53d5895386d1b57dbc060evboxsync#include <VBox/err.h>
8599686860198730ae53d5895386d1b57dbc060evboxsync#include <iprt/ctype.h>
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/*******************************************************************************
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync* Structures and Typedefs *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync*******************************************************************************/
8599686860198730ae53d5895386d1b57dbc060evboxsynctypedef enum { kAsmStyle_Default, kAsmStyle_yasm, kAsmStyle_masm, kAsmStyle_gas, kAsmStyle_invalid } ASMSTYLE;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsynctypedef enum { kUndefOp_Fail, kUndefOp_All, kUndefOp_DefineByte, kUndefOp_End } UNDEFOPHANDLING;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsynctypedef struct MYDISSTATE
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync DISCPUSTATE Cpu;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint64_t uAddress; /**< The current instruction address. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint8_t *pbInstr; /**< The current instruction (pointer). */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint32_t cbInstr; /**< The size of the current instruction. */
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync bool fUndefOp; /**< Whether the current instruction is really an undefined opcode.*/
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync UNDEFOPHANDLING enmUndefOp; /**< How to treat undefined opcodes. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int rc; /**< Set if we hit EOF. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync size_t cbLeft; /**< The number of bytes left. (read) */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint8_t *pbNext; /**< The next byte. (read) */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint64_t uNextAddr; /**< The address of the next byte. (read) */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync char szLine[256]; /**< The disassembler text output. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync} MYDISSTATE;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsynctypedef MYDISSTATE *PMYDISSTATE;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync/*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Non-logging builds doesn't to full formatting so we must do it on our own.
8599686860198730ae53d5895386d1b57dbc060evboxsync * This should probably be moved into the disassembler later as it's needed for
8599686860198730ae53d5895386d1b57dbc060evboxsync * the vbox debugger as well.
8599686860198730ae53d5895386d1b57dbc060evboxsync *
8599686860198730ae53d5895386d1b57dbc060evboxsync * Comment in USE_MY_FORMATTER to enable it.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync#define USE_MY_FORMATTER
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync#ifdef USE_MY_FORMATTER
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegGen8x86[8][4] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "al\0", "cl\0", "dl\0", "bl\0", "ah\0", "ch\0", "dh\0", "bh\0"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegGen8Amd64[16][5] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "al\0\0", "cl\0\0", "dl\0\0", "bl\0\0", "spb\0", "bpb\0", "sib\0", "dib\0", "r8b\0", "r9b\0", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegGen16[16][5] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "ax\0\0", "cx\0\0", "dx\0\0", "bx\0\0", "sp\0\0", "bp\0\0", "si\0\0", "di\0\0", "r8w\0", "r9w\0", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegGen1616[8][6] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "bx+si", "bx+di", "bp+si", "bp+di", "si\0\0\0", "di\0\0\0", "bp\0\0\0", "bx\0\0\0"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegGen32[16][5] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "eax\0", "ecx\0", "edx\0", "ebx\0", "esp\0", "ebp\0", "esi\0", "edi\0", "r8d\0", "r9d\0", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegGen64[16][4] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8\0", "r9\0", "r10", "r11", "r12", "r13", "r14", "r15"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegSeg[6][3] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "es", "cs", "ss", "ds", "fs", "gs"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegFP[8][4] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegMMX[8][4] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegXMM[16][6] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "xmm0\0", "xmm1\0", "xmm2\0", "xmm3\0", "xmm4\0", "xmm5\0", "xmm6\0", "xmm7\0", "xmm8\0", "xmm9\0", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegCRx[16][5] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "cr0\0", "cr1\0", "cr2\0", "cr3\0", "cr4\0", "cr5\0", "cr6\0", "cr7\0", "cr8\0", "cr9\0", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegDRx[16][5] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "dr0\0", "dr1\0", "dr2\0", "dr3\0", "dr4\0", "dr5\0", "dr6\0", "dr7\0", "dr8\0", "dr9\0", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic const char g_aszYasmRegTRx[16][5] =
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync "tr0\0", "tr1\0", "tr2\0", "tr3\0", "tr4\0", "tr5\0", "tr6\0", "tr7\0", "tr8\0", "tr9\0", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15"
8599686860198730ae53d5895386d1b57dbc060evboxsync};
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsyncDECLINLINE(const char *) MyDisasYasmFormatBaseReg(DISCPUSTATE const *pCpu, PCOP_PARAMETER pParam, size_t *pcchReg, bool fReg1616)
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & ( USE_REG_GEN8 | USE_REG_GEN16 | USE_REG_GEN32 | USE_REG_GEN64
8599686860198730ae53d5895386d1b57dbc060evboxsync | USE_REG_FP | USE_REG_MMX | USE_REG_XMM | USE_REG_CR
8599686860198730ae53d5895386d1b57dbc060evboxsync | USE_REG_DBG | USE_REG_SEG | USE_REG_TEST))
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_GEN8:
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->opmode == CPUMODE_64BIT)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen8Amd64));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen8Amd64[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen8x86));
8599686860198730ae53d5895386d1b57dbc060evboxsync return g_aszYasmRegGen8x86[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_GEN16:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fReg1616)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen1616));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen1616[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = psz[2] ? 5 : 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen16[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_GEN32:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen32[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_GEN64:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen64[pParam->base.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_FP:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_fp < RT_ELEMENTS(g_aszYasmRegFP));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegFP[pParam->base.reg_fp];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_MMX:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_mmx < RT_ELEMENTS(g_aszYasmRegMMX));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegMMX[pParam->base.reg_mmx];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_XMM:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_xmm < RT_ELEMENTS(g_aszYasmRegXMM));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegXMM[pParam->base.reg_mmx];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 4 + !!psz[4];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_CR:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_ctrl < RT_ELEMENTS(g_aszYasmRegCRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegCRx[pParam->base.reg_ctrl];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_DBG:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_dbg < RT_ELEMENTS(g_aszYasmRegDRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegDRx[pParam->base.reg_dbg];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_SEG:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_seg < RT_ELEMENTS(g_aszYasmRegCRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegSeg[pParam->base.reg_seg];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_REG_TEST:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->base.reg_test < RT_ELEMENTS(g_aszYasmRegTRx));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegTRx[pParam->base.reg_test];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsgFailed(("%#x\n", pParam->flags));
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return "r??";
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync}
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsyncDECLINLINE(const char *) MyDisasYasmFormatIndexReg(DISCPUSTATE const *pCpu, PCOP_PARAMETER pParam, size_t *pcchReg)
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pCpu->addrmode)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case CPUMODE_16BIT:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen16[pParam->index.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case CPUMODE_32BIT:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen32[pParam->index.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case CPUMODE_64BIT:
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *psz = g_aszYasmRegGen64[pParam->index.reg_gen];
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 2 + !!psz[2] + !!psz[3];
8599686860198730ae53d5895386d1b57dbc060evboxsync return psz;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsgFailed(("%#x %#x\n", pParam->flags, pCpu->addrmode));
8599686860198730ae53d5895386d1b57dbc060evboxsync *pcchReg = 3;
8599686860198730ae53d5895386d1b57dbc060evboxsync return "r??";
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync}
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic size_t MyDisasYasmFormat(DISCPUSTATE const *pCpu, char *pszBuf, size_t cchBuf)
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync PCOPCODE const pOp = pCpu->pCurInstr;
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchOutput = 0;
8599686860198730ae53d5895386d1b57dbc060evboxsync char *pszDst = pszBuf;
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchDst = cchBuf;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* output macros */
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_C(ch) \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchOutput++; \
8599686860198730ae53d5895386d1b57dbc060evboxsync if (cchDst > 1) \
8599686860198730ae53d5895386d1b57dbc060evboxsync { \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchDst--; \
8599686860198730ae53d5895386d1b57dbc060evboxsync *pszDst++ = (ch); \
8599686860198730ae53d5895386d1b57dbc060evboxsync } \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_STR(pszSrc, cchSrc) \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchOutput += (cchSrc); \
8599686860198730ae53d5895386d1b57dbc060evboxsync if (cchDst > (cchSrc)) \
8599686860198730ae53d5895386d1b57dbc060evboxsync { \
8599686860198730ae53d5895386d1b57dbc060evboxsync memcpy(pszDst, (pszSrc), (cchSrc)); \
8599686860198730ae53d5895386d1b57dbc060evboxsync pszDst += (cchSrc); \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchDst -= (cchSrc); \
8599686860198730ae53d5895386d1b57dbc060evboxsync } \
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (cchDst > 1) \
8599686860198730ae53d5895386d1b57dbc060evboxsync { \
8599686860198730ae53d5895386d1b57dbc060evboxsync memcpy(pszDst, (pszSrc), cchDst - 1); \
8599686860198730ae53d5895386d1b57dbc060evboxsync pszDst += cchDst - 1; \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchDst = 1; \
8599686860198730ae53d5895386d1b57dbc060evboxsync } \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_SZ(sz) \
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR((sz), sizeof(sz) - 1)
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_PSZ(psz) \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { const size_t cchTmp = strlen(psz); PUT_STR((psz), cchTmp); } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM(cch, fmt, num) \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchOutput += (cch); \
8599686860198730ae53d5895386d1b57dbc060evboxsync if (cchBuf > 1) \
8599686860198730ae53d5895386d1b57dbc060evboxsync { \
8599686860198730ae53d5895386d1b57dbc060evboxsync const size_t cchTmp = RTStrPrintf(pszDst, cchBuf, fmt, (num)); \
8599686860198730ae53d5895386d1b57dbc060evboxsync pszDst += cchTmp; \
8599686860198730ae53d5895386d1b57dbc060evboxsync cchBuf -= cchTmp; \
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(cchTmp == (cch) || cchBuf == 1); \
8599686860198730ae53d5895386d1b57dbc060evboxsync } \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_8(num) PUT_NUM(4, "0%02xh", (uint8_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_16(num) PUT_NUM(6, "0%04xh", (uint16_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_32(num) PUT_NUM(10, "0%08xh", (uint32_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_NUM_64(num) PUT_NUM(18, "0%08xh", (uint64_t)(num))
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Filter out invalid opcodes first as they need special
8599686860198730ae53d5895386d1b57dbc060evboxsync * treatment. UD2 is an exception and should be handled normally.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pOp->opcode == OP_INVALID
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( pOp->opcode == OP_ILLUD2
8599686860198730ae53d5895386d1b57dbc060evboxsync && (pCpu->prefix & PREFIX_LOCK)))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Prefixes
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->prefix & PREFIX_LOCK)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("lock ");
8599686860198730ae53d5895386d1b57dbc060evboxsync if(pCpu->prefix & PREFIX_REP)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("rep ");
8599686860198730ae53d5895386d1b57dbc060evboxsync else if(pCpu->prefix & PREFIX_REPNE)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("repne ");
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Adjust the format string to avoid stuff the assembler cannot handle.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync char szTmpFmt[48];
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszFmt = pOp->pszOpcode;
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pOp->opcode)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_JECXZ:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "jcxz %Jb" : pCpu->opmode == CPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PUSHF:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "pushfw" : pCpu->opmode == CPUMODE_32BIT ? "pushfd" : "pushfq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_POPF:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "popfw" : pCpu->opmode == CPUMODE_32BIT ? "popfd" : "popfq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_INSB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "insb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_INSWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "insw" : pCpu->opmode == CPUMODE_32BIT ? "insd" : "insq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_OUTSB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "outsb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_OUTSWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "outsw" : pCpu->opmode == CPUMODE_32BIT ? "outsd" : "outsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_MOVSB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "movsb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_MOVSWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "movsw" : pCpu->opmode == CPUMODE_32BIT ? "movsd" : "movsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_CMPSB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "cmpsb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_CMPWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cmpsw" : pCpu->opmode == CPUMODE_32BIT ? "cmpsd" : "cmpsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SCASB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "scasb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SCASWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "scasw" : pCpu->opmode == CPUMODE_32BIT ? "scasd" : "scasq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_LODSB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "lodsb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_LODSWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "lodsw" : pCpu->opmode == CPUMODE_32BIT ? "lodsd" : "lodsq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_STOSB:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "stosb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_STOSWD:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "stosw" : pCpu->opmode == CPUMODE_32BIT ? "stosd" : "stosq";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SHL:
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pszFmt[3] == '/');
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += 4;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_XLAT:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "xlatb";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_INT3:
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "int3";
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Don't know how to tell yasm to generate complicated nop stuff, so 'db' it.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_NOP:
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->opcode == 0x90)
8599686860198730ae53d5895386d1b57dbc060evboxsync /* fine, fine */;
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pszFmt[sizeof("nop %Ev")] == '/' && pszFmt[sizeof("nop %Ev") + 1] == 'p')
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "prefetch %Eb";
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pCpu->opcode == 0x1f)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("db 01fh,");
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_8(pCpu->ModRM.u);
8599686860198730ae53d5895386d1b57dbc060evboxsync for (unsigned i = 2; i < pCpu->opsize; i++)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(',');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_8(0x90); ///@todo fixme.
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = "";
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync /* ST(X) -> stX (floating point) */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (*pszFmt == 'f' && strchr(pszFmt, '('))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync char *pszFmtDst = szTmpFmt;
8599686860198730ae53d5895386d1b57dbc060evboxsync char ch;
8599686860198730ae53d5895386d1b57dbc060evboxsync do
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync ch = *pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync if (ch == 'S' && pszFmt[0] == 'T' && pszFmt[1] == '(')
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync *pszFmtDst++ = 's';
8599686860198730ae53d5895386d1b57dbc060evboxsync *pszFmtDst++ = 't';
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync ch = *pszFmt;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pszFmt[1] == ')');
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync *pszFmtDst++ = ch;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync *pszFmtDst++ = ch;
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (ch != '\0');
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt = szTmpFmt;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Horrible hacks.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_FLD:
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->opcode == 0xdb) /* m80fp workaround. */
8599686860198730ae53d5895386d1b57dbc060evboxsync *(int *)&pCpu->param1.param &= ~0x1f; /* make it pure OP_PARM_M */
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_LAR: /* hack w -> v, probably not correct. */
8599686860198730ae53d5895386d1b57dbc060evboxsync *(int *)&pCpu->param2.param &= ~0x1f;
8599686860198730ae53d5895386d1b57dbc060evboxsync *(int *)&pCpu->param2.param |= OP_PARM_v;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Formatting context and associated macros.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync PCOP_PARAMETER pParam = &pCpu->param1;
8599686860198730ae53d5895386d1b57dbc060evboxsync int iParam = 1;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_FAR() \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { \
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p \
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LDS /* table bugs? */ \
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LES \
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LFS \
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LGS \
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LSS ) \
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("far "); \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync /** @todo mov ah,ch ends up with a byte 'override'... */
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_SIZE_OVERRIDE() \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { \
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (OP_PARM_VSUBTYPE(pParam->param)) \
8599686860198730ae53d5895386d1b57dbc060evboxsync { \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_v: \
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pCpu->opmode) \
8599686860198730ae53d5895386d1b57dbc060evboxsync { \
8599686860198730ae53d5895386d1b57dbc060evboxsync case CPUMODE_16BIT: PUT_SZ("word "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case CPUMODE_32BIT: PUT_SZ("dword "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case CPUMODE_64BIT: PUT_SZ("qword "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync default: break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync } \
8599686860198730ae53d5895386d1b57dbc060evboxsync break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_b: PUT_SZ("byte "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_w: PUT_SZ("word "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_d: PUT_SZ("dword "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_q: PUT_SZ("qword "); break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_dq: \
8599686860198730ae53d5895386d1b57dbc060evboxsync if (OP_PARM_VTYPE(pParam->param) != OP_PARM_W) /* these are 128 bit, pray they are all unambiguous.. */ \
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("qword "); \
8599686860198730ae53d5895386d1b57dbc060evboxsync break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_p: break; /* see PUT_FAR */ \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_s: if (pParam->flags & USE_REG_FP) PUT_SZ("tword "); break; /* ?? */ \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_z: break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_PARM_NONE: \
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( OP_PARM_VTYPE(pParam->param) == OP_PARM_M \
8599686860198730ae53d5895386d1b57dbc060evboxsync && ((pParam->flags & USE_REG_FP) || pOp->opcode == OP_FLD)) \
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("tword "); \
8599686860198730ae53d5895386d1b57dbc060evboxsync break; \
8599686860198730ae53d5895386d1b57dbc060evboxsync default: break; /*no pointer type specified/necessary*/ \
8599686860198730ae53d5895386d1b57dbc060evboxsync } \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync static const char s_szSegPrefix[6][4] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
8599686860198730ae53d5895386d1b57dbc060evboxsync#define PUT_SEGMENT_OVERRIDE() \
8599686860198730ae53d5895386d1b57dbc060evboxsync do { \
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->prefix & PREFIX_SEG) \
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR(s_szSegPrefix[pCpu->prefix_seg], 3); \
8599686860198730ae53d5895386d1b57dbc060evboxsync } while (0)
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * The formatting loop.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync char ch;
8599686860198730ae53d5895386d1b57dbc060evboxsync while ((ch = *pszFmt++) != '\0')
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (ch == '%')
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync ch = *pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (ch)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * ModRM - Register only.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'C': /* Control register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'D': /* Debug register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'G': /* ModRM selects general register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'S': /* ModRM byte selects a segment register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'T': /* ModRM byte selects a test register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'V': /* ModRM byte selects an XMM/SSE register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'P': /* ModRM byte selects MMX register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(!(pParam->flags & (USE_INDEX | USE_SCALE) /* No SIB here... */));
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(!(pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32)));
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchReg;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0 /* pCpu->addrmode == CPUMODE_16BIT */);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR(pszReg, cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * ModRM - Register or memory.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'E': /* ModRM specifies parameter (ParseModRM / UseModRM / UseSIB). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'Q': /* ModRM byte selects MMX register or memory address (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'R': /* ModRM byte may only refer to a general register (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'W': /* ModRM byte selects an XMM/SSE register or a memory address (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'M': /* ModRM may only refer to memory (ParseModRM / UseModRM). */
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_FAR();
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Work around mov seg,[mem16] and mov [mem16],seg as these always make a 16-bit mem
8599686860198730ae53d5895386d1b57dbc060evboxsync while the register variants deals with 16, 32 & 64 in the normal fashion. */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pParam->param != OP_PARM_Ev
8599686860198730ae53d5895386d1b57dbc060evboxsync || pOp->opcode != OP_MOV
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( pOp->param1 != OP_PARM_Sw
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->param2 != OP_PARM_Sw))
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SIZE_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C('[');
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (pParam->flags & USE_DISPLACEMENT8)
8599686860198730ae53d5895386d1b57dbc060evboxsync && !pParam->disp8)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("byte ");
8599686860198730ae53d5895386d1b57dbc060evboxsync else if ( (pParam->flags & USE_DISPLACEMENT16)
8599686860198730ae53d5895386d1b57dbc060evboxsync && (int8_t)pParam->disp16 == (int16_t)pParam->disp16)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("word ");
8599686860198730ae53d5895386d1b57dbc060evboxsync else if ( (pParam->flags & USE_DISPLACEMENT32)
8599686860198730ae53d5895386d1b57dbc060evboxsync && (int8_t)pParam->disp32 == (int32_t)pParam->disp32)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("dword ");
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SEGMENT_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fBase = (pParam->flags & USE_BASE) /* When exactly is USE_BASE supposed to be set? disasmModRMReg doesn't set it. */
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( (pParam->flags & (USE_REG_GEN8 | USE_REG_GEN16 | USE_REG_GEN32 | USE_REG_GEN64))
8599686860198730ae53d5895386d1b57dbc060evboxsync && !(pParam->flags & USE_EFFICIENT_ADDRESS));
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fBase)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchReg;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0 /*pCpu->addrmode == CPUMODE_16BIT*/);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR(pszReg, cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_INDEX)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fBase)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C('+');
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchReg;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatIndexReg(pCpu, pParam, &cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR(pszReg, cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_SCALE)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C('*');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C('0' + pParam->scale);
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(!(pParam->flags & USE_SCALE));
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(!(pParam->flags & USE_DISPLACEMENT64));
8599686860198730ae53d5895386d1b57dbc060evboxsync int32_t off;
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_DISPLACEMENT8)
8599686860198730ae53d5895386d1b57dbc060evboxsync off = pParam->disp8;
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pParam->flags & USE_DISPLACEMENT16)
8599686860198730ae53d5895386d1b57dbc060evboxsync off = pParam->disp16;
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pParam->flags & (USE_DISPLACEMENT32 | USE_RIPDISPLACEMENT32))
8599686860198730ae53d5895386d1b57dbc060evboxsync off = pParam->disp32;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fBase || (pParam->flags & USE_INDEX))
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(off >= 0 ? '+' : '-');
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (off < 0)
8599686860198730ae53d5895386d1b57dbc060evboxsync off = -off;
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_DISPLACEMENT8)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_8( off);
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pParam->flags & USE_DISPLACEMENT16)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(off);
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pParam->flags & USE_DISPLACEMENT32)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(off);
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(off);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ(" wrt rip"); //??
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(']');
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'F': /* Eflags register (0 - popf/pushf only, avoided in adjustments above). */
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertFailed();
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v' || *pszFmt == 'w' || *pszFmt == 'z'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & ( USE_IMMEDIATE8 | USE_IMMEDIATE16 | USE_IMMEDIATE32 | USE_IMMEDIATE64
8599686860198730ae53d5895386d1b57dbc060evboxsync | USE_IMMEDIATE16_SX8 | USE_IMMEDIATE32_SX8))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE8:
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (pOp->param1 >= OP_PARM_REG_GEN8_START && pOp->param1 <= OP_PARM_REG_GEN8_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param2 >= OP_PARM_REG_GEN8_START && pOp->param2 <= OP_PARM_REG_GEN8_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync )
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict byte ");
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_8(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE16:
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (int8_t)pParam->parval == (int16_t)pParam->parval
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param1 >= OP_PARM_REG_GEN16_START && pOp->param1 <= OP_PARM_REG_GEN16_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param2 >= OP_PARM_REG_GEN16_START && pOp->param2 <= OP_PARM_REG_GEN16_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync )
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_b)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict byte ");
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict word ");
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE16_SX8:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict byte ");
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE32:
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( (int8_t)pParam->parval == (int32_t)pParam->parval
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param1 >= OP_PARM_REG_GEN32_START && pOp->param1 <= OP_PARM_REG_GEN32_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync || (pOp->param2 >= OP_PARM_REG_GEN32_START && pOp->param2 <= OP_PARM_REG_GEN32_END)
8599686860198730ae53d5895386d1b57dbc060evboxsync )
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_b)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict byte ");
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict dword ");
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE32_SX8:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("strict byte ");
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE64:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_64(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertFailed();
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'J': /* Relative jump offset (ParseImmBRel + ParseImmVRel). */
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync int32_t offDisplacement;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(iParam == 1);
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fPrefix = pOp->opcode != OP_CALL
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LOOP
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LOOPE
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_LOOPNE
8599686860198730ae53d5895386d1b57dbc060evboxsync && pOp->opcode != OP_JECXZ;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_IMMEDIATE8_REL)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fPrefix)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("short ");
8599686860198730ae53d5895386d1b57dbc060evboxsync offDisplacement = (int8_t)pParam->parval;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pParam->flags & USE_IMMEDIATE16_REL)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fPrefix)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("near ");
8599686860198730ae53d5895386d1b57dbc060evboxsync offDisplacement = (int16_t)pParam->parval;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'v'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fPrefix)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("near ");
8599686860198730ae53d5895386d1b57dbc060evboxsync offDisplacement = (int32_t)pParam->parval;
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pParam->flags & USE_IMMEDIATE32_REL);
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'v'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync RTUINTPTR uTrgAddr = pCpu->opaddr + pCpu->opsize + offDisplacement;
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->mode == CPUMODE_16BIT)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(uTrgAddr);
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (pCpu->mode == CPUMODE_32BIT)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(uTrgAddr);
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_64(uTrgAddr);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'A': /* Direct (jump/call) address (ParseImmAddr). */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'p'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_FAR();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SIZE_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SEGMENT_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE_ADDR_16_16:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval >> 16);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(':');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE_ADDR_16_32:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval >> 32);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(':');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_DISPLACEMENT16:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_DISPLACEMENT32:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_DISPLACEMENT64:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_64(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertFailed();
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'O': /* No ModRM byte (ParseImmAddr). */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_FAR();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SIZE_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C('[');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SEGMENT_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE_ADDR_16_16:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval >> 16);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(':');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_IMMEDIATE_ADDR_16_32:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->parval >> 32);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(':');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(pParam->parval);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_DISPLACEMENT16:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_16(pParam->disp16);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_DISPLACEMENT32:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_32(pParam->disp32);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case USE_DISPLACEMENT64:
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_NUM_64(pParam->disp64);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertFailed();
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(']');
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'X': /* DS:SI (ParseXb, ParseXv). */
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'Y': /* ES:DI (ParseYb, ParseYv). */
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_FAR();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SIZE_OVERRIDE();
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C('[');
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pParam->flags & USE_POINTER_DS_BASED)
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("ds:");
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_SZ("es:");
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchReg;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR(pszReg, cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(']');
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 'e': /* Register based on operand size (e.g. %eAX) (ParseFixedReg). */
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2])); pszFmt += 2;
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cchReg;
8599686860198730ae53d5895386d1b57dbc060evboxsync const char *pszReg = MyDisasYasmFormatBaseReg(pCpu, pParam, &cchReg, 0);
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_STR(pszReg, cchReg);
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsgFailed(("%c%s!\n", ch, pszFmt));
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsg(*pszFmt == ',' || *pszFmt == '\0', ("%c%s\n", ch, pszFmt));
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(ch);
8599686860198730ae53d5895386d1b57dbc060evboxsync if (ch == ',')
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(*pszFmt != ' ');
8599686860198730ae53d5895386d1b57dbc060evboxsync PUT_C(' ');
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (++iParam)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case 2: pParam = &pCpu->param2; break;
8599686860198730ae53d5895386d1b57dbc060evboxsync case 3: pParam = &pCpu->param3; break;
8599686860198730ae53d5895386d1b57dbc060evboxsync default: pParam = NULL; break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync } /* while more to format */
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Terminate it - on overflow we'll have reserved one byte for this. */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (cchDst > 0)
8599686860198730ae53d5895386d1b57dbc060evboxsync *pszDst = '\0';
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* clean up macros */
8599686860198730ae53d5895386d1b57dbc060evboxsync#undef PUT_PSZ
8599686860198730ae53d5895386d1b57dbc060evboxsync#undef PUT_SZ
8599686860198730ae53d5895386d1b57dbc060evboxsync#undef PUT_STR
8599686860198730ae53d5895386d1b57dbc060evboxsync#undef PUT_C
8599686860198730ae53d5895386d1b57dbc060evboxsync return cchOutput;
8599686860198730ae53d5895386d1b57dbc060evboxsync}
8599686860198730ae53d5895386d1b57dbc060evboxsync#endif
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/**
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Default style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pState The disassembler state.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic void MyDisasDefaultFormatter(PMYDISSTATE pState)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s", pState->szLine);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/**
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Yasm style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pState The disassembler state.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic void MyDisasYasmFormatter(PMYDISSTATE pState)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync char szTmp[256];
8599686860198730ae53d5895386d1b57dbc060evboxsync#ifndef USE_MY_FORMATTER
8599686860198730ae53d5895386d1b57dbc060evboxsync /* a very quick hack. */
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync strcpy(szTmp, RTStrStripL(strchr(pState->szLine, ':') + 1));
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync char *psz = strrchr(szTmp, '[');
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync *psz = '\0';
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrStripR(szTmp);
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync psz = strstr(szTmp, " ptr ");
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync if (psz)
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync memset(psz, ' ', 5);
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync char *pszEnd = strchr(szTmp, '\0');
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync while (pszEnd - &szTmp[0] < 71)
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync *pszEnd++ = ' ';
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync *pszEnd = '\0';
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync#else /* USE_MY_FORMATTER */
8599686860198730ae53d5895386d1b57dbc060evboxsync size_t cch = MyDisasYasmFormat(&pState->Cpu, szTmp, sizeof(szTmp));
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(cch < sizeof(szTmp));
8599686860198730ae53d5895386d1b57dbc060evboxsync while (cch < 71)
8599686860198730ae53d5895386d1b57dbc060evboxsync szTmp[cch++] = ' ';
8599686860198730ae53d5895386d1b57dbc060evboxsync szTmp[cch] = '\0';
8599686860198730ae53d5895386d1b57dbc060evboxsync#endif /* USE_MY_FORMATTER */
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(" %s ; %08llu %s", szTmp, pState->uAddress, pState->szLine);
8599686860198730ae53d5895386d1b57dbc060evboxsync}
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync/**
8599686860198730ae53d5895386d1b57dbc060evboxsync * Checks if the encoding of the current instruction is something
8599686860198730ae53d5895386d1b57dbc060evboxsync * we can never get the assembler to produce.
8599686860198730ae53d5895386d1b57dbc060evboxsync *
8599686860198730ae53d5895386d1b57dbc060evboxsync * @returns true if it's odd, false if it isn't.
8599686860198730ae53d5895386d1b57dbc060evboxsync * @param pCpu The disassembler output.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic bool MyDisasYasmFormatterIsOddEncoding(PMYDISSTATE pState)
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pState->Cpu.addrmode != CPUMODE_16BIT ///@todo correct?
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.ModRM.Bits.Rm == 4
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.ModRM.Bits.Mod != 3)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /* No scaled index SIB (index=4), except for ESP. */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pState->Cpu.SIB.Bits.Index == 4
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.SIB.Bits.Base != 4)
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* EBP + displacement */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pState->Cpu.ModRM.Bits.Mod != 0
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.SIB.Bits.Base == 5
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.SIB.Bits.Scale == 0)
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pState->Cpu.pCurInstr->opcode == OP_SHL
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.ModRM.Bits.Reg == 6)
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /*
8599686860198730ae53d5895386d1b57dbc060evboxsync * Check for multiple prefixes of the same kind.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fSegmentPrefix = false;
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fLockPrefix = false;
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fAddressSize = false;
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fOperandSize = false;
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fRepPrefix = false;
8599686860198730ae53d5895386d1b57dbc060evboxsync bool fRex = false;
8599686860198730ae53d5895386d1b57dbc060evboxsync for (uint8_t const *pu8 = pState->pbInstr;; pu8++)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync bool *pf;
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (*pu8)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0xf0:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = &fLockPrefix;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0xf2:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0xf3:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = &fRepPrefix;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x2e:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x3e:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x26:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x36:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x64:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x65:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = &fSegmentPrefix;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x66:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = &fOperandSize;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x67:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = &fAddressSize;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
8599686860198730ae53d5895386d1b57dbc060evboxsync case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = pState->Cpu.mode == CPUMODE_64BIT ? &fRex : NULL;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync pf = NULL;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync if (!pf)
8599686860198730ae53d5895386d1b57dbc060evboxsync break; /* done */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (*pf)
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync *pf = true;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* segment overrides are fun */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fSegmentPrefix)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /* no efficient address which it may apply to. */
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert((pState->Cpu.prefix & PREFIX_SEG) || pState->Cpu.mode == CPUMODE_64BIT);
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( !(pState->Cpu.param1.flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync && !(pState->Cpu.param2.flags & USE_EFFICIENT_ADDRESS)
8599686860198730ae53d5895386d1b57dbc060evboxsync && !(pState->Cpu.param3.flags & USE_EFFICIENT_ADDRESS))
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* fixed register + addr override doesn't go down all that well. */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (fAddressSize)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync Assert(pState->Cpu.prefix & PREFIX_ADDRSIZE);
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pState->Cpu.pCurInstr->param3 == OP_PARM_NONE
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param2 == OP_PARM_NONE
8599686860198730ae53d5895386d1b57dbc060evboxsync && ( pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END))
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* check for the version of xyz reg,reg instruction that the assembler doesn't use.
8599686860198730ae53d5895386d1b57dbc060evboxsync expected: 1aee sbb ch, dh ; SBB r8, r/m8
8599686860198730ae53d5895386d1b57dbc060evboxsync yasm: 18F5 sbb ch, dh ; SBB r/m8, r8 */
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pState->Cpu.ModRM.Bits.Mod == 3 /* reg,reg */)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pState->Cpu.pCurInstr->opcode)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_ADC:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_ADD:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_AND:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_OR:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SUB:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SBB:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_XOR:
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gb /* r8 */
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */)
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( pState->Cpu.pCurInstr->param1 == OP_PARM_Gv /* rX */
8599686860198730ae53d5895386d1b57dbc060evboxsync && pState->Cpu.pCurInstr->param2 == OP_PARM_Ev /* rX/memX */))
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* ff /0, fe /0, ff /1, fe /0 */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_DEC:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_INC:
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* check for REX.X = 1 without SIB. */
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual
8599686860198730ae53d5895386d1b57dbc060evboxsync says (intel doesn't appear to care). */
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pState->Cpu.pCurInstr->opcode)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETO:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNO:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETC:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNC:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETE:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNE:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETBE:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNBE:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETS:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNS:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETP:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNP:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETL:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNL:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETLE:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_SETNLE:
8599686860198730ae53d5895386d1b57dbc060evboxsync AssertMsg(pState->Cpu.opcode >= 0x90 && pState->Cpu.opcode <= 0x9f, ("%#x\n", pState->Cpu.opcode));
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pState->Cpu.ModRM.Bits.Reg != 2)
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/**
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Masm style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pState The disassembler state.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic void MyDisasMasmFormatter(PMYDISSTATE pState)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("masm not implemented: %s", pState->szLine);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync/**
8599686860198730ae53d5895386d1b57dbc060evboxsync * This is a temporary workaround for catching a few illegal opcodes
8599686860198730ae53d5895386d1b57dbc060evboxsync * that the disassembler is currently letting thru, just enough to make
8599686860198730ae53d5895386d1b57dbc060evboxsync * the assemblers happy.
8599686860198730ae53d5895386d1b57dbc060evboxsync *
8599686860198730ae53d5895386d1b57dbc060evboxsync * We're too close to a release to dare mess with these things now as
8599686860198730ae53d5895386d1b57dbc060evboxsync * they may consequences for performance and let alone introduce bugs.
8599686860198730ae53d5895386d1b57dbc060evboxsync *
8599686860198730ae53d5895386d1b57dbc060evboxsync * @returns true if it's valid. false if it isn't.
8599686860198730ae53d5895386d1b57dbc060evboxsync *
8599686860198730ae53d5895386d1b57dbc060evboxsync * @param pCpu The disassembler output.
8599686860198730ae53d5895386d1b57dbc060evboxsync */
8599686860198730ae53d5895386d1b57dbc060evboxsyncstatic bool MyDisasIsValidInstruction(DISCPUSTATE const *pCpu)
8599686860198730ae53d5895386d1b57dbc060evboxsync{
8599686860198730ae53d5895386d1b57dbc060evboxsync switch (pCpu->pCurInstr->opcode)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /* These doesn't take memory operands. */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_MOV_CR:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_MOV_DR:
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_MOV_TR:
8599686860198730ae53d5895386d1b57dbc060evboxsync if (pCpu->ModRM.Bits.Mod != 3)
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* The 0x8f /0 variant of this instruction doesn't get its /r value verified. */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_POP:
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( pCpu->opcode == 0x8f
8599686860198730ae53d5895386d1b57dbc060evboxsync && pCpu->ModRM.Bits.Reg != 0)
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync /* The 0xc6 /0 and 0xc7 /0 variants of this instruction don't get their /r values verified. */
8599686860198730ae53d5895386d1b57dbc060evboxsync case OP_MOV:
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( ( pCpu->opcode == 0xc6
8599686860198730ae53d5895386d1b57dbc060evboxsync || pCpu->opcode == 0xc7)
8599686860198730ae53d5895386d1b57dbc060evboxsync && pCpu->ModRM.Bits.Reg != 0)
8599686860198730ae53d5895386d1b57dbc060evboxsync return false;
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync default:
8599686860198730ae53d5895386d1b57dbc060evboxsync break;
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
8599686860198730ae53d5895386d1b57dbc060evboxsync return true;
8599686860198730ae53d5895386d1b57dbc060evboxsync}
8599686860198730ae53d5895386d1b57dbc060evboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/**
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Callback for reading bytes.
8599686860198730ae53d5895386d1b57dbc060evboxsync *
8599686860198730ae53d5895386d1b57dbc060evboxsync * @todo This should check that the disassembler doesn't do unnecessary reads,
8599686860198730ae53d5895386d1b57dbc060evboxsync * however the current doesn't do this and is just complicated...
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic DECLCALLBACK(int) MyDisasInstrRead(RTUINTPTR uSrcAddr, uint8_t *pbDst, uint32_t cbRead, void *pvDisCpu)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync PMYDISSTATE pState = (PMYDISSTATE)pvDisCpu;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (RT_LIKELY( pState->uNextAddr == uSrcAddr
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync && pState->cbLeft >= cbRead))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Straight forward reading.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (cbRead == 1)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft--;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *pbDst = *pState->pbNext++;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr++;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync memcpy(pbDst, pState->pbNext, cbRead);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->pbNext += cbRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft -= cbRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr += cbRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Jumping up the stream.
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync * This occures when the byte sequence is added to the output string.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint64_t offReq64 = uSrcAddr - pState->uAddress;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (offReq64 < 32)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint32_t offReq = offReq64;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uintptr_t off = pState->pbNext - pState->pbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (off + pState->cbLeft <= offReq)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->pbNext += pState->cbLeft;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr += pState->cbLeft;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft = 0;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync memset(pbDst, 0xcc, cbRead);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->rc = VERR_EOF;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return VERR_EOF;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* reset the stream. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft += off;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->pbNext = pState->pbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr = pState->uAddress;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* skip ahead. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft -= offReq;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->pbNext += offReq;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr += offReq;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* do the reading. */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (pState->cbLeft >= cbRead)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync memcpy(pbDst, pState->pbNext, cbRead);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft -= cbRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->pbNext += cbRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr += cbRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (pState->cbLeft > 0)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync memcpy(pbDst, pState->pbNext, pState->cbLeft);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pbDst += pState->cbLeft;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync cbRead -= pState->cbLeft;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->pbNext += pState->cbLeft;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->uNextAddr += pState->cbLeft;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->cbLeft = 0;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync memset(pbDst, 0xcc, cbRead);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->rc = VERR_EOF;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return VERR_EOF;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTStrmPrintf(g_pStdErr, "Reading before current instruction!\n");
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync memset(pbDst, 0x90, cbRead);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pState->rc = VERR_INTERNAL_ERROR;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return VERR_INTERNAL_ERROR;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return VINF_SUCCESS;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/**
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Disassembles a block of memory.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @returns VBox status code.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param argv0 Program name (for errors and warnings).
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param enmCpuMode The cpu mode to disassemble in.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param uAddress The address we're starting to disassemble at.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param pbFile Where to start disassemble.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param cbFile How much to disassemble.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param enmStyle The assembly output style.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param fListing Whether to print in a listing like mode.
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync * @param enmUndefOp How to deal with undefined opcodes.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic int MyDisasmBlock(const char *argv0, DISCPUMODE enmCpuMode, uint64_t uAddress, uint8_t *pbFile, size_t cbFile,
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync ASMSTYLE enmStyle, bool fListing, UNDEFOPHANDLING enmUndefOp)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Initialize the CPU context.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync MYDISSTATE State;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.Cpu.mode = enmCpuMode;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.Cpu.pfnReadBytes = MyDisasInstrRead;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.uAddress = uAddress;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.pbInstr = pbFile;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.cbInstr = 0;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync State.enmUndefOp = enmUndefOp;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.rc = VINF_SUCCESS;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.cbLeft = cbFile;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.pbNext = pbFile;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.uNextAddr = uAddress;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync void (*pfnFormatter)(PMYDISSTATE pState);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync switch (enmStyle)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case kAsmStyle_Default:
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pfnFormatter = MyDisasDefaultFormatter;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case kAsmStyle_yasm:
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTPrintf(" BITS %d\n", enmCpuMode == CPUMODE_16BIT ? 16 : enmCpuMode == CPUMODE_32BIT ? 32 : 64);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pfnFormatter = MyDisasYasmFormatter;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case kAsmStyle_masm:
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync pfnFormatter = MyDisasMasmFormatter;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync default:
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync AssertFailedReturn(VERR_INTERNAL_ERROR);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * The loop.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int rcRet = VINF_SUCCESS;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync while (State.cbLeft > 0)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Disassemble it.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.cbInstr = 0;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.cbLeft += State.pbNext - State.pbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.uNextAddr = State.uAddress;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.pbNext = State.pbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int rc = DISInstr(&State.Cpu, State.uAddress, 0, &State.cbInstr, State.szLine);
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( RT_SUCCESS(rc)
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( ( rc == VERR_DIS_INVALID_OPCODE
8599686860198730ae53d5895386d1b57dbc060evboxsync || rc == VERR_DIS_GEN_FAILURE)
8599686860198730ae53d5895386d1b57dbc060evboxsync && State.enmUndefOp == kUndefOp_DefineByte))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync State.fUndefOp = rc == VERR_DIS_INVALID_OPCODE
8599686860198730ae53d5895386d1b57dbc060evboxsync || rc == VERR_DIS_GEN_FAILURE
8599686860198730ae53d5895386d1b57dbc060evboxsync || State.Cpu.pCurInstr->opcode == OP_INVALID
8599686860198730ae53d5895386d1b57dbc060evboxsync || State.Cpu.pCurInstr->opcode == OP_ILLUD2
8599686860198730ae53d5895386d1b57dbc060evboxsync || ( State.enmUndefOp == kUndefOp_DefineByte
8599686860198730ae53d5895386d1b57dbc060evboxsync && !MyDisasIsValidInstruction(&State.Cpu));
8599686860198730ae53d5895386d1b57dbc060evboxsync if (State.fUndefOp && State.enmUndefOp == kUndefOp_DefineByte)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(" db");
8599686860198730ae53d5895386d1b57dbc060evboxsync if (!State.cbInstr)
8599686860198730ae53d5895386d1b57dbc060evboxsync State.cbInstr = 1;
8599686860198730ae53d5895386d1b57dbc060evboxsync for (unsigned off = 0; off < State.cbInstr; off++)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync uint8_t b;
8599686860198730ae53d5895386d1b57dbc060evboxsync State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu);
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(off ? ", %03xh" : " %03xh", b);
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(" ; %s\n", State.szLine);
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync else if (!State.fUndefOp && State.enmUndefOp == kUndefOp_All)
d4162288035439690deb3175bc2ca74a015e325bvboxsync {
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTPrintf("%s: error at %#RX64: unexpected valid instruction (op=%d)\n", argv0, State.uAddress, State.Cpu.pCurInstr->opcode);
d4162288035439690deb3175bc2ca74a015e325bvboxsync pfnFormatter(&State);
d4162288035439690deb3175bc2ca74a015e325bvboxsync rcRet = VERR_GENERAL_FAILURE;
d4162288035439690deb3175bc2ca74a015e325bvboxsync }
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync else if (State.fUndefOp && State.enmUndefOp == kUndefOp_Fail)
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync {
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync RTPrintf("%s: error at %#RX64: undefined opcode (op=%d)\n", argv0, State.uAddress, State.Cpu.pCurInstr->opcode);
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync pfnFormatter(&State);
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync rcRet = VERR_GENERAL_FAILURE;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync }
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync else
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync /* Use db for odd encodings that we can't make the assembler use. */
8599686860198730ae53d5895386d1b57dbc060evboxsync if ( State.enmUndefOp == kUndefOp_DefineByte
8599686860198730ae53d5895386d1b57dbc060evboxsync && MyDisasYasmFormatterIsOddEncoding(&State))
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(" db");
8599686860198730ae53d5895386d1b57dbc060evboxsync for (unsigned off = 0; off < State.cbInstr; off++)
8599686860198730ae53d5895386d1b57dbc060evboxsync {
8599686860198730ae53d5895386d1b57dbc060evboxsync uint8_t b;
8599686860198730ae53d5895386d1b57dbc060evboxsync State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu);
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(off ? ", %03xh" : " %03xh", b);
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync RTPrintf(" ; ");
8599686860198730ae53d5895386d1b57dbc060evboxsync }
8599686860198730ae53d5895386d1b57dbc060evboxsync
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync pfnFormatter(&State);
8599686860198730ae53d5895386d1b57dbc060evboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.cbInstr = State.pbNext - State.pbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (!State.cbLeft)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s: error at %#RX64: read beyond the end (%Rrc)\n", argv0, State.uAddress, rc);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else if (State.cbInstr)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d\n", argv0, State.uAddress, rc, State.cbInstr);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTPrintf("%s: error at %#RX64: %Rrc cbInstr=%d!\n", argv0, State.uAddress, rc, State.cbInstr);
d4162288035439690deb3175bc2ca74a015e325bvboxsync if (rcRet == VINF_SUCCESS)
d4162288035439690deb3175bc2ca74a015e325bvboxsync rcRet = rc;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* next */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.uAddress += State.cbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync State.pbInstr += State.cbInstr;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return rcRet;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync/**
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Prints usage info.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync *
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @returns 1.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * @param argv0 The program name.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncstatic int Usage(const char *argv0)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTStrmPrintf(g_pStdErr,
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync"usage: %s [options] <file1> [file2..fileN]\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" or: %s <--help|-h>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync"\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync"Options:\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --address|-a <address>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The base address. Default: 0\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --max-bytes|-b <bytes>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The maximum number of bytes to disassemble. Default: 1GB\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --cpumode|-c <16|32|64>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The cpu mode. Default: 32\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --listing|-l, --no-listing|-L\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" Enables or disables listing mode. Default: --no-listing\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --offset|-o <offset>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The file offset at which to start disassembling. Default: 0\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" --style|-s <default|yasm|masm>\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync" The assembly output style. Default: default\n"
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync" --undef-op|-u <fail|all|db>\n"
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync" How to treat undefined opcodes. Default: fail\n"
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync , argv0, argv0);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsyncint main(int argc, char **argv)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync{
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTR3Init();
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync const char * const argv0 = RTPathFilename(argv[0]);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /* options */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uint64_t uAddress = 0;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync ASMSTYLE enmStyle = kAsmStyle_Default;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync UNDEFOPHANDLING enmUndefOp = kUndefOp_Fail;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync bool fListing = true;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync DISCPUMODE enmCpuMode = CPUMODE_32BIT;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTFOFF off = 0;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTFOFF cbMax = _1G;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Parse arguments.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync static const RTOPTIONDEF g_aOptions[] =
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--address", 'a', RTGETOPT_REQ_UINT64 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--cpumode", 'c', RTGETOPT_REQ_UINT32 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--help", 'h', 0 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--bytes", 'b', RTGETOPT_REQ_INT64 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--listing", 'l', 0 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--no-listing", 'L', 0 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--offset", 'o', RTGETOPT_REQ_INT64 },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync { "--style", 's', RTGETOPT_REQ_STRING },
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync { "--undef-op", 'u', RTGETOPT_REQ_STRING },
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync };
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int ch;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int iArg = 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync RTOPTIONUNION ValueUnion;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync while ((ch = RTGetOpt(argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), &iArg, &ValueUnion)))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync switch (ch)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'a':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync uAddress = ValueUnion.u64;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'b':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync cbMax = ValueUnion.i;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'c':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (ValueUnion.u32 == 16)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync enmCpuMode = CPUMODE_16BIT;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else if (ValueUnion.u32 == 32)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync enmCpuMode = CPUMODE_32BIT;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else if (ValueUnion.u32 == 64)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync enmCpuMode = CPUMODE_64BIT;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: Invalid CPU mode value %RU32\n", argv0, ValueUnion.u32);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'h':
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync return Usage(argv0);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'l':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync fListing = true;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'L':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync fListing = false;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 'o':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync off = ValueUnion.i;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync case 's':
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (!strcmp(ValueUnion.psz, "default"))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync enmStyle = kAsmStyle_Default;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else if (!strcmp(ValueUnion.psz, "yasm"))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync enmStyle = kAsmStyle_yasm;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else if (!strcmp(ValueUnion.psz, "masm"))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync enmStyle = kAsmStyle_masm;
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: masm style isn't implemented yet\n", argv0);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync else
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: unknown assembly style: %s\n", argv0, ValueUnion.psz);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync case 'u':
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync if (!strcmp(ValueUnion.psz, "fail"))
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync enmUndefOp = kUndefOp_Fail;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync else if (!strcmp(ValueUnion.psz, "all"))
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync enmUndefOp = kUndefOp_All;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync else if (!strcmp(ValueUnion.psz, "db"))
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync enmUndefOp = kUndefOp_DefineByte;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync else
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync {
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync RTStrmPrintf(g_pStdErr, "%s: unknown undefined opcode handling method: %s\n", argv0, ValueUnion.psz);
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync return 1;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync }
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync break;
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync default:
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: syntax error: %Rrc\n", argv0, ch);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (iArg >= argc)
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync return Usage(argv0);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Process the files.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync int rc = VINF_SUCCESS;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync for ( ; iArg < argc; iArg++)
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Read the file into memory.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync void *pvFile;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync size_t cbFile;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync rc = RTFileReadAllEx(argv[iArg], off, cbMax, 0, &pvFile, &cbFile);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (RT_FAILURE(rc))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync {
8fa1e8a8a8702ee38195fbe7ad5959bf971eb93bvboxsync RTStrmPrintf(g_pStdErr, "%s: %s: %Rrc\n", argv0, argv[iArg], rc);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync /*
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync * Disassemble it.
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync */
7748b9362d6a39df9045d5d05ccb57871145a649vboxsync rc = MyDisasmBlock(argv0, enmCpuMode, uAddress, (uint8_t *)pvFile, cbFile, enmStyle, fListing, enmUndefOp);
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync if (RT_FAILURE(rc))
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync break;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync }
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync return RT_SUCCESS(rc) ? 0 : 1;
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync}
7bf0220c3332700233120b513c9b4ba20a0caa9bvboxsync