de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * VBox Disassembler - Yasm(/Nasm) Style Formatter.
701efa93fe91e164d983fdc7b780b9f203381d0bvboxsync * Copyright (C) 2008-2012 Oracle Corporation
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * available from http://www.virtualbox.org. This file is free software;
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * you can redistribute it and/or modify it under the terms of the GNU
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * General Public License (GPL) as published by the Free Software
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync/*******************************************************************************
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync* Header Files *
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync*******************************************************************************/
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync/*******************************************************************************
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync* Global Variables *
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync*******************************************************************************/
d3cb168f4c128e4477c3f791d983f84075fb2835vboxsync "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"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "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"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "bx+si", "bx+di", "bp+si", "bp+di", "si\0\0\0", "di\0\0\0", "bp\0\0\0", "bx\0\0\0"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "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"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8\0", "r9\0", "r10", "r11", "r12", "r13", "r14", "r15"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "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"
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync "ymm0\0", "ymm1\0", "ymm2\0", "ymm3\0", "ymm4\0", "ymm5\0", "ymm6\0", "ymm7\0", "ymm8\0", "ymm9\0", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "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"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "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"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync "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"
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Gets the base register name for the given parameter.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @returns Pointer to the register name.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync * @param pDis The disassembler state.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pParam The parameter.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pcchReg Where to store the length of the name.
6d51216d13610f142b377a8e15c6c51adb83ba1bvboxsyncstatic const char *disasmFormatYasmBaseReg(PCDISSTATE pDis, PCDISOPPARAM pParam, size_t *pcchReg)
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync switch (pParam->fUse & ( DISUSE_REG_GEN8 | DISUSE_REG_GEN16 | DISUSE_REG_GEN32 | DISUSE_REG_GEN64
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync | DISUSE_REG_FP | DISUSE_REG_MMX | DISUSE_REG_XMM | DISUSE_REG_YMM
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync | DISUSE_REG_CR | DISUSE_REG_DBG | DISUSE_REG_SEG | DISUSE_REG_TEST))
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen8));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegGen8[pParam->Base.idxGenReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen16));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegGen16[pParam->Base.idxGenReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen32));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegGen32[pParam->Base.idxGenReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen64));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegGen64[pParam->Base.idxGenReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxFpuReg < RT_ELEMENTS(g_aszYasmRegFP));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegFP[pParam->Base.idxFpuReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxMmxReg < RT_ELEMENTS(g_aszYasmRegMMX));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegMMX[pParam->Base.idxMmxReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxXmmReg < RT_ELEMENTS(g_aszYasmRegXMM));
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync const char *psz = g_aszYasmRegXMM[pParam->Base.idxXmmReg];
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync Assert(pParam->Base.idxYmmReg < RT_ELEMENTS(g_aszYasmRegYMM));
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync const char *psz = g_aszYasmRegYMM[pParam->Base.idxYmmReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxCtrlReg < RT_ELEMENTS(g_aszYasmRegCRx));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegCRx[pParam->Base.idxCtrlReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxDbgReg < RT_ELEMENTS(g_aszYasmRegDRx));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegDRx[pParam->Base.idxDbgReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxSegReg < RT_ELEMENTS(g_aszYasmRegCRx));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegSeg[pParam->Base.idxSegReg];
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync Assert(pParam->Base.idxTestReg < RT_ELEMENTS(g_aszYasmRegTRx));
1a5d2d9ef8cf8eeec5649664cf88c7fd55c968d2vboxsync const char *psz = g_aszYasmRegTRx[pParam->Base.idxTestReg];
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync return "r??";
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Gets the index register name for the given parameter.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @returns The index register name.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync * @param pDis The disassembler state.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pParam The parameter.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pcchReg Where to store the length of the name.
6d51216d13610f142b377a8e15c6c51adb83ba1bvboxsyncstatic const char *disasmFormatYasmIndexReg(PCDISSTATE pDis, PCDISOPPARAM pParam, size_t *pcchReg)
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync Assert(pParam->Index.idxXmmReg < RT_ELEMENTS(g_aszYasmRegXMM));
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync const char *psz = g_aszYasmRegXMM[pParam->Index.idxXmmReg];
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync Assert(pParam->Index.idxYmmReg < RT_ELEMENTS(g_aszYasmRegYMM));
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync const char *psz = g_aszYasmRegYMM[pParam->Index.idxYmmReg];
a483cdaf39353be16051341f24a8f32baa77c72dvboxsync Assert(pParam->Index.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen16));
a483cdaf39353be16051341f24a8f32baa77c72dvboxsync const char *psz = g_aszYasmRegGen16[pParam->Index.idxGenReg];
a483cdaf39353be16051341f24a8f32baa77c72dvboxsync Assert(pParam->Index.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen32));
a483cdaf39353be16051341f24a8f32baa77c72dvboxsync const char *psz = g_aszYasmRegGen32[pParam->Index.idxGenReg];
a483cdaf39353be16051341f24a8f32baa77c72dvboxsync Assert(pParam->Index.idxGenReg < RT_ELEMENTS(g_aszYasmRegGen64));
a483cdaf39353be16051341f24a8f32baa77c72dvboxsync const char *psz = g_aszYasmRegGen64[pParam->Index.idxGenReg];
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync AssertMsgFailed(("%#x %#x\n", pParam->fUse, pDis->uAddrMode));
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync return "r??";
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Formats the current instruction in Yasm (/ Nasm) style.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @returns The number of output characters. If this is >= cchBuf, then the content
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * of pszBuf will be truncated.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync * @param pDis Pointer to the disassembler state.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pszBuf The output buffer.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param cchBuf The size of the output buffer.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param fFlags Format flags, see DIS_FORMAT_FLAGS_*.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pfnGetSymbol Get symbol name for a jmp or call target address. Optional.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pvUser User argument for pfnGetSymbol.
6d51216d13610f142b377a8e15c6c51adb83ba1bvboxsyncDISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags,
6aaf719e54eb3264fb7330e1a3bb41417dff7ab5vboxsync/** @todo monitor and mwait aren't formatted correctly in 64-bit mode. */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Input validation and massaging.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync AssertMsg(DIS_FMT_FLAGS_IS_VALID(fFlags), ("%#x\n", fFlags));
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync fFlags = (fFlags & ~DIS_FMT_FLAGS_ADDR_LEFT) | DIS_FMT_FLAGS_ADDR_RIGHT;
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync fFlags = (fFlags & ~DIS_FMT_FLAGS_BYTES_LEFT) | DIS_FMT_FLAGS_BYTES_RIGHT;
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Output macros
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } while (0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } while (0)
92473d1de9ab080ff886ad61a4d908f7c3429608vboxsync do { if (fFlags & DIS_FMT_FLAGS_STRICT) PUT_SZ(szStrict); else PUT_SZ(szRelaxed); } while (0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync do { const size_t cchTmp = strlen(psz); PUT_STR((psz), cchTmp); } while (0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync const size_t cchTmp = RTStrPrintf(pszDst, cchDst, fmt, (num)); \
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } while (0)
95ed338027d70aabb68eff2437bf0d08ebbdbea4vboxsync/** @todo add two flags for choosing between %X / %x and h / 0x. */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync#define PUT_NUM_8(num) PUT_NUM(4, "0%02xh", (uint8_t)(num))
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync#define PUT_NUM_16(num) PUT_NUM(6, "0%04xh", (uint16_t)(num))
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync#define PUT_NUM_32(num) PUT_NUM(10, "0%08xh", (uint32_t)(num))
7917e2039cb1b59b67a3a8e26acce7f445860192vboxsync#define PUT_NUM_64(num) PUT_NUM(18, "0%016RX64h", (uint64_t)(num))
92473d1de9ab080ff886ad61a4d908f7c3429608vboxsync } while (0)
92473d1de9ab080ff886ad61a4d908f7c3429608vboxsync#define PUT_NUM_S8(num) PUT_NUM_SIGN(4, "0%02xh", num, int8_t, uint8_t)
92473d1de9ab080ff886ad61a4d908f7c3429608vboxsync#define PUT_NUM_S16(num) PUT_NUM_SIGN(6, "0%04xh", num, int16_t, uint16_t)
92473d1de9ab080ff886ad61a4d908f7c3429608vboxsync#define PUT_NUM_S32(num) PUT_NUM_SIGN(10, "0%08xh", num, int32_t, uint32_t)
7917e2039cb1b59b67a3a8e26acce7f445860192vboxsync#define PUT_NUM_S64(num) PUT_NUM_SIGN(18, "0%016RX64h", num, int64_t, uint64_t)
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync#define PUT_SYMBOL_TWO(a_rcSym, a_szStart, a_chEnd) \
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync if (off != 0) \
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync } while (0)
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync#define PUT_SYMBOL(a_uSeg, a_uAddr, a_szStart, a_chEnd) \
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync int rcSym = pfnGetSymbol(pDis, a_uSeg, a_uAddr, szSymbol, sizeof(szSymbol), &off, pvUser); \
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync } while (0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * The address?
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync PUT_NUM(9, "%08x`", (uint32_t)(pDis->uInstrAddr >> 32));
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * The opcode bytes?
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync size_t cchTmp = disFormatBytes(pDis, pszDst, cchDst, fFlags);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* Some padding to align the instruction. */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync size_t cchPadding = (7 * (2 + !!(fFlags & DIS_FMT_FLAGS_BYTES_SPACED)))
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync cchPadding = cchTmp + 1 >= cchPadding ? 1 : cchPadding - cchTmp;
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Filter out invalid opcodes first as they need special
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * treatment. UD2 is an exception and should be handled normally.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Adjust the format string to the correct mnemonic
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * or to avoid things the assembler cannot handle correctly.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "jcxz %Jb" : pDis->uOpMode == DISCPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "pushfw" : pDis->uOpMode == DISCPUMODE_32BIT ? "pushfd" : "pushfq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "popfw" : pDis->uOpMode == DISCPUMODE_32BIT ? "popfd" : "popfq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "pushaw" : "pushad";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "popaw" : "popad";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "insw" : pDis->uOpMode == DISCPUMODE_32BIT ? "insd" : "insq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "outsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "outsd" : "outsq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "movsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "movsd" : "movsq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "cmpsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "cmpsd" : "cmpsq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "scasw" : pDis->uOpMode == DISCPUMODE_32BIT ? "scasd" : "scasq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "lodsw" : pDis->uOpMode == DISCPUMODE_32BIT ? "lodsd" : "lodsq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "stosw" : pDis->uOpMode == DISCPUMODE_32BIT ? "stosd" : "stosq";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "cbw" : pDis->uOpMode == DISCPUMODE_32BIT ? "cwde" : "cdqe";
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync pszFmt = pDis->uOpMode == DISCPUMODE_16BIT ? "cwd" : pDis->uOpMode == DISCPUMODE_32BIT ? "cdq" : "cqo";
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Don't know how to tell yasm to generate complicated nop stuff, so 'db' it.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* fine, fine */;
a1952aa85294c02b76ede695d74f0d3a805d6490vboxsync else if (pszFmt[sizeof("nop %Ev") - 1] == '/' && pszFmt[sizeof("nop %Ev")] == 'p')
f3b40e09af69fe4b71f297df0073145e23d52e31vboxsync PUT_NUM_8(MAKE_MODRM(pDis->ModRM.Bits.Mod, pDis->ModRM.Bits.Reg, pDis->ModRM.Bits.Rm));
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* ST(X) -> stX (floating point) */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync if (ch == 'S' && pszFmt[0] == 'T' && pszFmt[1] == '(')
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync const char *pszSpace = (pszDelim ? strchr(pszDelim, ' ') : NULL);
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync if (pszSpace == NULL) pszSpace = strchr(pszDelim, 0);
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync || (*pszFmt == '@' && !VEXREG_IS256B(pDis->bVexDestReg))
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync || (*pszFmt == '&' && ( DISUSE_IS_EFFECTIVE_ADDR(pDis->Param1.fUse)
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync strncpy(pszFmtDst, pszFmt + 1, pszDelim - pszFmt - 1);
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync strncpy(pszFmtDst, pszDelim + 1, pszSpace - pszDelim - 1);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Horrible hacks.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync *(int *)&pDis->Param1.fParam &= ~0x1f; /* make it pure OP_PARM_M */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case OP_LAR: /* hack w -> v, probably not correct. */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Formatting context and associated macros.
70fa291a159216a90eea85d879c46bf4d86ed545vboxsync if ( OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_p \
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } while (0)
95ed338027d70aabb68eff2437bf0d08ebbdbea4vboxsync /** @todo mov ah,ch ends up with a byte 'override'... - check if this wasn't fixed. */
95ed338027d70aabb68eff2437bf0d08ebbdbea4vboxsync /** @todo drop the work/dword/qword override when the src/dst is a register (except for movsx/movzx). */
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync case DISCPUMODE_16BIT: if (OP_PARM_VSUBTYPE(pParam->fParam) != OP_PARM_y) PUT_SZ("word "); break; \
ec1c5db622ee5d1d8b69c47a7a122092512cc2aevboxsync if (pDis->pCurInstr->uOpcode != OP_GATHER || pDis->bVexWFlag) { PUT_SZ("dword "); break; } \
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync default: break; \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync if (OP_PARM_VTYPE(pParam->fParam) == OP_PARM_W || \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync if (VEXREG_IS256B(pDis->bVexDestReg)) PUT_SZ("dword "); \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync if (OP_PARM_VTYPE(pParam->fParam) == OP_PARM_W || \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync if (VEXREG_IS256B(pDis->bVexDestReg)) PUT_SZ("qword "); \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync if (OP_PARM_VTYPE(pParam->fParam) == OP_PARM_W || \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync if (VEXREG_IS256B(pDis->bVexDestReg)) PUT_SZ("oword "); \
d339699e84f24733294c16cb38f37a404032b8a2vboxsync case OP_PARM_x: if (VEXREG_IS256B(pDis->bVexDestReg)) { PUT_SZ("yword "); break; } \
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync case OP_PARM_s: if (pParam->fUse & DISUSE_REG_FP) PUT_SZ("tword "); break; /* ?? */ \
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case OP_PARM_z: break; \
fe95fa9fc2a364e3d678307971cc900b89f5c94avboxsync && ((pParam->fUse & DISUSE_REG_FP) || pOp->uOpcode == OP_FLD)) \
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync default: break; /*no pointer type specified/necessary*/ \
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } while (0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync static const char s_szSegPrefix[6][4] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } while (0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Segment prefixing for instructions that doesn't do memory access.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * The formatting loop.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * ModRM - Register only.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'C': /* Control register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'D': /* Debug register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'G': /* ModRM selects general register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'S': /* ModRM byte selects a segment register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'T': /* ModRM byte selects a test register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'V': /* ModRM byte selects an XMM/SSE register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'P': /* ModRM byte selects MMX register (ParseModRM / UseModRM). */
03e8e21575a0d6ace51c528e7a6fcc35ce69cae7vboxsync case 'H': /* The VEX.vvvv field of the VEX prefix selects a XMM/YMM register. */
d339699e84f24733294c16cb38f37a404032b8a2vboxsync case 'L': /* The upper 4 bits of the 8-bit immediate selects a XMM/YMM register. */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync Assert(!(pParam->fUse & (DISUSE_INDEX | DISUSE_SCALE) /* No SIB here... */));
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync Assert(!(pParam->fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32)));
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * ModRM - Register or memory.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'E': /* ModRM specifies parameter (ParseModRM / UseModRM / UseSIB). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'Q': /* ModRM byte selects MMX register or memory address (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'R': /* ModRM byte may only refer to a general register (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'W': /* ModRM byte selects an XMM/SSE register or a memory address (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'M': /* ModRM may only refer to memory (ParseModRM / UseModRM). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync pszFmt += RT_C_IS_ALPHA(pszFmt[0]) ? RT_C_IS_ALPHA(pszFmt[1]) ? 2 : 1 : 0;
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* Work around mov seg,[mem16] and mov [mem16],seg as these always make a 16-bit mem
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync while the register variants deals with 16, 32 & 64 in the normal fashion. */
3814edbc6a665ea4f1c3dc0c7dc9cb9dd83735b0vboxsync && (fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32)))
a0892a0a33b8ffaa8ff2f252411176f63e8d9f18vboxsync && (int8_t)pParam->uDisp.i16 == (int16_t)pParam->uDisp.i16)
a0892a0a33b8ffaa8ff2f252411176f63e8d9f18vboxsync && (int16_t)pParam->uDisp.i32 == (int32_t)pParam->uDisp.i32) //??
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && (pDis->SIB.Bits.Base != 5 || pDis->ModRM.Bits.Mod != 0)
a0892a0a33b8ffaa8ff2f252411176f63e8d9f18vboxsync && (int32_t)pParam->uDisp.i64 == (int64_t)pParam->uDisp.i64) //??
3814edbc6a665ea4f1c3dc0c7dc9cb9dd83735b0vboxsync bool fBase = (fUse & DISUSE_BASE) /* When exactly is DISUSE_BASE supposed to be set? disasmModRMReg doesn't set it. */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync const char *pszReg = disasmFormatYasmIndexReg(pDis, pParam, &cchReg);
3814edbc6a665ea4f1c3dc0c7dc9cb9dd83735b0vboxsync if (fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32))
3814edbc6a665ea4f1c3dc0c7dc9cb9dd83735b0vboxsync else if (fUse & (DISUSE_DISPLACEMENT32 | DISUSE_RIPDISPLACEMENT32))
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync if (pfnGetSymbol && !fBase && !(fUse & DISUSE_INDEX) && off2 != 0)
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'F': /* Eflags register (0 - popf/pushf only, avoided in adjustments above). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v' || *pszFmt == 'w' || *pszFmt == 'z'); pszFmt++;
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync switch (pParam->fUse & ( DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE64
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync | DISUSE_IMMEDIATE16_SX8 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE64_SX8))
450cb3837567e8aa2c4c99ba2a14aebe69a4572bvboxsync && ( (pOp->fParam1 >= OP_PARM_REG_GEN8_START && pOp->fParam1 <= OP_PARM_REG_GEN8_END)
450cb3837567e8aa2c4c99ba2a14aebe69a4572bvboxsync || (pOp->fParam2 >= OP_PARM_REG_GEN8_START && pOp->fParam2 <= OP_PARM_REG_GEN8_END))
50a3afb1817352d175c128cc6c1d7eefbe4972advboxsync && ( (int8_t)pParam->uValue == (int16_t)pParam->uValue
450cb3837567e8aa2c4c99ba2a14aebe69a4572bvboxsync || (pOp->fParam1 >= OP_PARM_REG_GEN16_START && pOp->fParam1 <= OP_PARM_REG_GEN16_END)
450cb3837567e8aa2c4c99ba2a14aebe69a4572bvboxsync || (pOp->fParam2 >= OP_PARM_REG_GEN16_START && pOp->fParam2 <= OP_PARM_REG_GEN16_END))
70fa291a159216a90eea85d879c46bf4d86ed545vboxsync else if ( OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_v
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync if ( pDis->uOpMode != (pDis->uCpuMode == DISCPUMODE_16BIT ? DISCPUMODE_16BIT : DISCPUMODE_32BIT) /* not perfect */
50a3afb1817352d175c128cc6c1d7eefbe4972advboxsync && ( (int8_t)pParam->uValue == (int32_t)pParam->uValue
450cb3837567e8aa2c4c99ba2a14aebe69a4572bvboxsync || (pOp->fParam1 >= OP_PARM_REG_GEN32_START && pOp->fParam1 <= OP_PARM_REG_GEN32_END)
450cb3837567e8aa2c4c99ba2a14aebe69a4572bvboxsync || (pOp->fParam2 >= OP_PARM_REG_GEN32_START && pOp->fParam2 <= OP_PARM_REG_GEN32_END))
70fa291a159216a90eea85d879c46bf4d86ed545vboxsync else if ( OP_PARM_VSUBTYPE(pParam->fParam) == OP_PARM_v
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uValue, " (=", ')');
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'J': /* Relative jump offset (ParseImmBRel + ParseImmVRel). */
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync Assert(pParam->fUse & (DISUSE_IMMEDIATE32_REL | DISUSE_IMMEDIATE64_REL));
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync RTUINTPTR uTrgAddr = pDis->uInstrAddr + pDis->cbInstr + offDisplacement;
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, " = ", ' ');
22ea035f2c52eb2124f09b0a4bfdacd78caddca4vboxsync PUT_SYMBOL(DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, " (", ')');
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync case 'A': /* Direct (jump/call) address (ParseImmAddr). */
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync switch (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16 | DISUSE_IMMEDIATE_ADDR_16_32 | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT16))
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint16_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint32_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint16_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint32_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint64_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
8e2451f7a9a8e6e722d2065fe0eeb5df93799c7avboxsync switch (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16 | DISUSE_IMMEDIATE_ADDR_16_32 | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT16))
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint16_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_VALUE(pParam->uValue >> 16), (uint32_t)pParam->uValue, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u16, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u32, szSymbol, sizeof(szSymbol), &off, pvUser);
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync rc = pfnGetSymbol(pDis, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u64, szSymbol, sizeof(szSymbol), &off, pvUser);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
e627037a3fdeda1cceedc755167048d121642ba7vboxsync case 'e': /* Register based on operand size (e.g. %eAX, %eAH) (ParseFixedReg). */
e627037a3fdeda1cceedc755167048d121642ba7vboxsync Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2]));
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync const char *pszReg = disasmFormatYasmBaseReg(pDis, pParam, &cchReg);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync AssertMsg(*pszFmt == ',' || *pszFmt == '\0', ("%c%s\n", ch, pszFmt));
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync } /* while more to format */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Any additional output to the right of the instruction?
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* some up front padding. */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync cchPadding = cchPadding + 1 >= 42 ? 1 : 42 - cchPadding;
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* comment? */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * The address?
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync PUT_NUM(9, "%08x`", (uint32_t)(pDis->uInstrAddr >> 32));
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Opcode bytes?
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync size_t cchTmp = disFormatBytes(pDis, pszDst, cchDst, fFlags);
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Terminate it - on overflow we'll have reserved one byte for this.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync /* clean up macros */
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * Formats the current instruction in Yasm (/ Nasm) style.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * This is a simplified version of DISFormatYasmEx() provided for your convenience.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @returns The number of output characters. If this is >= cchBuf, then the content
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * of pszBuf will be truncated.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync * @param pDis Pointer to the disassembler state.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param pszBuf The output buffer.
de6ba1989c812829372828f1801b232b3e7f09bfvboxsync * @param cchBuf The size of the output buffer.
6d51216d13610f142b377a8e15c6c51adb83ba1bvboxsyncDISDECL(size_t) DISFormatYasm(PCDISSTATE pDis, char *pszBuf, size_t cchBuf)
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync return DISFormatYasmEx(pDis, pszBuf, cchBuf, 0 /* fFlags */, NULL /* pfnGetSymbol */, NULL /* pvUser */);
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * Checks if the encoding of the given disassembled instruction is something we
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * can never get YASM to produce.
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * @returns true if it's odd, false if it isn't.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync * @param pDis The disassembler output. The byte fetcher callback will
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * be used if present as we might need to fetch opcode
6d51216d13610f142b377a8e15c6c51adb83ba1bvboxsyncDISDECL(bool) DISFormatYasmIsOddEncoding(PDISSTATE pDis)
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync if ( pDis->uAddrMode != DISCPUMODE_16BIT ///@todo correct?
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* No scaled index SIB (index=4), except for ESP. */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* EBP + displacement */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * Check for multiple prefixes of the same kind.
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync for (uint32_t offOpcode = 0; offOpcode < RT_ELEMENTS(pDis->abInstr); offOpcode++)
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync f = pDis->uCpuMode == DISCPUMODE_64BIT ? DISPREFIX_REX : 0;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync break; /* done */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* segment overrides are fun */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* no effective address which it may apply to. */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync Assert((pDis->fPrefix & DISPREFIX_SEG) || pDis->uCpuMode == DISCPUMODE_64BIT);
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync /* Yasm puts the segment prefixes before the operand prefix with no
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync way of overriding it. */
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* fixed register + addr override doesn't go down all that well. */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && ( pDis->pCurInstr->fParam1 >= OP_PARM_REG_GEN32_START
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam1 <= OP_PARM_REG_GEN32_END))
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync /* Almost all prefixes are bad for jumps. */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* nop w/ prefix(es). */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* fall thru */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /** @todo branch hinting 0x2e/0x3e... */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync /* All but the segment prefix is bad news for push/pop. */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync if ( pDis->pCurInstr->fParam1 >= OP_PARM_REG_SEG_START
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam1 <= OP_PARM_REG_SEG_END)
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam1 >= OP_PARM_REG_GEN32_START
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam1 <= OP_PARM_REG_GEN32_END)
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* Implicit 8-bit register instructions doesn't mix with operand size. */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && ( ( pDis->pCurInstr->fParam1 == OP_PARM_Gb /* r8 */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam2 == OP_PARM_Eb /* r8/mem8 */)
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync || ( pDis->pCurInstr->fParam2 == OP_PARM_Gb /* r8 */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam1 == OP_PARM_Eb /* r8/mem8 */))
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync /* Instructions taking no address or operand which thus may be annoyingly
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync difficult to format for yasm. */
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync /** @todo Many more to can be added here. */
3b3a827f743983461c9737e22d852feae7dd9a07vboxsync return true;
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync /* FPU and other instructions that ignores operand size override. */
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync /** @todo there are many more. */
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync return true;
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync /** @todo could be that we're not disassembling these correctly. */
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync return true;
7306565f20289efa418aa6d90ebaa82fd54f3958vboxsync /** @todo what about the other way? */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * Check for the version of xyz reg,reg instruction that the assembler doesn't use.
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * For example:
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * expected: 1aee sbb ch, dh ; SBB r8, r/m8
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * yasm: 18F5 sbb ch, dh ; SBB r/m8, r8
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync if ( ( pDis->pCurInstr->fParam1 == OP_PARM_Gb /* r8 */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam2 == OP_PARM_Eb /* r8/mem8 */)
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync || ( pDis->pCurInstr->fParam1 == OP_PARM_Gv /* rX */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && pDis->pCurInstr->fParam2 == OP_PARM_Ev /* rX/memX */))
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* 82 (see table A-6). */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* ff /0, fe /0, ff /1, fe /0 */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
76cd534a81a3b479e8a30f0f8182f5fe9c00c3aavboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* shl eax,1 will be assembled to the form without the immediate byte. */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* And some more - see table A-6. */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* check for REX.X = 1 without SIB. */
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync says (intel doesn't appear to care). */
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync AssertMsg(pDis->bOpCode >= 0x90 && pDis->bOpCode <= 0x9f, ("%#x\n", pDis->bOpCode));
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * The MOVZX reg32,mem16 instruction without an operand size prefix
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync * doesn't quite make sense...
377e22fd02a277efa645dfe4e1a327f4fa26c2aavboxsync && (pDis->uCpuMode == DISCPUMODE_16BIT) != !!(fPrefixes & DISPREFIX_OPSIZE))
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return true;
b82fef5dcbe08cae8ce37a09825adc4c6b0bf762vboxsync return false;