DisasmFormatYasm.cpp revision 450cb3837567e8aa2c4c99ba2a14aebe69a4572b
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VBox Disassembler - Yasm(/Nasm) Style Formatter.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Copyright (C) 2008-2012 Oracle Corporation
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/*******************************************************************************
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync* Header Files *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync*******************************************************************************/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/*******************************************************************************
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync* Global Variables *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync*******************************************************************************/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic const char g_szSpaces[] =
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync "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"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Gets the base register name for the given parameter.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns Pointer to the register name.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @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 *disasmFormatYasmBaseReg(PCDISCPUSTATE pCpu, PCDISOPPARAM pParam, size_t *pcchReg)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync switch (pParam->fUse & ( DISUSE_REG_GEN8 | DISUSE_REG_GEN16 | DISUSE_REG_GEN32 | DISUSE_REG_GEN64
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync | DISUSE_REG_FP | DISUSE_REG_MMX | DISUSE_REG_XMM | DISUSE_REG_CR
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync | DISUSE_REG_DBG | DISUSE_REG_SEG | DISUSE_REG_TEST))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen8));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen8[pParam->base.reg_gen];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen16));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen16[pParam->base.reg_gen];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen32));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen32[pParam->base.reg_gen];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_gen < RT_ELEMENTS(g_aszYasmRegGen64));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegGen64[pParam->base.reg_gen];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_fp < RT_ELEMENTS(g_aszYasmRegFP));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegFP[pParam->base.reg_fp];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_mmx < RT_ELEMENTS(g_aszYasmRegMMX));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegMMX[pParam->base.reg_mmx];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_xmm < RT_ELEMENTS(g_aszYasmRegXMM));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *psz = g_aszYasmRegXMM[pParam->base.reg_mmx];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->base.reg_ctrl < RT_ELEMENTS(g_aszYasmRegCRx));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync 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 < 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??";
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Gets the index register name for the given parameter.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns The index register name.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @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, PCDISOPPARAM 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];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertMsgFailed(("%#x %#x\n", pParam->fUse, pCpu->uAddrMode));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return "r??";
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Formats the current instruction in Yasm (/ Nasm) style.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns The number of output characters. If this is >= cchBuf, then the content
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * of pszBuf will be truncated.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pCpu Pointer to the disassembler CPU state.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pszBuf The output buffer.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @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.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDISDECL(size_t) DISFormatYasmEx(PCDISCPUSTATE pCpu, char *pszBuf, size_t cchBuf, uint32_t fFlags,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Input validation and massaging.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync 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)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } while (0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync 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))
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_16(num) PUT_NUM(6, "0%04xh", (uint16_t)(num))
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_32(num) PUT_NUM(10, "0%08xh", (uint32_t)(num))
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_64(num) PUT_NUM(18, "0%016RX64h", (uint64_t)(num))
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync } while (0)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_S8(num) PUT_NUM_SIGN(4, "0%02xh", num, int8_t, uint8_t)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_S16(num) PUT_NUM_SIGN(6, "0%04xh", num, int16_t, uint16_t)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_S32(num) PUT_NUM_SIGN(10, "0%08xh", num, int32_t, uint32_t)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync#define PUT_NUM_S64(num) PUT_NUM_SIGN(18, "0%016RX64h", num, int64_t, uint64_t)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * The address?
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync PUT_NUM(9, "%08x`", (uint32_t)(pCpu->uInstrAddr >> 32));
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * The opcode bytes?
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync size_t cchTmp = disFormatBytes(pCpu, pszDst, cchDst, fFlags);
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync /* Some padding to align the instruction. */
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync size_t cchPadding = (7 * (2 + !!(fFlags & DIS_FMT_FLAGS_BYTES_SPACED)))
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync cchPadding = cchTmp + 1 >= cchPadding ? 1 : cchPadding - cchTmp;
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * Filter out invalid opcodes first as they need special
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * treatment. UD2 is an exception and should be handled normally.
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * Adjust the format string to the correct mnemonic
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * or to avoid things the assembler cannot handle correctly.
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "jcxz %Jb" : pCpu->uOpMode == DISCPUMODE_32BIT ? "jecxz %Jb" : "jrcxz %Jb";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "pushfw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "pushfd" : "pushfq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "popfw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "popfd" : "popfq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "pushaw" : "pushad";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "popaw" : "popad";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "insw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "insd" : "insq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "outsw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "outsd" : "outsq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "movsw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "movsd" : "movsq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "cmpsw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "cmpsd" : "cmpsq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "scasw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "scasd" : "scasq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "lodsw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "lodsd" : "lodsq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "stosw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "stosd" : "stosq";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "cbw" : pCpu->uOpMode == DISCPUMODE_32BIT ? "cwde" : "cdqe";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync pszFmt = pCpu->uOpMode == DISCPUMODE_16BIT ? "cwd" : pCpu->uOpMode == DISCPUMODE_32BIT ? "cdq" : "cqo";
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * Don't know how to tell yasm to generate complicated nop stuff, so 'db' it.
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync /* fine, fine */;
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync else if (pszFmt[sizeof("nop %Ev") - 1] == '/' && pszFmt[sizeof("nop %Ev")] == 'p')
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync /* ST(X) -> stX (floating point) */
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync if (ch == 'S' && pszFmt[0] == 'T' && pszFmt[1] == '(')
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * Horrible hacks.
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync *(int *)&pCpu->param1.param &= ~0x1f; /* make it pure OP_PARM_M */
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync case OP_LAR: /* hack w -> v, probably not correct. */
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync * Formatting context and associated macros.
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync if ( OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_p \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync } while (0)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync /** @todo mov ah,ch ends up with a byte 'override'... - check if this wasn't fixed. */
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync /** @todo drop the work/dword/qword override when the src/dst is a register (except for movsx/movzx). */
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync default: break; \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync if (OP_PARM_VTYPE(pParam->param) != OP_PARM_W) /* these are 128 bit, pray they are all unambiguous.. */ \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync case OP_PARM_s: if (pParam->fUse & DISUSE_REG_FP) PUT_SZ("tword "); break; /* ?? */ \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync case OP_PARM_z: break; \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync && ((pParam->fUse & DISUSE_REG_FP) || pOp->uOpcode == OP_FLD)) \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync default: break; /*no pointer type specified/necessary*/ \
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync } while (0)
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync static const char s_szSegPrefix[6][4] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
340ee06f35257fee1bd68223ab3504cf2b1d0c3evboxsync } 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;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(!(pParam->fUse & (DISUSE_INDEX | DISUSE_SCALE) /* No SIB here... */));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(!(pParam->fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_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 && (fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32)))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (int8_t)pParam->uDisp.i16 == (int16_t)pParam->uDisp.i16)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (int16_t)pParam->uDisp.i32 == (int32_t)pParam->uDisp.i32) //??
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (pCpu->SIB.Bits.Base != 5 || pCpu->ModRM.Bits.Mod != 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && (int32_t)pParam->uDisp.i64 == (int64_t)pParam->uDisp.i64) //??
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync bool fBase = (fUse & DISUSE_BASE) /* When exactly is DISUSE_BASE supposed to be set? disasmModRMReg doesn't set it. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmIndexReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (fUse & (DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_RIPDISPLACEMENT32))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else if (fUse & (DISUSE_DISPLACEMENT32 | DISUSE_RIPDISPLACEMENT32))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'F': /* Eflags register (0 - popf/pushf only, avoided in adjustments above). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'I': /* Immediate data (ParseImmByte, ParseImmByteSX, ParseImmV, ParseImmUshort, ParseImmZ). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v' || *pszFmt == 'w' || *pszFmt == 'z'); pszFmt++;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync switch (pParam->fUse & ( DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE64
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync | DISUSE_IMMEDIATE16_SX8 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE64_SX8))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ( (pOp->fParam1 >= OP_PARM_REG_GEN8_START && pOp->fParam1 <= OP_PARM_REG_GEN8_END)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (pOp->fParam2 >= OP_PARM_REG_GEN8_START && pOp->fParam2 <= OP_PARM_REG_GEN8_END))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ( (int8_t)pParam->parval == (int16_t)pParam->parval
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (pOp->fParam1 >= OP_PARM_REG_GEN16_START && pOp->fParam1 <= OP_PARM_REG_GEN16_END)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (pOp->fParam2 >= OP_PARM_REG_GEN16_START && pOp->fParam2 <= OP_PARM_REG_GEN16_END))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else if ( OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( pCpu->uOpMode != (pCpu->uCpuMode == DISCPUMODE_16BIT ? DISCPUMODE_16BIT : DISCPUMODE_32BIT) /* not perfect */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ( (int8_t)pParam->parval == (int32_t)pParam->parval
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (pOp->fParam1 >= OP_PARM_REG_GEN32_START && pOp->fParam1 <= OP_PARM_REG_GEN32_END)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (pOp->fParam2 >= OP_PARM_REG_GEN32_START && pOp->fParam2 <= OP_PARM_REG_GEN32_END))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else if ( OP_PARM_VSUBTYPE(pParam->param) == OP_PARM_v
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'J': /* Relative jump offset (ParseImmBRel + ParseImmVRel). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(pParam->fUse & (DISUSE_IMMEDIATE32_REL|DISUSE_IMMEDIATE64_REL));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync RTUINTPTR uTrgAddr = pCpu->uInstrAddr + pCpu->cbInstr + offDisplacement;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync int rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), uTrgAddr, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'A': /* Direct (jump/call) address (ParseImmAddr). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync switch (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16 | DISUSE_IMMEDIATE_ADDR_16_32 | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT16))
3a343ca21a267ec3c54e2317e2ed18fe99b8ebbbvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), (uint64_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync switch (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16 | DISUSE_IMMEDIATE_ADDR_16_32 | DISUSE_DISPLACEMENT64 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT16))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint16_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_VALUE(pParam->parval >> 16), (uint32_t)pParam->parval, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u16, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u32, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = pfnGetSymbol(pCpu, DIS_FMT_SEL_FROM_REG(DISSELREG_CS), pParam->uDisp.u64, szSymbol, sizeof(szSymbol), &off, pvUser);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(*pszFmt == 'b' || *pszFmt == 'v'); pszFmt++;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 'e': /* Register based on operand size (e.g. %eAX) (ParseFixedReg). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert(RT_C_IS_ALPHA(pszFmt[0]) && RT_C_IS_ALPHA(pszFmt[1]) && !RT_C_IS_ALPHA(pszFmt[2])); pszFmt += 2;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync const char *pszReg = disasmFormatYasmBaseReg(pCpu, pParam, &cchReg);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertMsg(*pszFmt == ',' || *pszFmt == '\0', ("%c%s\n", ch, pszFmt));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync } /* while more to format */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Any additional output to the right of the instruction?
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* some up front padding. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cchPadding = cchPadding + 1 >= 42 ? 1 : 42 - cchPadding;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* comment? */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_RIGHT))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The address?
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PUT_NUM(9, "%08x`", (uint32_t)(pCpu->uInstrAddr >> 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.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * 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.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pCpu Pointer to the disassembler CPU state.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @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)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return DISFormatYasmEx(pCpu, pszBuf, cchBuf, 0 /* fFlags */, NULL /* pfnGetSymbol */, NULL /* pvUser */);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Checks if the encoding of the given disassembled instruction is something we
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * can never get YASM to produce.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @returns true if it's odd, false if it isn't.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @param pCpu The disassembler output. The byte fetcher callback will
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * be used if present as we might need to fetch opcode
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDISDECL(bool) DISFormatYasmIsOddEncoding(PDISCPUSTATE pCpu)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( pCpu->uAddrMode != DISCPUMODE_16BIT ///@todo correct?
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* No scaled index SIB (index=4), except for ESP. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* EBP + displacement */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Check for multiple prefixes of the same kind.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync for (uint32_t offOpcode = 0; offOpcode < RT_ELEMENTS(pCpu->abInstr); offOpcode++)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
c58dc77ef4af214d7ae06910fa5ab18587d2ae08vboxsync f = pCpu->uCpuMode == DISCPUMODE_64BIT ? DISPREFIX_REX : 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync break; /* done */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* segment overrides are fun */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* no effective address which it may apply to. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync Assert((pCpu->fPrefix & DISPREFIX_SEG) || pCpu->uCpuMode == DISCPUMODE_64BIT);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* fixed register + addr override doesn't go down all that well. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ( pCpu->pCurInstr->fParam1 >= OP_PARM_REG_GEN32_START
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam1 <= OP_PARM_REG_GEN32_END))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Almost all prefixes are bad. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* nop w/ prefix(es). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* fall thru */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /** @todo branch hinting 0x2e/0x3e... */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* All but the segment prefix is bad news. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( pCpu->pCurInstr->fParam1 >= OP_PARM_REG_SEG_START
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam1 <= OP_PARM_REG_SEG_END)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam1 >= OP_PARM_REG_GEN32_START
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam1 <= OP_PARM_REG_GEN32_END)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9cdd4d805ecb43126372f7cf12e4032836cb738avboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Implicit 8-bit register instructions doesn't mix with operand size. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && ( ( pCpu->pCurInstr->fParam1 == OP_PARM_Gb /* r8 */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam2 == OP_PARM_Eb /* r8/mem8 */)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || ( pCpu->pCurInstr->fParam2 == OP_PARM_Gb /* r8 */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam1 == OP_PARM_Eb /* r8/mem8 */))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Check for the version of xyz reg,reg instruction that the assembler doesn't use.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * For example:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * expected: 1aee sbb ch, dh ; SBB r8, r/m8
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * yasm: 18F5 sbb ch, dh ; SBB r/m8, r8
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( ( pCpu->pCurInstr->fParam1 == OP_PARM_Gb /* r8 */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam2 == OP_PARM_Eb /* r8/mem8 */)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || ( pCpu->pCurInstr->fParam1 == OP_PARM_Gv /* rX */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && pCpu->pCurInstr->fParam2 == OP_PARM_Ev /* rX/memX */))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* 82 (see table A-6). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* ff /0, fe /0, ff /1, fe /0 */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* shl eax,1 will be assembled to the form without the immediate byte. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* And some more - see table A-6. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* check for REX.X = 1 without SIB. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync says (intel doesn't appear to care). */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync AssertMsg(pCpu->bOpCode >= 0x90 && pCpu->bOpCode <= 0x9f, ("%#x\n", pCpu->bOpCode));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return true;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The MOVZX reg32,mem16 instruction without an operand size prefix
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * doesn't quite make sense...
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync && (pCpu->uCpuMode == DISCPUMODE_16BIT) != !!(fPrefixes & DISPREFIX_OPSIZE))
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync return true;
441b60f8b0601cc1718368c9c3ef082223ad12a2vboxsync return false;