2013-09-30 23:01:42 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// $Id$
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Copyright (c) 2013 Stanislav Shwartsman
|
|
|
|
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#define NEED_CPU_REG_SHORTCUTS 1
|
|
|
|
#include "bochs.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#define LOG_THIS BX_CPU_THIS_PTR
|
|
|
|
|
|
|
|
#include "fetchdecode.h"
|
|
|
|
|
|
|
|
// table of all Bochs opcodes
|
|
|
|
extern struct bxIAOpcodeTable BxOpcodesTable[];
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
char* dis_sprintf(char *disbufptr, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsprintf(disbufptr, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
disbufptr += strlen(disbufptr);
|
|
|
|
return disbufptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* dis_putc(char *disbufptr, char symbol)
|
|
|
|
{
|
|
|
|
*disbufptr++ = symbol;
|
|
|
|
*disbufptr = 0;
|
|
|
|
return disbufptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *intel_general_16bit_regname[16] = {
|
|
|
|
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
|
|
|
|
"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
|
|
|
|
};
|
|
|
|
|
2013-10-01 22:47:55 +04:00
|
|
|
static const char *intel_general_32bit_regname[17] = {
|
2013-09-30 23:01:42 +04:00
|
|
|
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
|
2013-10-01 22:47:55 +04:00
|
|
|
"r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", "eip"
|
2013-09-30 23:01:42 +04:00
|
|
|
};
|
|
|
|
|
2013-10-01 22:47:55 +04:00
|
|
|
static const char *intel_general_64bit_regname[17] = {
|
2013-09-30 23:01:42 +04:00
|
|
|
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
|
2013-10-01 22:47:55 +04:00
|
|
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rip"
|
2013-09-30 23:01:42 +04:00
|
|
|
};
|
|
|
|
|
2013-10-05 22:51:28 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
2013-09-30 23:01:42 +04:00
|
|
|
static const char *intel_general_8bit_regname_rex[16] = {
|
|
|
|
"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
|
|
|
|
"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
|
|
|
|
};
|
2013-10-05 22:51:28 +04:00
|
|
|
#endif
|
2013-09-30 23:01:42 +04:00
|
|
|
|
|
|
|
static const char *intel_general_8bit_regname[8] = {
|
|
|
|
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *intel_segment_name[8] = {
|
|
|
|
"es", "cs", "ss", "ds", "fs", "gs", "??", "??"
|
|
|
|
};
|
|
|
|
|
2013-10-01 22:47:55 +04:00
|
|
|
#if BX_SUPPORT_EVEX
|
|
|
|
static const char *rounding_mode[4] = {
|
|
|
|
"round_nearest_even", "round_down", "round_up", "round_to_zero"
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2013-10-06 23:04:52 +04:00
|
|
|
#define BX_JUMP_TARGET_NOT_REQ ((bx_address)(-1))
|
|
|
|
|
2013-09-30 23:01:42 +04:00
|
|
|
char *resolve_memref(char *disbufptr, const bxInstruction_c *i, const char *regname[])
|
|
|
|
{
|
2013-10-02 23:23:34 +04:00
|
|
|
unsigned sib_base = i->sibBase(), sib_index = i->sibIndex(), sib_scale = i->sibScale();
|
|
|
|
|
2013-10-05 15:00:31 +04:00
|
|
|
if (sib_index == 4) sib_index = BX_NIL_REGISTER;
|
|
|
|
|
2013-10-02 23:23:34 +04:00
|
|
|
if (sib_base == BX_NIL_REGISTER)
|
2013-10-01 00:16:52 +04:00
|
|
|
{
|
2013-10-02 23:23:34 +04:00
|
|
|
if (sib_index == BX_NIL_REGISTER)
|
2013-10-01 00:16:52 +04:00
|
|
|
{
|
2013-10-05 23:32:09 +04:00
|
|
|
if (! i->as32L()) {
|
2013-10-06 23:04:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%04x", (Bit32u) (Bit16u) i->displ16s());
|
2013-10-01 00:16:52 +04:00
|
|
|
}
|
|
|
|
else {
|
2013-10-06 23:04:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%08x", (Bit32u) i->displ32s());
|
2013-10-01 00:16:52 +04:00
|
|
|
}
|
|
|
|
return disbufptr;
|
|
|
|
}
|
2013-09-30 23:01:42 +04:00
|
|
|
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s", regname[i->sibIndex()]);
|
2013-10-02 23:23:34 +04:00
|
|
|
if (sib_scale)
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "*%d", 1 << i->sibScale());
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
2013-10-01 00:16:52 +04:00
|
|
|
else {
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s", regname[i->sibBase()]);
|
2013-09-30 23:01:42 +04:00
|
|
|
|
2013-10-02 23:23:34 +04:00
|
|
|
if (sib_index != BX_NIL_REGISTER)
|
2013-10-01 00:16:52 +04:00
|
|
|
{
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "+%s", regname[i->sibIndex()]);
|
2013-10-02 23:23:34 +04:00
|
|
|
if (sib_scale)
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "*%d", 1 << i->sibScale());
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-05 23:32:09 +04:00
|
|
|
if (! i->as32L()) {
|
2013-09-30 23:01:42 +04:00
|
|
|
if (i->displ16s() != 0) {
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%+d", (Bit32s) i->displ16s());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-10-01 00:16:52 +04:00
|
|
|
if (i->displ32s() != 0) {
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%+d", i->displ32s());
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_putc(disbufptr, ']');
|
2013-09-30 23:01:42 +04:00
|
|
|
return disbufptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *resolve_memref(char *disbufptr, const bxInstruction_c *i)
|
|
|
|
{
|
2013-10-01 00:16:52 +04:00
|
|
|
// seg:[base + index*scale + disp]
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s:", intel_segment_name[i->seg()]);
|
2013-10-02 23:23:34 +04:00
|
|
|
if (i->as64L()) {
|
2013-09-30 23:01:42 +04:00
|
|
|
disbufptr = resolve_memref(disbufptr, i, intel_general_64bit_regname);
|
|
|
|
}
|
2013-10-02 23:23:34 +04:00
|
|
|
else if (i->as32L()) {
|
2013-09-30 23:01:42 +04:00
|
|
|
disbufptr = resolve_memref(disbufptr, i, intel_general_32bit_regname);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
disbufptr = resolve_memref(disbufptr, i, intel_general_16bit_regname);
|
|
|
|
}
|
|
|
|
return disbufptr;
|
|
|
|
}
|
|
|
|
|
2013-10-02 00:17:21 +04:00
|
|
|
char* disasm(char *disbufptr, const bxInstruction_c *i, bx_address cs_base, bx_address rip)
|
2013-09-30 23:01:42 +04:00
|
|
|
{
|
2013-10-02 23:23:34 +04:00
|
|
|
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
|
2013-10-01 22:47:55 +04:00
|
|
|
if (i->getIaOpcode() == BX_INSERTED_OPCODE) {
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "(bochs inserted internal opcode)");
|
|
|
|
return disbufptr;
|
|
|
|
}
|
2013-10-02 23:23:34 +04:00
|
|
|
#endif
|
2013-10-01 22:47:55 +04:00
|
|
|
|
2013-10-04 22:14:54 +04:00
|
|
|
if (i->execute1 == &BX_CPU_C::BxError) {
|
2013-10-01 22:47:55 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "(invalid)");
|
|
|
|
return disbufptr;
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *opname = i->getIaOpcodeName() + 6; // skip the "BX_IA_"
|
|
|
|
unsigned n;
|
2013-10-01 22:47:55 +04:00
|
|
|
#if BX_SUPPORT_EVEX
|
|
|
|
bx_bool is_vector = BX_FALSE;
|
|
|
|
#endif
|
2013-09-30 23:01:42 +04:00
|
|
|
|
2013-10-01 22:47:55 +04:00
|
|
|
if (! strncmp(opname, "V128_", 5) || ! strncmp(opname, "V256_", 5) || ! strncmp(opname, "V512_", 5)) {
|
|
|
|
opname += 5;
|
|
|
|
#if BX_SUPPORT_EVEX
|
|
|
|
is_vector = BX_TRUE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! strncmp(opname, "REP_", 4)) {
|
2013-09-30 23:01:42 +04:00
|
|
|
opname += 4;
|
|
|
|
|
2013-10-02 23:23:34 +04:00
|
|
|
// Step 1: print prefixes
|
|
|
|
if (i->repUsedL()) {
|
|
|
|
if (i->repUsedValue() == 2)
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "repne ");
|
|
|
|
else
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "rep ");
|
|
|
|
}
|
2013-10-01 22:47:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Step 2: print opcode name
|
2013-09-30 23:01:42 +04:00
|
|
|
unsigned opname_len = strlen(opname);
|
|
|
|
for (n=0;n < opname_len; n++) {
|
|
|
|
if (opname[n] == '_') break;
|
|
|
|
disbufptr = dis_putc(disbufptr, tolower(opname[n]));
|
|
|
|
}
|
|
|
|
|
|
|
|
disbufptr = dis_putc(disbufptr, ' ');
|
|
|
|
|
2013-10-01 22:47:55 +04:00
|
|
|
// Step 3: print sources
|
2013-09-30 23:01:42 +04:00
|
|
|
Bit16u ia_opcode = i->getIaOpcode();
|
|
|
|
unsigned srcs_used = 0;
|
|
|
|
for (n = 0; n <= 3; n++) {
|
|
|
|
unsigned src = (unsigned) BxOpcodesTable[ia_opcode].src[n];
|
2013-10-01 22:47:55 +04:00
|
|
|
unsigned src_type = src >> 3;
|
|
|
|
if (! src_type && src != BX_SRC_RM) continue;
|
2013-09-30 23:01:42 +04:00
|
|
|
if (srcs_used++ > 0)
|
|
|
|
disbufptr = dis_sprintf(disbufptr, ", ");
|
|
|
|
|
|
|
|
if (! i->modC0() && ((src & 0x7) == BX_SRC_RM)) {
|
|
|
|
disbufptr = resolve_memref(disbufptr, i);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
unsigned srcreg = i->getSrcReg(n);
|
|
|
|
if (src_type < 0x10) {
|
|
|
|
switch(src_type) {
|
|
|
|
case BX_GPR8:
|
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
if (i->extend8bitL())
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s", intel_general_8bit_regname_rex[srcreg]);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s", intel_general_8bit_regname[srcreg]);
|
|
|
|
break;
|
|
|
|
case BX_GPR16:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s", intel_general_16bit_regname[srcreg]);
|
|
|
|
break;
|
|
|
|
case BX_GPR32:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s", intel_general_32bit_regname[srcreg]);
|
|
|
|
break;
|
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
case BX_GPR64:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s", intel_general_64bit_regname[srcreg]);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case BX_FPU_REG:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "st(%d)", srcreg);
|
|
|
|
break;
|
|
|
|
case BX_MMX_REG:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "mm%d", srcreg);
|
|
|
|
break;
|
|
|
|
case BX_VMM_REG:
|
|
|
|
#if BX_SUPPORT_AVX
|
2013-10-01 22:47:55 +04:00
|
|
|
if (i->getVL() > BX_NO_VL) {
|
2013-09-30 23:01:42 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "%cmm%d", 'x' + i->getVL() - 1, srcreg);
|
2013-10-01 22:47:55 +04:00
|
|
|
#if BX_SUPPORT_EVEX
|
|
|
|
if (n == 0 && i->opmask()) {
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "{k%d}%s", i->opmask(),
|
|
|
|
i->isZeroMasking() ? "{z}" : "");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2013-09-30 23:01:42 +04:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "xmm%d", srcreg);
|
|
|
|
break;
|
|
|
|
#if BX_SUPPORT_EVEX
|
|
|
|
case BX_KMASK_REG:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "k%d", srcreg);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case BX_SEGREG:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s", intel_segment_name[srcreg]);
|
|
|
|
break;
|
|
|
|
case BX_CREG:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "cr%d", srcreg);
|
|
|
|
break;
|
|
|
|
case BX_DREG:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "dr%d", srcreg);
|
|
|
|
break;
|
|
|
|
default:
|
2013-10-01 22:47:55 +04:00
|
|
|
if (src_type != BX_NO_REG)
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "(unknown source type %d)", src_type);
|
2013-09-30 23:01:42 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch(src_type) {
|
|
|
|
case BX_IMMB:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%02x", i->Ib());
|
|
|
|
break;
|
|
|
|
case BX_IMMW:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%04x", i->Iw());
|
|
|
|
break;
|
|
|
|
case BX_IMMD:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%08x", i->Id());
|
|
|
|
break;
|
2013-10-04 21:26:56 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
2013-10-06 22:10:58 +04:00
|
|
|
case BX_IMMD_SE:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x" FMT_ADDRX64, (Bit64u) (Bit32s) i->Id());
|
|
|
|
break;
|
2013-09-30 23:01:42 +04:00
|
|
|
case BX_IMMQ:
|
2013-10-02 23:23:34 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x" FMT_ADDRX64, i->Iq());
|
2013-09-30 23:01:42 +04:00
|
|
|
break;
|
2013-10-04 21:26:56 +04:00
|
|
|
#endif
|
2013-10-01 00:16:52 +04:00
|
|
|
case BX_IMMB2:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%02x", i->Ib2());
|
|
|
|
break;
|
2013-09-30 23:01:42 +04:00
|
|
|
case BX_IMM_BrOff16:
|
2013-10-02 00:17:21 +04:00
|
|
|
{
|
|
|
|
Bit16u target = (rip + i->ilen() + (Bit16s) i->Iw()) & 0xffff;
|
|
|
|
disbufptr = dis_sprintf(disbufptr, ".%+d (0x%08x)", i->Iw(), (Bit32u)(cs_base + target));
|
|
|
|
}
|
2013-09-30 23:01:42 +04:00
|
|
|
break;
|
|
|
|
case BX_IMM_BrOff32:
|
2013-10-02 00:17:21 +04:00
|
|
|
{
|
2013-10-06 23:04:52 +04:00
|
|
|
Bit32u target = rip + i->ilen() + (Bit32s) i->Id();
|
|
|
|
disbufptr = dis_sprintf(disbufptr, ".%+d (0x%08x)", i->Id(), (Bit32u) (cs_base + target));
|
|
|
|
}
|
|
|
|
break;
|
2013-10-06 22:37:56 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
2013-10-06 23:04:52 +04:00
|
|
|
case BX_IMM_BrOff64:
|
|
|
|
{
|
|
|
|
Bit64u target = rip + i->ilen() + (Bit32s) i->Id();
|
|
|
|
disbufptr = dis_sprintf(disbufptr, ".%+d (0x" FMT_ADDRX ")", i->Id(), (Bit64u) (cs_base + target));
|
2013-10-02 00:17:21 +04:00
|
|
|
}
|
2013-09-30 23:01:42 +04:00
|
|
|
break;
|
2013-10-06 23:04:52 +04:00
|
|
|
#endif
|
2013-09-30 23:01:42 +04:00
|
|
|
case BX_RSIREF:
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s:", intel_segment_name[i->seg()]);
|
2013-10-04 21:26:56 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
2013-09-30 23:01:42 +04:00
|
|
|
if (i->as64L()) {
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s]", intel_general_64bit_regname[BX_64BIT_REG_RSI]);
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
2013-10-04 21:26:56 +04:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2013-09-30 23:01:42 +04:00
|
|
|
if (i->as32L())
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s]", intel_general_32bit_regname[BX_32BIT_REG_ESI]);
|
2013-09-30 23:01:42 +04:00
|
|
|
else
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s]", intel_general_16bit_regname[BX_16BIT_REG_SI]);
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BX_RDIREF:
|
2013-10-05 12:34:09 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s:", intel_segment_name[BX_SEG_REG_ES]);
|
2013-10-04 21:26:56 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
2013-09-30 23:01:42 +04:00
|
|
|
if (i->as64L()) {
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s]", intel_general_64bit_regname[BX_64BIT_REG_RDI]);
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
2013-10-04 21:26:56 +04:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2013-09-30 23:01:42 +04:00
|
|
|
if (i->as32L())
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s]", intel_general_32bit_regname[BX_32BIT_REG_EDI]);
|
2013-09-30 23:01:42 +04:00
|
|
|
else
|
2013-10-01 00:16:52 +04:00
|
|
|
disbufptr = dis_sprintf(disbufptr, "[%s]", intel_general_16bit_regname[BX_16BIT_REG_DI]);
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|
|
|
|
break;
|
2013-10-01 22:47:55 +04:00
|
|
|
case BX_USECL:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "cl");
|
|
|
|
break;
|
|
|
|
case BX_USEDX:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "dx");
|
|
|
|
break;
|
2013-10-02 23:23:34 +04:00
|
|
|
case BX_DIRECT_PTR:
|
|
|
|
if (i->os32L())
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%04x:%08x", i->Iw2(), i->Id());
|
|
|
|
else
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%04x:%04x", i->Iw2(), i->Iw());
|
|
|
|
break;
|
2013-10-01 22:47:55 +04:00
|
|
|
case BX_DIRECT_MEMREF32:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s:", intel_segment_name[i->seg()]);
|
|
|
|
if (! i->as32L())
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%04x", i->Id());
|
|
|
|
else
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "0x%08x", i->Id());
|
|
|
|
break;
|
2013-10-05 22:51:28 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
2013-10-01 22:47:55 +04:00
|
|
|
case BX_DIRECT_MEMREF64:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "%s:0x" FMT_ADDRX, intel_segment_name[i->seg()], i->Iq());
|
|
|
|
break;
|
2013-10-05 22:51:28 +04:00
|
|
|
#endif
|
2013-09-30 23:01:42 +04:00
|
|
|
default:
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "(unknown source type %d)", src_type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-10-01 22:47:55 +04:00
|
|
|
|
|
|
|
#if BX_SUPPORT_EVEX
|
|
|
|
if (is_vector && i->getEvexb()) {
|
|
|
|
if (! i->modC0())
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "{broadcast TBD}");
|
|
|
|
else
|
|
|
|
disbufptr = dis_sprintf(disbufptr, "{sae/%s}", rounding_mode[i->getRC()]);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return disbufptr;
|
2013-09-30 23:01:42 +04:00
|
|
|
}
|