DisasmFormatYasm.cpp revision 1293aa7d1fe6b44033bd94a1ffb4da5b7ba3be52
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VBox Disassembler - Yasm(/Nasm) Style Formatter.
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * available from http://www.virtualbox.org. This file is free software;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * General Public License (GPL) as published by the Free Software
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * additional information or have any questions.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/*******************************************************************************
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync* Header Files *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync*******************************************************************************/
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync/*******************************************************************************
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync* Global Variables *
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync*******************************************************************************/
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsyncstatic const char g_szSpaces[] =
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync "al\0\0", "cl\0\0", "dl\0\0", "bl\0\0", "ah\0\0", "ch\0\0", "dh\0\0", "bh\0\0", "r8b\0", "r9b\0", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "spl\0", "bpl\0", "sil\0", "dil\0"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "bx+si", "bx+di", "bp+si", "bp+di", "si\0\0\0", "di\0\0\0", "bp\0\0\0", "bx\0\0\0"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8\0", "r9\0", "r10", "r11", "r12", "r13", "r14", "r15"
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync "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"
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync "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"
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync "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"
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync "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"
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync * Gets the base register name for the given parameter.
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync * @returns Pointer to the register name.
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync * @param pCpu The disassembler cpu state.
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync * @param pParam The parameter.
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync * @param pcchReg Where to store the length of the name.
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsyncstatic const char *disasmFormatYasmBaseReg(PCDISCPUSTATE pCpu, PCOP_PARAMETER pParam, size_t *pcchReg)
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync switch (pParam->flags & ( USE_REG_GEN8 | USE_REG_GEN16 | USE_REG_GEN32 | USE_REG_GEN64
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync | USE_REG_FP | USE_REG_MMX | USE_REG_XMM | USE_REG_CR
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen8));
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync const char *psz = g_aszYasmRegGen8[pParam->base.reg_gen];
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
4a9af9a8062589b741444d717d2dd1ed22b0f583vboxsync const char *psz = g_aszYasmRegGen16[pParam->base.reg_gen];
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync const char *psz = g_aszYasmRegGen32[pParam->base.reg_gen];
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync const char *psz = g_aszYasmRegGen64[pParam->base.reg_gen];
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync Assert(pParam->base.reg_fp < RT_ELEMENTS(g_aszYasmRegFP));
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync const char *psz = g_aszYasmRegFP[pParam->base.reg_fp];
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync Assert(pParam->base.reg_mmx < RT_ELEMENTS(g_aszYasmRegMMX));
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync const char *psz = g_aszYasmRegMMX[pParam->base.reg_mmx];
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync Assert(pParam->base.reg_xmm < RT_ELEMENTS(g_aszYasmRegXMM));
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync const char *psz = g_aszYasmRegXMM[pParam->base.reg_mmx];
1c0d3d017f9a45748b4839bf6622b53e83a4f1f8vboxsync Assert(pParam->base.reg_ctrl < RT_ELEMENTS(g_aszYasmRegCRx));
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync const char *psz = g_aszYasmRegCRx[pParam->base.reg_ctrl];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_dbg < RT_ELEMENTS(g_aszYasmRegDRx));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegDRx[pParam->base.reg_dbg];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_seg < (DIS_SELREG)RT_ELEMENTS(g_aszYasmRegCRx));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegSeg[pParam->base.reg_seg];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_test < RT_ELEMENTS(g_aszYasmRegTRx));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegTRx[pParam->base.reg_test];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return "r??";
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync * Gets the index register name for the given parameter.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns The index register name.
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync * @param pCpu The disassembler cpu state.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pParam The parameter.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pcchReg Where to store the length of the name.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic const char *disasmFormatYasmIndexReg(PCDISCPUSTATE pCpu, PCOP_PARAMETER pParam, size_t *pcchReg)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen16[pParam->index.reg_gen];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen32[pParam->index.reg_gen];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->index.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen64[pParam->index.reg_gen];
7b4ea63789001468ec3662bdfcd6432bf89095dfvboxsync AssertMsgFailed(("%#x %#x\n", pParam->flags, pCpu->addrmode));
7b4ea63789001468ec3662bdfcd6432bf89095dfvboxsync return "r??";
46737b2c6b2da473108a7670c3682d88474bd8b9vboxsync * Formats the current instruction in Yasm (/ Nasm) style.
7b4ea63789001468ec3662bdfcd6432bf89095dfvboxsync * @returns The number of output characters. If this is >= cchBuf, then the content
46737b2c6b2da473108a7670c3682d88474bd8b9vboxsync * of pszBuf will be truncated.
46737b2c6b2da473108a7670c3682d88474bd8b9vboxsync * @param pCpu Pointer to the disassembler CPU state.
7b4ea63789001468ec3662bdfcd6432bf89095dfvboxsync * @param pszBuf The output buffer.
7b4ea63789001468ec3662bdfcd6432bf89095dfvboxsync * @param cchBuf The size of the output buffer.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param fFlags Format flags, see DIS_FORMAT_FLAGS_*.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pfnGetSymbol Get symbol name for a jmp or call target address. Optional.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pvUser User argument for pfnGetSymbol.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsyncDISDECL(size_t) DISFormatYasmEx(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, uint32_t fFlags,
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * Input validation and massaging.
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync AssertMsg(DIS_FMT_FLAGS_IS_VALID(fFlags), ("%#x\n", fFlags));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync fFlags = (fFlags & ~DIS_FMT_FLAGS_ADDR_LEFT) | DIS_FMT_FLAGS_ADDR_RIGHT;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync fFlags = (fFlags & ~DIS_FMT_FLAGS_BYTES_LEFT) | DIS_FMT_FLAGS_BYTES_RIGHT;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Output macros
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } while (0)
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync } while (0)
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync do { if (fFlags & DIS_FMT_FLAGS_STRICT) PUT_SZ(szStrict); else PUT_SZ(szRelaxed); } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync do { const size_t cchTmp = strlen(psz); PUT_STR((psz), cchTmp); } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const size_t cchTmp = RTStrPrintf(pszDst, cchDst, fmt, (num)); \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/** @todo add two flags for choosing between %X / %x and h / 0x. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_8(num) PUT_NUM(4, "0%02xh", (uint8_t)(num))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_16(num) PUT_NUM(6, "0%04xh", (uint16_t)(num))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_32(num) PUT_NUM(10, "0%08xh", (uint32_t)(num))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_64(num) PUT_NUM(18, "0%016RX64h", (uint64_t)(num))
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_S8(num) PUT_NUM_SIGN(4, "0%02xh", num, int8_t, uint8_t)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_S16(num) PUT_NUM_SIGN(6, "0%04xh", num, int16_t, uint16_t)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_S32(num) PUT_NUM_SIGN(10, "0%08xh", num, int32_t, uint32_t)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#define PUT_NUM_S64(num) PUT_NUM_SIGN(18, "0%016RX64h", num, int64_t, uint64_t)
46737b2c6b2da473108a7670c3682d88474bd8b9vboxsync * The address?
46737b2c6b2da473108a7670c3682d88474bd8b9vboxsync PUT_NUM(9, "%08x`", (uint32_t)(pCpu->opaddr >> 32));
329df9696e709dc71611f504a4774f323545be0avboxsync * The opcode bytes?
41fcf8465b641c7083d3b440451f17c1210fce33vboxsync size_t cchTmp = disFormatBytes(pCpu, pszDst, cchDst, fFlags);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Some padding to align the instruction. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync size_t cchPadding = (7 * (2 + !!(fFlags & DIS_FMT_FLAGS_BYTES_SPACED)))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cchPadding = cchTmp + 1 >= cchPadding ? 1 : cchPadding - cchTmp;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * Filter out invalid opcodes first as they need special
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * treatment. UD2 is an exception and should be handled normally.
4ecd4ad59281328476ad14f2baa51716b6f5f804vboxsync * Adjust the format string to the correct mnemonic
4ecd4ad59281328476ad14f2baa51716b6f5f804vboxsync * or to avoid things the assembler cannot handle correctly.
329df9696e709dc71611f504a4774f323545be0avboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "jcxz %Jb" : pCpu->opmode == CPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
329df9696e709dc71611f504a4774f323545be0avboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "pushfw" : pCpu->opmode == CPUMODE_32BIT ? "pushfd" : "pushfq";
329df9696e709dc71611f504a4774f323545be0avboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "popfw" : pCpu->opmode == CPUMODE_32BIT ? "popfd" : "popfq";
329df9696e709dc71611f504a4774f323545be0avboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "pushaw" : "pushad";
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "popaw" : "popad";
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "insw" : pCpu->opmode == CPUMODE_32BIT ? "insd" : "insq";
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "outsw" : pCpu->opmode == CPUMODE_32BIT ? "outsd" : "outsq";
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "movsw" : pCpu->opmode == CPUMODE_32BIT ? "movsd" : "movsq";
09f4b412099acda62997fd82c8608075c453b3ebvboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cmpsw" : pCpu->opmode == CPUMODE_32BIT ? "cmpsd" : "cmpsq";
09f4b412099acda62997fd82c8608075c453b3ebvboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "scasw" : pCpu->opmode == CPUMODE_32BIT ? "scasd" : "scasq";
09f4b412099acda62997fd82c8608075c453b3ebvboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "lodsw" : pCpu->opmode == CPUMODE_32BIT ? "lodsd" : "lodsq";
09f4b412099acda62997fd82c8608075c453b3ebvboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "stosw" : pCpu->opmode == CPUMODE_32BIT ? "stosd" : "stosq";
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cbw" : pCpu->opmode == CPUMODE_32BIT ? "cwde" : "cdqe";
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync pszFmt = pCpu->opmode == CPUMODE_16BIT ? "cwd" : pCpu->opmode == CPUMODE_32BIT ? "cdq" : "cqo";
09f4b412099acda62997fd82c8608075c453b3ebvboxsync * Don't know how to tell yasm to generate complicated nop stuff, so 'db' it.
09f4b412099acda62997fd82c8608075c453b3ebvboxsync /* fine, fine */;
09f4b412099acda62997fd82c8608075c453b3ebvboxsync else if (pszFmt[sizeof("nop %Ev") - 1] == '/' && pszFmt[sizeof("nop %Ev")] == 'p')
09f4b412099acda62997fd82c8608075c453b3ebvboxsync /* ST(X) -> stX (floating point) */
09f4b412099acda62997fd82c8608075c453b3ebvboxsync if (ch == 'S' && pszFmt[0] == 'T' && pszFmt[1] == '(')
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Horrible hacks.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *(int *)&pCpu->param1.param &= ~0x1f; /* make it pure OP_PARM_M */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case OP_LAR: /* hack w -> v, probably not correct. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Formatting context and associated macros.
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync if ( OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p \
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync } while (0)
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync /** @todo mov ah,ch ends up with a byte 'override'... - check if this wasn't fixed. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo drop the work/dword/qword override when the src/dst is a register (except for movsx/movzx). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync default: break; \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (OP_PARM_VTYPE(pParam->param) != OP_PARM_W) /* these are 128 bit, pray they are all unambiguous.. */ \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case OP_PARM_s: if (pParam->flags & USE_REG_FP) PUT_SZ("tword "); break; /* ?? */ \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case OP_PARM_z: break; \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ((pParam->flags & USE_REG_FP) || pOp->opcode == OP_FLD)) \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync default: break; /*no pointer type specified/necessary*/ \
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync static const char s_szSegPrefix[6][4] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Segment prefixing for instructions that doesn't do memory access.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The formatting loop.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * ModRM - Register only.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'C': /* Control register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'D': /* Debug register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'G': /* ModRM selects general register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'S': /* ModRM byte selects a segment register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'T': /* ModRM byte selects a test register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'V': /* ModRM byte selects an XMM/SSE register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'P': /* ModRM byte selects MMX register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync Assert(!(pParam->flags & (USE_INDEX | USE_SCALE) /* No SIB here... */));
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync Assert(!(pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32)));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * ModRM - Register or memory.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'E': /* ModRM specifies parameter (ParseModRM / UseModRM / UseSIB). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'Q': /* ModRM byte selects MMX register or memory address (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'R': /* ModRM byte may only refer to a general register (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'W': /* ModRM byte selects an XMM/SSE register or a memory address (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'M': /* ModRM may only refer to memory (ParseModRM / UseModRM). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Work around mov seg,[mem16] and mov [mem16],seg as these always make a 16-bit mem
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync while the register variants deals with 16, 32 & 64 in the normal fashion. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32)))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (int8_t)pParam->disp16 == (int16_t)pParam->disp16)
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync && (int8_t)pParam->disp32 == (int32_t)pParam->disp32)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (int8_t)pParam->disp64 == (int64_t)pParam->disp32)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync bool fBase = (pParam->flags & USE_BASE) /* When exactly is USE_BASE supposed to be set? disasmModRMReg doesn't set it. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || ( (pParam->flags & (USE_REG_GEN8 | USE_REG_GEN16 | USE_REG_GEN32 | USE_REG_GEN64))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmIndexReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pParam->flags & (USE_DISPLACEMENT8 | USE_DISPLACEMENT16 | USE_DISPLACEMENT32 | USE_DISPLACEMENT64 | USE_RIPDISPLACEMENT32))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else if (pParam->flags & (USE_DISPLACEMENT32 | USE_RIPDISPLACEMENT32))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync case 'F': /* Eflags register (0 - popf/pushf only, avoided in adjustments above). */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v' || *pszFmt == 'w' || *pszFmt == 'z'); pszFmt++;
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync switch (pParam->flags & ( USE_IMMEDIATE8 | USE_IMMEDIATE16 | USE_IMMEDIATE32 | USE_IMMEDIATE64
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync | USE_IMMEDIATE16_SX8 | USE_IMMEDIATE32_SX8 | USE_IMMEDIATE64_SX8))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync && ( (pOp->param1 >= OP_PARM_REG_GEN8_START && pOp->param1 <= OP_PARM_REG_GEN8_END)
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync || (pOp->param2 >= OP_PARM_REG_GEN8_START && pOp->param2 <= OP_PARM_REG_GEN8_END))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync && ( (int8_t)pParam->parval == (int16_t)pParam->parval
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync || (pOp->param1 >= OP_PARM_REG_GEN16_START && pOp->param1 <= OP_PARM_REG_GEN16_END)
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync || (pOp->param2 >= OP_PARM_REG_GEN16_START && pOp->param2 <= OP_PARM_REG_GEN16_END))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync else if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v)
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync if ( pCpu->opmode != (pCpu->mode == CPUMODE_16BIT ? CPUMODE_16BIT : CPUMODE_32BIT) /* not perfect */
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync && ( (int8_t)pParam->parval == (int32_t)pParam->parval
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync || (pOp->param1 >= OP_PARM_REG_GEN32_START && pOp->param1 <= OP_PARM_REG_GEN32_END)
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync || (pOp->param2 >= OP_PARM_REG_GEN32_START && pOp->param2 <= OP_PARM_REG_GEN32_END))
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync else if (OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'J': /* Relative jump offset (ParseImmBRel + ParseImmVRel). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->flags & (USE_IMMEDIATE32_REL|USE_IMMEDIATE64_REL));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync RTUINTPTR uTrgAddr = pCpu->opaddr + pCpu->opsize + offDisplacement;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync int rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), uTrgAddr, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'A': /* Direct (jump/call) address (ParseImmAddr). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
cb0578a5309e1fc264e5a4acc30543bea075be43vboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint64_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
09f4b412099acda62997fd82c8608075c453b3ebvboxsync switch (pParam->flags & (USE_IMMEDIATE_ADDR_16_16 | USE_IMMEDIATE_ADDR_16_32 | USE_DISPLACEMENT64 | USE_DISPLACEMENT32 | USE_DISPLACEMENT16))
c7d2f5508ab9703a7a6c5cce5c9d4bf335af660avboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
4c98b8b05f3783351cf256cc90cd4478fb28b62bvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
a7ba3d5f31ca70d04a3933e570374e5ec5eff84avboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint16_t)pParam->disp16, szSymbol, sizeof(szSymbol), &off, pvUser);
105b1a31b6037dbe14acb8d09e60da540885202bvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint32_t)pParam->disp32, szSymbol, sizeof(szSymbol), &off, pvUser);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DIS_SELREG_CS), (uint64_t)pParam->disp64, szSymbol, sizeof(szSymbol), &off, pvUser);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync case 'e': /* Register based on operand size (e.g. %eAX) (ParseFixedReg). */
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2])); pszFmt += 2;
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
73ba84f95f918cc170be38908ad240fbb2f8f354vboxsync AssertMsg(*pszFmt == ',' || *pszFmt == '\0', ("%c%s\n", ch, pszFmt));
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync } /* while more to format */
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync * Any additional output to the right of the instruction?
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync /* some up front padding. */
5159c4c6485473c77871b515c15b59c3caa60b46vboxsync cchPadding = cchPadding + 1 >= 42 ? 1 : 42 - cchPadding;
6b2a50fc09aa4f7ce2082284f082d97a2c738321vboxsync /* comment? */
6b2a50fc09aa4f7ce2082284f082d97a2c738321vboxsync if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * The address?
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PUT_NUM(9, "%08x`", (uint32_t)(pCpu->opaddr >> 32));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Opcode bytes?
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync size_t cchTmp = disFormatBytes(pCpu, pszDst, cchDst, fFlags);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Terminate it - on overflow we'll have reserved one byte for this.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* clean up macros */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Formats the current instruction in Yasm (/ Nasm) style.
67b8a5a52c43a79ea7e159dbbeec99687fb9cd3bvboxsync * This is a simplified version of DISFormatYasmEx() provided for your convenience.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns The number of output characters. If this is >= cchBuf, then the content
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * of pszBuf will be truncated.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * @param pCpu Pointer to the disassembler CPU state.
3fa7a7e633f46a212052b510cdb8cee41f279a67vboxsync * @param pszBuf The output buffer.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param cchBuf The size of the output buffer.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDISDECL(size_t) DISFormatYasm(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf)
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync return DISFormatYasmEx(pCpu, pszBuf, cchBuf, 0 /* fFlags */, NULL /* pfnGetSymbol */, NULL /* pvUser */);