Merge new disasm module with x96-64 support

This commit is contained in:
Stanislav Shwartsman 2005-12-23 14:15:13 +00:00
parent 520da21dcf
commit 276c006129
9 changed files with 7185 additions and 3411 deletions

View File

@ -81,7 +81,7 @@ dist-clean: clean
# dependencies generated by
# gcc -MM -I.. -I../instrument/stubs *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g'
###########################################
dis_decode.o: dis_decode.@CPP_SUFFIX@ disasm.h ../config.h dis_tables.h
dis_decode.o: dis_decode.@CPP_SUFFIX@ disasm.h ../config.h dis_tables.h opcodes.inc dis_tables.inc
dis_groups.o: dis_groups.@CPP_SUFFIX@ disasm.h ../config.h
resolve.o: resolve.@CPP_SUFFIX@ disasm.h ../config.h
syntax.o: syntax.@CPP_SUFFIX@ disasm.h ../config.h

View File

@ -5,6 +5,9 @@
#include "disasm.h"
#include "dis_tables.h"
#define OPCODE(entry) ((BxDisasmOpcodeInfo_t*) entry->OpcodeInfo)
#define OPCODE_TABLE(entry) ((BxDisasmOpcodeTable_t*) entry->OpcodeInfo)
static const unsigned char instruction_has_modrm[512] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
@ -56,19 +59,21 @@ unsigned disassembler::disasm32(bx_address base, bx_address ip, Bit8u *instr, ch
return disasm(1, 0, base, ip, instr, disbuf);
}
unsigned disassembler::disasm64(bx_address base, bx_address ip, Bit8u *instr, char *disbuf)
{
return disasm(1, 1, base, ip, instr, disbuf);
}
unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, Bit8u *instr, char *disbuf)
{
os_32 = is_32;
as_32 = is_32;
x86_insn insn(is_32, is_64);
Bit8u *instruction_begin = instruction = instr;
resolve_modrm = NULL;
unsigned n_prefixes = 0;
db_eip = ip;
db_base = base; // cs linear base (base for PM & cs<<4 for RM & VM)
Bit8u *instruction_begin = instruction = instr;
displacement.displ32 = 0;
resolve_modrm = NULL;
seg_override = NULL;
n_prefixes = 0;
disbufptr = disbuf; // start sprintf()'ing into beginning of buffer
#define SSE_PREFIX_NONE 0
@ -78,71 +83,127 @@ unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_
static int sse_prefix_index[8] = { 0, 1, 2, -1, 3, -1, -1, -1 };
unsigned sse_prefix = SSE_PREFIX_NONE;
int b1;
const BxDisasmOpcodeInfo_t *entry;
for(;;)
{
b1 = fetch_byte();
entry = &BxDisasmOpcodes[b1];
insn.b1 = fetch_byte();
n_prefixes++;
if (entry->Attr == _PREFIX)
{
switch(b1) {
case 0xf3:
switch(insn.b1) {
case 0xf3: // rep
sse_prefix |= SSE_PREFIX_F3;
break;
continue;
case 0xf2:
case 0xf2: // repne
sse_prefix |= SSE_PREFIX_F2;
break;
continue;
case 0x2e:
case 0x36:
case 0x3e:
case 0x26:
case 0x64:
case 0x65:
seg_override = entry->Opcode;
break;
case 0x40: // rex
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F:
if (! is_64) break;
insn.extend8b = 1;
if (insn.b1 & 0x8) {
insn.os_64 = 1;
insn.os_32 = 1;
}
if (insn.b1 & 0x4) insn.rex_r = 8;
if (insn.b1 & 0x2) insn.rex_x = 8;
if (insn.b1 & 0x1) insn.rex_b = 8;
continue;
case 0x66:
os_32 = !is_32;
case 0x26: // ES:
if (! is_64) insn.seg_override = ES_REG;
continue;
case 0x2e: // CS:
if (! is_64) insn.seg_override = CS_REG;
continue;
case 0x36: // SS:
if (! is_64) insn.seg_override = SS_REG;
continue;
case 0x3e: // DS:
if (! is_64) insn.seg_override = DS_REG;
continue;
case 0x64: // FS:
insn.seg_override = FS_REG;
continue;
case 0x65: // GS:
insn.seg_override = GS_REG;
continue;
case 0x66: // operand size override
if (!insn.os_64) insn.os_32 = !is_32;
sse_prefix |= SSE_PREFIX_66;
break;
continue;
case 0x67:
as_32 = !is_32;
break;
case 0x67: // address size override
if (!is_64) insn.as_32 = !is_32;
insn.as_64 = 0;
continue;
case 0xf0: // lock
break;
continue;
// no more prefixes
default:
printf("Internal disassembler error !\n");
return 0;
break;
}
n_prefixes++;
}
else break;
n_prefixes--;
break;
}
if (b1 == 0x0f)
if (insn.b1 == 0x0f)
{
b1 = 0x100 | fetch_byte();
entry = &BxDisasmOpcodes[b1];
insn.b1 = 0x100 | fetch_byte();
}
if (instruction_has_modrm[b1])
decode_modrm();
const BxDisasmOpcodeTable_t *opcode_table, *entry;
if (is_64) {
if (insn.os_64)
opcode_table = BxDisasmOpcodes64q;
else if (insn.os_32)
opcode_table = BxDisasmOpcodes64d;
else
opcode_table = BxDisasmOpcodes64w;
} else {
if (insn.os_32)
opcode_table = BxDisasmOpcodes32;
else
opcode_table = BxDisasmOpcodes16;
}
entry = opcode_table + insn.b1;
if (instruction_has_modrm[insn.b1])
{
decode_modrm(&insn);
}
int attr = entry->Attr;
while(attr)
{
switch(attr) {
case _GROUPN:
entry = &(entry->AnotherArray[nnn]);
entry = &(OPCODE_TABLE(entry)[insn.nnn]);
break;
case _GRPSSE:
@ -152,20 +213,24 @@ unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_
with the opcode prefixes (NONE, 0x66, 0xF2, 0xF3) */
int op = sse_prefix_index[sse_prefix];
if (op < 0) return 0;
entry = &(entry->AnotherArray[op]);
entry = &(OPCODE_TABLE(entry)[op]);
}
break;
case _SPLIT11B:
entry = &(entry->AnotherArray[mod==3]);
entry = &(OPCODE_TABLE(entry)[insn.mod != 3]); /* REG/MEM */
break;
case _GRPRM:
entry = &(OPCODE_TABLE(entry)[insn.rm]);
break;
case _GRPFP:
if(mod != 3)
if(insn.mod != 3)
{
entry = &(entry->AnotherArray[nnn]);
entry = &(OPCODE_TABLE(entry)[insn.nnn]);
} else {
int index = (b1-0xD8)*64 + (0x3f & modrm);
int index = (insn.b1-0xD8)*64 + (insn.modrm & 0x3f);
entry = &(BxDisasmOpcodeInfoFP[index]);
}
break;
@ -175,7 +240,7 @@ unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_
break;
default:
printf("Internal disassembler error !\n");
printf("Internal disassembler error - unknown attribute !\n");
return 0;
}
@ -183,26 +248,51 @@ unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_
attr = entry->Attr;
}
#define BRANCH_NOT_TAKEN 0x2E
#define BRANCH_TAKEN 0x3E
unsigned branch_hint = 0;
// print prefixes
for(unsigned i=0;i<n_prefixes;i++)
{
if (*(instr+i) == 0xF3 || *(instr+i) == 0xF2 || *(instr+i) == 0xF0)
dis_sprintf("%s ", BxDisasmOpcodes[*(instr+i)].Opcode);
Bit8u prefix_byte = *(instr+i);
if (entry->Op3Attr == BRANCH_HINT)
if (prefix_byte == 0xF3 || prefix_byte == 0xF2 || prefix_byte == 0xF0)
{
if (*(instr+i) == 0x2E)
dis_sprintf("not taken ");
if (*(instr+i) == 0x3E)
dis_sprintf("taken ");
const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
}
// branch hint for jcc instructions
if ((insn.b1 >= 0x070 && insn.b1 <= 0x07F) ||
(insn.b1 >= 0x180 && insn.b1 <= 0x18F))
{
if (prefix_byte == BRANCH_NOT_TAKEN || prefix_byte == BRANCH_TAKEN)
branch_hint = prefix_byte;
}
}
const BxDisasmOpcodeInfo_t *opcode = OPCODE(entry);
// patch jecx opcode
if (insn.b1 == 0xE3 && insn.as_32 && !insn.as_64)
opcode = &Ia_jecxz_Jb;
// print instruction disassembly
if (intel_mode)
print_disassembly_intel(entry);
print_disassembly_intel(&insn, opcode);
else
print_disassembly_att (entry);
print_disassembly_att (&insn, opcode);
if (branch_hint == BRANCH_NOT_TAKEN)
{
dis_sprintf(", not taken");
}
else if (branch_hint == BRANCH_TAKEN)
{
dis_sprintf(", taken");
}
return(instruction - instruction_begin);
}

View File

@ -1,139 +1,379 @@
#include <stdio.h>
#include "disasm.h"
/*
#if BX_DEBUGGER
#include "../bx_debug/debug.h"
#endif
*/
// 16/32-bit general purpose register
void disassembler::REG32 (unsigned attr)
void disassembler::Apw(const x86_insn *insn)
{
if (os_32)
dis_sprintf("%s", general_32bit_regname[attr]);
else
dis_sprintf("%s", general_16bit_regname[attr]);
Bit16u imm16 = fetch_word();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%04x", (unsigned) cs_selector, (unsigned) imm16);
}
// 8-bit general purpose register
void disassembler::REG8 (unsigned attr)
void disassembler::Apd(const x86_insn *insn)
{
dis_sprintf("%s", general_8bit_regname[attr]);
Bit32u imm32 = fetch_dword();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%08x", (unsigned) cs_selector, (unsigned) imm32);
}
// 8-bit general purpose registers
void disassembler::AL(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rAX_REG]); }
void disassembler::CL(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rCX_REG]); }
// 16-bit general purpose registers
void disassembler::AX(const x86_insn *insn) {
dis_sprintf("%s", general_16bit_regname[rAX_REG]);
}
void disassembler::DX(const x86_insn *insn) {
dis_sprintf("%s", general_16bit_regname[rDX_REG]);
}
// 32-bit general purpose registers
void disassembler::EAX(const x86_insn *insn)
{
dis_sprintf("%s", general_32bit_regname[rAX_REG]);
}
// 64-bit general purpose registers
void disassembler::RAX(const x86_insn *insn)
{
dis_sprintf("%s", general_64bit_regname[rAX_REG]);
}
// segment registers
void disassembler::CS(const x86_insn *insn) { dis_sprintf("%s", segment_name[CS_REG]); }
void disassembler::DS(const x86_insn *insn) { dis_sprintf("%s", segment_name[DS_REG]); }
void disassembler::ES(const x86_insn *insn) { dis_sprintf("%s", segment_name[ES_REG]); }
void disassembler::SS(const x86_insn *insn) { dis_sprintf("%s", segment_name[SS_REG]); }
void disassembler::FS(const x86_insn *insn) { dis_sprintf("%s", segment_name[FS_REG]); }
void disassembler::GS(const x86_insn *insn) { dis_sprintf("%s", segment_name[GS_REG]); }
void disassembler::Sw(const x86_insn *insn) { dis_sprintf("%s", segment_name[insn->nnn]); }
// test registers
void disassembler::Td(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("tr%d", insn->nnn);
else
dis_sprintf("%%tr%d", insn->nnn);
}
// control register
void disassembler::Cd(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("cr%d", insn->nnn);
else
dis_sprintf("%%cr%d", insn->nnn);
}
void disassembler::Cq(const x86_insn *insn) { Cd(insn); }
// debug register
void disassembler::Dd(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("db%d", insn->nnn);
else
dis_sprintf("%%db%d", insn->nnn);
}
void disassembler::Dq(const x86_insn *insn) { Dd(insn); }
// 8-bit general purpose register
void disassembler::R8(const x86_insn *insn)
{
unsigned reg = (insn->b1 & 7) | insn->rex_b;
if (reg < 4 || insn->extend8b)
dis_sprintf("%s", general_8bit_regname_rex[reg]);
else
dis_sprintf("%s", general_8bit_regname[reg]);
}
// 16-bit general purpose register
void disassembler::REG16 (unsigned attr)
void disassembler::RX(const x86_insn *insn)
{
dis_sprintf("%s", general_16bit_regname[attr]);
dis_sprintf("%s", general_16bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// segment register
void disassembler::OP_SEG (unsigned attr)
// 32-bit general purpose register
void disassembler::ERX(const x86_insn *insn)
{
dis_sprintf("%s", segment_name[attr]);
dis_sprintf("%s", general_32bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// memory operand
void disassembler::OP_MEM (unsigned attr)
// 64-bit general purpose register
void disassembler::RRX(const x86_insn *insn)
{
if(mod == 3)
dis_sprintf("(bad)");
dis_sprintf("%s", general_64bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// general purpose register or memory operand
void disassembler::Eb(const x86_insn *insn)
{
if (insn->mod == 3) {
if (insn->rm < 4 || insn->extend8b)
dis_sprintf("%s", general_8bit_regname_rex[insn->rm]);
else
(this->*resolve_modrm)(attr);
}
void disassembler::OP_Q (unsigned attr)
{
if (mod == 3)
{
if (intel_mode)
dis_sprintf ("mm%d", rm);
else
dis_sprintf("%%mm%d", rm);
dis_sprintf("%s", general_8bit_regname[insn->rm]);
}
else
(this->*resolve_modrm)(attr);
(this->*resolve_modrm)(insn, B_SIZE);
}
void disassembler::OP_W (unsigned attr)
void disassembler::Ew(const x86_insn *insn)
{
if (mod == 3)
if (insn->mod == 3)
dis_sprintf("%s", general_16bit_regname[insn->rm]);
else
(this->*resolve_modrm)(insn, W_SIZE);
}
void disassembler::Ed(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->rm]);
else
(this->*resolve_modrm)(insn, D_SIZE);
}
void disassembler::Eq(const x86_insn *insn)
{
if (insn->mod == 3)
dis_sprintf("%s", general_64bit_regname[insn->rm]);
else
(this->*resolve_modrm)(insn, Q_SIZE);
}
// general purpose register
void disassembler::Gb(const x86_insn *insn)
{
if (insn->nnn < 4 || insn->extend8b)
dis_sprintf("%s", general_8bit_regname_rex[insn->nnn]);
else
dis_sprintf("%s", general_8bit_regname[insn->nnn]);
}
void disassembler::Gw(const x86_insn *insn)
{
dis_sprintf("%s", general_16bit_regname[insn->nnn]);
}
void disassembler::Gd(const x86_insn *insn)
{
dis_sprintf("%s", general_32bit_regname[insn->nnn]);
}
void disassembler::Gq(const x86_insn *insn)
{
dis_sprintf("%s", general_64bit_regname[insn->nnn]);
}
// immediate
void disassembler::I1(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_putc ('1');
}
void disassembler::Ib(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%02x", (unsigned) fetch_byte());
}
void disassembler::Iw(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%04x", (unsigned) fetch_word());
}
void disassembler::Id(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%08x", (unsigned) fetch_dword());
}
void disassembler::Iq(const x86_insn *insn)
{
Bit64u value = fetch_qword();
if (! intel_mode) dis_putc('$');
dis_sprintf("0x%08x%08x",
(unsigned)(value>>32), (unsigned)(value & 0xffffffff));
}
// sign extended immediate
void disassembler::sIbw(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit16u imm16 = (Bit8s) fetch_byte();
dis_sprintf("0x%04x", (unsigned) imm16);
}
// sign extended immediate
void disassembler::sIbd(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit32u imm32 = (Bit8s) fetch_byte();
dis_sprintf ("0x%08x", (unsigned) imm32);
}
// sign extended immediate
void disassembler::sIbq(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit64u imm64 = (Bit8s) fetch_byte();
dis_sprintf ("0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
}
// sign extended immediate
void disassembler::sIdq(const x86_insn *insn)
{
if (! intel_mode) dis_putc('$');
Bit64u imm64 = (Bit32s) fetch_dword();
dis_sprintf ("0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
}
// floating point
void disassembler::ST0(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("st(0)");
else
dis_sprintf("%%st(0)");
}
void disassembler::STi(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("st(%d)", insn->rm);
else
dis_sprintf("%%st(%d)", insn->rm);
}
// 16-bit general purpose register
void disassembler::Rw(const x86_insn *insn)
{
dis_sprintf("%s", general_16bit_regname[insn->rm]);
}
// 32-bit general purpose register
void disassembler::Rd(const x86_insn *insn)
{
dis_sprintf("%s", general_32bit_regname[insn->rm]);
}
// 64-bit general purpose register
void disassembler::Rq(const x86_insn *insn)
{
dis_sprintf("%s", general_64bit_regname[insn->rm]);
}
// mmx register
void disassembler::Pq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->nnn);
else
dis_sprintf("%%mm%d", insn->nnn);
}
void disassembler::Qd(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", rm);
dis_sprintf ("mm%d", insn->rm);
else
dis_sprintf("%%xmm%d", rm);
dis_sprintf("%%mm%d", insn->rm);
}
else
(this->*resolve_modrm)(attr);
(this->*resolve_modrm)(insn, D_SIZE);
}
void disassembler::OP_V (unsigned attr)
void disassembler::Qq(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->rm);
else
dis_sprintf("%%mm%d", insn->rm);
}
else
(this->*resolve_modrm)(insn, Q_SIZE);
}
// xmm register
void disassembler::Vq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("xmm%d", nnn);
dis_sprintf ("xmm%d", insn->nnn);
else
dis_sprintf("%%xmm%d", nnn);
dis_sprintf("%%xmm%d", insn->nnn);
}
void disassembler::OP_P (unsigned attr)
void disassembler::Vdq(const x86_insn *insn) { Vq(insn); }
void disassembler::Vss(const x86_insn *insn) { Vq(insn); }
void disassembler::Vsd(const x86_insn *insn) { Vq(insn); }
void disassembler::Vps(const x86_insn *insn) { Vq(insn); }
void disassembler::Vpd(const x86_insn *insn) { Vq(insn); }
void disassembler::Wq(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("mm%d", nnn);
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%mm%d", nnn);
dis_sprintf("%%xmm%d", insn->rm);
}
else
(this->*resolve_modrm)(insn, Q_SIZE);
}
void disassembler::OP_X (unsigned attr)
void disassembler::Wdq(const x86_insn *insn)
{
const char *esi, *seg;
if (as_32)
esi = general_32bit_regname[eSI_REG];
else
esi = general_16bit_regname[eSI_REG];
if (seg_override)
seg = seg_override;
else
seg = segment_name[DS_REG];
print_datasize(attr);
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf("%s:[%s]", seg, esi);
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%s:(%s)", seg, esi);
dis_sprintf("%%xmm%d", insn->rm);
}
else
(this->*resolve_modrm)(insn, O_SIZE);
}
void disassembler::OP_Y (unsigned attr)
{
const char *edi;
void disassembler::Wss(const x86_insn *insn) { Wdq(insn); }
void disassembler::Wsd(const x86_insn *insn) { Wdq(insn); }
void disassembler::Wps(const x86_insn *insn) { Wdq(insn); }
void disassembler::Wpd(const x86_insn *insn) { Wdq(insn); }
if (as_32)
edi = general_32bit_regname[eDI_REG];
else
edi = general_16bit_regname[eDI_REG];
print_datasize(attr);
if (intel_mode)
dis_sprintf("%s:[%s]", segment_name[ES_REG], edi);
else
dis_sprintf("%s:(%s)", segment_name[ES_REG], edi);
}
void disassembler::OP_O (unsigned attr)
// direct memory access
void disassembler::OP_O(const x86_insn *insn, unsigned size)
{
const char *seg;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
print_datasize(attr);
print_datasize(size);
if (as_32) {
if (insn->as_32) {
Bit32u imm32 = fetch_dword();
dis_sprintf("%s:0x%x", seg, (unsigned) imm32);
}
@ -143,248 +383,147 @@ void disassembler::OP_O (unsigned attr)
}
}
void disassembler::Jb (unsigned attr)
void disassembler::Ob(const x86_insn *insn) { OP_O(insn, B_SIZE); }
void disassembler::Ow(const x86_insn *insn) { OP_O(insn, W_SIZE); }
void disassembler::Od(const x86_insn *insn) { OP_O(insn, D_SIZE); }
void disassembler::Oq(const x86_insn *insn) { OP_O(insn, Q_SIZE); }
// memory operand
void disassembler::OP_M(const x86_insn *insn, unsigned size)
{
Bit8s imm8; /* JMP rel8 is signed */
imm8 = (Bit8s) fetch_byte();
if (os_32) {
#if BX_DEBUGGER
char *Sym=bx_dbg_disasm_symbolic_address((Bit32u)(imm8+db_eip), db_base);
if(Sym) {
dis_sprintf("%s", Sym);
}
else // Symbol not found
#endif
dis_sprintf(".+0x%x", (unsigned) (imm8+db_eip));
}
if(insn->mod == 3)
dis_sprintf("(bad)");
else
{
#if BX_DEBUGGER
char *Sym=bx_dbg_disasm_symbolic_address((Bit32u)((imm8+db_eip) & 0xFFFF), db_base);
if(Sym) {
dis_sprintf("%s", Sym);
}
else // Symbol not found
#endif
dis_sprintf(".+0x%x", (unsigned) ((imm8+db_eip) & 0xFFFF));
}
(this->*resolve_modrm)(insn, size);
}
void disassembler::Jv (unsigned attr)
void disassembler::Ma(const x86_insn *insn) { OP_M(insn, X_SIZE); }
void disassembler::Mp(const x86_insn *insn) { OP_M(insn, X_SIZE); }
void disassembler::Ms(const x86_insn *insn) { OP_M(insn, X_SIZE); }
void disassembler::Mx(const x86_insn *insn) { OP_M(insn, X_SIZE); }
void disassembler::Mb(const x86_insn *insn) { OP_M(insn, B_SIZE); }
void disassembler::Mw(const x86_insn *insn) { OP_M(insn, W_SIZE); }
void disassembler::Md(const x86_insn *insn) { OP_M(insn, D_SIZE); }
void disassembler::Mq(const x86_insn *insn) { OP_M(insn, Q_SIZE); }
void disassembler::Mt(const x86_insn *insn) { OP_M(insn, T_SIZE); }
void disassembler::Mdq(const x86_insn *insn) { OP_M(insn, O_SIZE); }
void disassembler::Mps(const x86_insn *insn) { OP_M(insn, O_SIZE); }
void disassembler::Mpd(const x86_insn *insn) { OP_M(insn, O_SIZE); }
// string instructions
void disassembler::OP_X(const x86_insn *insn, unsigned size)
{
if (os_32) {
Bit32s imm32; /* JMP rel32 is signed */
imm32 = (Bit32s) fetch_dword();
#if BX_DEBUGGER
char *Sym=bx_dbg_disasm_symbolic_address((Bit32u)(imm32+db_eip), db_base);
if(Sym) {
dis_sprintf("%s", Sym);
}
else // Symbol not found
#endif
dis_sprintf(".+0x%x", (unsigned) (imm32+db_eip));
const char *rsi, *seg;
if (insn->as_64) {
rsi = general_64bit_regname[rSI_REG];
}
else {
if (insn->as_32)
rsi = general_32bit_regname[rSI_REG];
else
{
Bit16s imm16; /* JMP rel16 is signed */
imm16 = (Bit16s) fetch_word();
#if BX_DEBUGGER
char *Sym=bx_dbg_disasm_symbolic_address((Bit32u)((imm16+db_eip) & 0xFFFF), db_base);
if(Sym) {
dis_sprintf("%s", Sym);
rsi = general_16bit_regname[rSI_REG];
}
else // Symbol not found
#endif
dis_sprintf(".+0x%x", (unsigned) ((imm16+db_eip) & 0xFFFF));
}
}
void disassembler::Ap (unsigned attr)
{
if (os_32)
{
Bit32u imm32 = fetch_dword();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%08x", (unsigned) cs_selector, (unsigned) imm32);
}
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
{
Bit16u imm16 = fetch_word();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%04x", (unsigned) cs_selector, (unsigned) imm16);
}
}
seg = segment_name[DS_REG];
// general purpose register or memory operand
void disassembler::Eb (unsigned attr)
{
if (mod == 3)
dis_sprintf("%s", general_8bit_regname[rm]);
else
(this->*resolve_modrm)(B_SIZE);
}
print_datasize(size);
void disassembler::Ew (unsigned attr)
{
if (mod == 3)
dis_sprintf("%s", general_16bit_regname[rm]);
else
(this->*resolve_modrm)(W_SIZE);
}
void disassembler::Ev (unsigned attr)
{
if (os_32)
Ed(attr);
else
Ew(attr);
}
void disassembler::Ed (unsigned attr)
{
if (mod == 3)
dis_sprintf("%s", general_32bit_regname[rm]);
else
(this->*resolve_modrm)(D_SIZE);
}
// general purpose register
void disassembler::Gb (unsigned attr)
{
dis_sprintf("%s", general_8bit_regname[nnn]);
}
void disassembler::Gv (unsigned attr)
{
if (os_32)
dis_sprintf("%s", general_32bit_regname[nnn]);
else
dis_sprintf("%s", general_16bit_regname[nnn]);
}
void disassembler::Gd (unsigned attr)
{
dis_sprintf("%s", general_32bit_regname[nnn]);
}
// 32-bit general purpose register
void disassembler::Rd (unsigned attr)
{
dis_sprintf("%s", general_32bit_regname[rm]);
}
// 16-bit general purpose register
void disassembler::Rw (unsigned attr)
{
dis_sprintf("%s", general_16bit_regname[rm]);
}
// segment register
void disassembler::Sw (unsigned attr)
{
dis_sprintf("%s", segment_name[nnn]);
}
// immediate
void disassembler::I1 (unsigned)
{
if (! intel_mode) dis_putc('$');
dis_putc ('1');
}
void disassembler::Ib (unsigned attr)
{
if (intel_mode)
dis_sprintf ("0x%x", (unsigned) fetch_byte());
dis_sprintf("%s:[%s]", seg, rsi);
else
dis_sprintf("$0x%x", (unsigned) fetch_byte());
dis_sprintf("%s:(%s)", seg, rsi);
}
void disassembler::Iw (unsigned attr)
{
if (intel_mode)
dis_sprintf ("0x%x", (unsigned) fetch_word());
else
dis_sprintf("$0x%x", (unsigned) fetch_word());
}
void disassembler::Xb(const x86_insn *insn) { OP_X(insn, B_SIZE); }
void disassembler::Xw(const x86_insn *insn) { OP_X(insn, W_SIZE); }
void disassembler::Xd(const x86_insn *insn) { OP_X(insn, D_SIZE); }
void disassembler::Xq(const x86_insn *insn) { OP_X(insn, Q_SIZE); }
void disassembler::Id (unsigned attr)
void disassembler::OP_Y(const x86_insn *insn, unsigned size)
{
if (intel_mode)
dis_sprintf ("0x%x", (unsigned) fetch_dword());
else
dis_sprintf("$0x%x", (unsigned) fetch_dword());
}
const char *rdi;
void disassembler::Iv (unsigned attr)
{
if (os_32)
Id(attr);
else
Iw(attr);
}
// sign extended immediate
void disassembler::sIb(unsigned attr)
{
if (os_32)
{
Bit32u imm32 = (Bit8s) fetch_byte();
if (intel_mode)
dis_sprintf ("0x%x", (unsigned) imm32);
else
dis_sprintf("$0x%x", (unsigned) imm32);
if (insn->as_64) {
rdi = general_64bit_regname[rDI_REG];
}
else {
if (insn->as_32)
rdi = general_32bit_regname[rDI_REG];
else
{
Bit16u imm16 = (Bit8s) fetch_byte();
rdi = general_16bit_regname[rDI_REG];
}
print_datasize(size);
if (intel_mode)
dis_sprintf ("0x%x", (unsigned) imm16);
dis_sprintf("%s:[%s]", segment_name[ES_REG], rdi);
else
dis_sprintf("$0x%x", (unsigned) imm16);
dis_sprintf("%s:(%s)", segment_name[ES_REG], rdi);
}
void disassembler::Yb(const x86_insn *insn) { OP_Y(insn, B_SIZE); }
void disassembler::Yw(const x86_insn *insn) { OP_Y(insn, W_SIZE); }
void disassembler::Yd(const x86_insn *insn) { OP_Y(insn, D_SIZE); }
void disassembler::Yq(const x86_insn *insn) { OP_Y(insn, Q_SIZE); }
// jump offset
void disassembler::Jb(const x86_insn *insn)
{
Bit8s imm8 = (Bit8s) fetch_byte();
if (insn->is_64) {
Bit64u imm64 = (Bit64s) imm8;
dis_sprintf(".+0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
return;
}
if (insn->os_32) {
Bit32u imm32 = (Bit32s) imm8;
dis_sprintf(".+0x%08x", (unsigned) imm32);
}
else {
Bit16u imm16 = (Bit16s) imm8;
dis_sprintf(".+0x%04x", (unsigned) imm16);
}
}
// floating point
void disassembler::ST0 (unsigned attr)
void disassembler::Jw(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("st(0)");
else
dis_sprintf("%%st(0)");
Bit16s imm16 = (Bit16s) fetch_word();
if (insn->is_64) {
Bit64u imm64 = (Bit64s) imm16;
dis_sprintf(".+0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
return;
}
if (insn->os_32) {
Bit32u imm32 = (Bit32s) imm16;
dis_sprintf(".+0x%08x", (unsigned) imm32);
}
else {
dis_sprintf(".+0x%04x", (unsigned) imm16);
}
}
void disassembler::STj (unsigned attr)
void disassembler::Jd(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("st(%d)", rm);
else
dis_sprintf("%%st(%d)", rm);
}
Bit32s imm32 = (Bit32s) fetch_dword();
// control register
void disassembler::Cd (unsigned attr)
{
if (intel_mode)
dis_sprintf ("cr%d", nnn);
else
dis_sprintf("%%cr%d", nnn);
}
if (insn->is_64) {
Bit64u imm64 = (Bit64s) imm32;
dis_sprintf(".+0x%08x%08x",
(unsigned)(imm64>>32), (unsigned)(imm64 & 0xffffffff));
return;
}
// debug register
void disassembler::Dd (unsigned attr)
{
if (intel_mode)
dis_sprintf ("db%d", nnn);
else
dis_sprintf("%%db%d", nnn);
}
// test registers
void disassembler::Td (unsigned attr)
{
if (intel_mode)
dis_sprintf ("tr%d", nnn);
else
dis_sprintf("%%tr%d", nnn);
dis_sprintf(".+0x%08x", (unsigned) imm32);
}

File diff suppressed because it is too large Load Diff

4804
bochs/disasm/dis_tables.inc Executable file

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,9 @@
}
#define BX_DECODE_SIB(sib_byte, scale, index, base) { \
scale = sib >> 6; \
index = (sib >> 3) & 0x07; \
base = sib & 0x07; \
scale = sib_byte >> 6; \
index = (sib_byte >> 3) & 0x07; \
base = sib_byte & 0x07; \
}
// will be used in future
@ -41,40 +41,7 @@
#define IF_SSE2 0x00000000 /* SSE2 instruction */
#define IF_PNI 0x00000000 /* Prescott new instruction */
enum {
AL_REG,
CL_REG,
DL_REG,
BL_REG,
AH_REG,
CH_REG,
DH_REG,
BH_REG
};
enum {
AX_REG,
CX_REG,
DX_REG,
BX_REG,
SP_REG,
BP_REG,
SI_REG,
DI_REG
};
enum {
eAX_REG,
eCX_REG,
eDX_REG,
eBX_REG,
eSP_REG,
eBP_REG,
eSI_REG,
eDI_REG
};
#if BX_DISASM_SUPPORT_X86_64
/* general purpose bit register */
enum {
rAX_REG,
rCX_REG,
@ -85,33 +52,38 @@ enum {
rSI_REG,
rDI_REG
};
#endif
/* segment register */
enum {
ES_REG,
CS_REG,
SS_REG,
DS_REG,
FS_REG,
GS_REG
GS_REG,
INVALID_SEG1,
INVALID_SEG2
};
class disassembler;
class x86_insn;
typedef void (disassembler::*BxDisasmPtr_t) (unsigned attr);
typedef void (disassembler::*BxDisasmResolveModrmPtr_t) (unsigned attr);
typedef void (disassembler::*BxDisasmPtr_t)(const x86_insn *insn);
typedef void (disassembler::*BxDisasmResolveModrmPtr_t)(const x86_insn *insn, unsigned attr);
struct BxDisasmOpcodeInfo_t
{
const char *Opcode;
unsigned Attr;
const char *IntelOpcode;
const char *AttOpcode;
BxDisasmPtr_t Operand1;
unsigned Op1Attr;
BxDisasmPtr_t Operand2;
unsigned Op2Attr;
BxDisasmPtr_t Operand3;
unsigned Op3Attr;
struct BxDisasmOpcodeInfo_t *AnotherArray;
};
struct BxDisasmOpcodeTable_t
{
Bit32u Attr;
const void *OpcodeInfo;
};
// datasize attributes
@ -119,23 +91,73 @@ struct BxDisasmOpcodeInfo_t
#define B_SIZE 0x0100
#define W_SIZE 0x0200
#define D_SIZE 0x0300
#define V_SIZE 0x0400
#define Q_SIZE 0x0500
#define Z_SIZE 0x0600
#define Q_SIZE 0x0400
#define Z_SIZE 0x0500
#define V_SIZE 0x0600
#define O_SIZE 0x0700
#define T_SIZE 0x0800
#define P_SIZE 0x0900
#define S_SIZE 0x0A00
// branch hint attribute
#define BRANCH_HINT 0x1000
struct x86_insn
{
public:
x86_insn(bx_bool is32, bx_bool is64);
public:
bx_bool is_32, is_64;
bx_bool as_32, as_64;
bx_bool os_32, os_64;
Bit8u extend8b;
Bit8u rex_r, rex_x, rex_b;
Bit8u seg_override;
unsigned b1;
Bit8u modrm, mod, nnn, rm;
Bit8u sib, scale, index, base;
union {
Bit16u displ16;
Bit32u displ32;
} displacement;
};
BX_CPP_INLINE x86_insn::x86_insn(bx_bool is32, bx_bool is64)
{
is_32 = is32;
is_64 = is64;
if (is_64) {
os_64 = 0;
as_64 = 1;
os_32 = 1;
as_32 = 1;
}
else {
os_64 = 0;
as_64 = 0;
os_32 = is_32;
as_32 = is_32;
}
extend8b = 0;
rex_r = rex_b = rex_x = 0;
seg_override = 0;
b1 = 0;
modrm = mod = nnn = rm = 0;
sib = scale = index = base = 0;
displacement.displ32 = 0;
}
class disassembler {
public:
disassembler() { set_syntax_intel(); }
unsigned disasm16(bx_address base, bx_address ip, Bit8u *instr, char *disbuf);
unsigned disasm32(bx_address base, bx_address ip, Bit8u *instr, char *disbuf);
unsigned disasm64(bx_address base, bx_address ip, Bit8u *instr, char *disbuf);
unsigned disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, Bit8u *instr, char *disbuf);
@ -148,10 +170,8 @@ private:
const char **general_16bit_regname;
const char **general_8bit_regname;
const char **general_32bit_regname;
#if BX_DISASM_SUPPORT_X86_64
const char **general_8bit_regname_rex;
const char **general_64bit_regname;
#endif
const char **segment_name;
const char **index16;
@ -164,29 +184,10 @@ private:
private:
bx_bool os_32;
bx_bool as_32;
#if BX_DISASM_SUPPORT_X86_64
bx_bool os_64;
bx_bool as_64;
#endif
Bit8u modrm, mod, nnn, rm;
Bit8u sib, scale, sib_index, sib_base;
union {
Bit16u displ16;
Bit32u displ32;
} displacement;
bx_address db_eip, db_base;
unsigned n_prefixes;
Bit8u *instruction; // for fetching of next byte of instruction
const char *seg_override;
char *disbufptr;
BxDisasmResolveModrmPtr_t resolve_modrm;
@ -218,27 +219,31 @@ private:
return(ret32);
};
#if BX_DISASM_SUPPORT_X86_64
BX_CPP_INLINE Bit64u fetch_qword() {
Bit64u d0 = fetch_dword();
Bit64u d1 = fetch_dword();
Bit64u ret64 = (d1<<32) | d0;
return(ret64);
};
#endif
void dis_putc(char symbol);
void dis_sprintf(char *fmt, ...);
void decode_modrm();
void decode_modrm(x86_insn *insn);
void resolve16_mod0 (unsigned mode);
void resolve16_mod1or2 (unsigned mode);
void resolve16_mod0 (const x86_insn *insn, unsigned mode);
void resolve16_mod1or2(const x86_insn *insn, unsigned mode);
void resolve32_mod0 (unsigned mode);
void resolve32_mod1or2 (unsigned mode);
void resolve32_mod0 (const x86_insn *insn, unsigned mode);
void resolve32_mod1or2(const x86_insn *insn, unsigned mode);
void resolve32_mod0_rm4 (unsigned mode);
void resolve32_mod1or2_rm4 (unsigned mode);
void resolve32_mod0_rm4 (const x86_insn *insn, unsigned mode);
void resolve32_mod1or2_rm4(const x86_insn *insn, unsigned mode);
void resolve64_mod0 (const x86_insn *insn, unsigned mode);
void resolve64_mod1or2(const x86_insn *insn, unsigned mode);
void resolve64_mod0_rm4 (const x86_insn *insn, unsigned mode);
void resolve64_mod1or2_rm4(const x86_insn *insn, unsigned mode);
void initialize_modrm_segregs();
@ -246,11 +251,11 @@ private:
void print_memory_access16(int datasize,
const char *seg, const char *index, Bit16u disp);
void print_memory_access32(int datasize,
void print_memory_access (int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32u disp);
void print_disassembly_intel(const BxDisasmOpcodeInfo_t *entry);
void print_disassembly_att (const BxDisasmOpcodeInfo_t *entry);
void print_disassembly_intel(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry);
void print_disassembly_att (const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry);
public:
@ -317,78 +322,158 @@ public:
* ss - Scalar element of a 128-bit packed single-precision floating data.
* sd - Scalar element of a 128-bit packed double-precision floating data.
* v - Word, doubleword or quadword, depending on operand-size attribute.
* w - Word, regardless of operand-size attribute.
* z - A word if the effective operand size is 16 bits, or a doubleword
* if the effective operand size is 32 or 64 bits.
* w - Word, regardless of operand-size attr.
*/
// fpu
void ST0 (unsigned attribute);
void STj (unsigned attribute);
// far call/jmp
void Apw(const x86_insn *insn);
void Apd(const x86_insn *insn);
// general/segment register
void Rw (unsigned attribute);
void Rd (unsigned attribute);
void Sw (unsigned attribute);
// 8-bit general purpose registers
void AL(const x86_insn *insn);
void CL(const x86_insn *insn);
// control/debug register
void Cd (unsigned attribute);
void Dd (unsigned attribute);
void Td (unsigned attribute);
// 16-bit general purpose registers
void AX(const x86_insn *insn);
void DX(const x86_insn *insn);
// segment register
void OP_SEG (unsigned attribute);
// 32-bit general purpose registers
void EAX(const x86_insn *insn);
// memory only
void OP_MEM (unsigned attribute);
// 64-bit general purpose registers
void RAX(const x86_insn *insn);
// segment registers
void CS(const x86_insn *insn);
void DS(const x86_insn *insn);
void ES(const x86_insn *insn);
void SS(const x86_insn *insn);
void FS(const x86_insn *insn);
void GS(const x86_insn *insn);
// segment registers
void Sw(const x86_insn *insn);
// test registers
void Td(const x86_insn *insn);
// control register
void Cd(const x86_insn *insn);
void Cq(const x86_insn *insn);
// debug register
void Dd(const x86_insn *insn);
void Dq(const x86_insn *insn);
// 8-bit general purpose register
void R8(const x86_insn *insn);
// 16-bit general purpose register
void RX(const x86_insn *insn);
// 32-bit general purpose register
void ERX(const x86_insn *insn);
// 64-bit general purpose register
void RRX(const x86_insn *insn);
// general purpose register or memory operand
void Eb(const x86_insn *insn);
void Ew(const x86_insn *insn);
void Ed(const x86_insn *insn);
void Eq(const x86_insn *insn);
// general purpose register
void REG16 (unsigned attribute);
void REG8 (unsigned attribute);
void REG32 (unsigned attribute);
// string instructions
void OP_X (unsigned attribute);
void OP_Y (unsigned attribute);
// mmx/xmm
void OP_P (unsigned attribute);
void OP_Q (unsigned attribute);
void OP_W (unsigned attribute);
void OP_V (unsigned attribute);
// mov
void OP_O (unsigned attribute);
void Gb(const x86_insn *insn);
void Gw(const x86_insn *insn);
void Gd(const x86_insn *insn);
void Gq(const x86_insn *insn);
// immediate
void sIb (unsigned attribute);
void I1 (unsigned attribute);
void Ib (unsigned attribute);
void Iw (unsigned attribute);
void Id (unsigned attribute);
void Iv (unsigned attribute);
#if BX_DISASM_SUPPORT_X86_64
void Iz (unsigned attribute);
void Iq (unsigned attribute);
#endif
void I1(const x86_insn *insn);
void Ib(const x86_insn *insn);
void Iw(const x86_insn *insn);
void Id(const x86_insn *insn);
void Iq(const x86_insn *insn);
// general purpose register or memory
void Eb (unsigned attribute);
void Ew (unsigned attribute);
void Ed (unsigned attribute);
void Ev (unsigned attribute);
// sign extended immediate
void sIbw(const x86_insn *insn);
void sIbd(const x86_insn *insn);
void sIbq(const x86_insn *insn);
void sIdq(const x86_insn *insn);
// floating point
void ST0(const x86_insn *insn);
void STi(const x86_insn *insn);
// general purpose register
void Gb (unsigned attribute);
void Gv (unsigned attribute);
void Gd (unsigned attribute);
void Rw(const x86_insn *insn);
void Rd(const x86_insn *insn);
void Rq(const x86_insn *insn);
// call/jump
void Jb (unsigned attribute);
void Jv (unsigned attribute);
// mmx register
void Pq(const x86_insn *insn);
// call/jmp far
void Ap (unsigned attribute);
// mmx register or memory operand
void Qd(const x86_insn *insn);
void Qq(const x86_insn *insn);
void Vq(const x86_insn *insn);
// xmm register
void Vdq(const x86_insn *insn);
void Vss(const x86_insn *insn);
void Vsd(const x86_insn *insn);
void Vps(const x86_insn *insn);
void Vpd(const x86_insn *insn);
// xmm register or memory operand
void Wq(const x86_insn *insn);
void Wdq(const x86_insn *insn);
void Wss(const x86_insn *insn);
void Wsd(const x86_insn *insn);
void Wps(const x86_insn *insn);
void Wpd(const x86_insn *insn);
// direct memory access
void OP_O(const x86_insn *insn, unsigned size);
void Ob(const x86_insn *insn);
void Ow(const x86_insn *insn);
void Od(const x86_insn *insn);
void Oq(const x86_insn *insn);
// memory operand
void OP_M(const x86_insn *insn, unsigned size);
void Ma(const x86_insn *insn);
void Mp(const x86_insn *insn);
void Ms(const x86_insn *insn);
void Mx(const x86_insn *insn);
void Mb(const x86_insn *insn);
void Mw(const x86_insn *insn);
void Md(const x86_insn *insn);
void Mq(const x86_insn *insn);
void Mt(const x86_insn *insn);
void Mdq(const x86_insn *insn);
void Mps(const x86_insn *insn);
void Mpd(const x86_insn *insn);
// string instructions
void OP_X(const x86_insn *insn, unsigned size);
void Xb(const x86_insn *insn);
void Xw(const x86_insn *insn);
void Xd(const x86_insn *insn);
void Xq(const x86_insn *insn);
// string instructions
void OP_Y(const x86_insn *insn, unsigned size);
void Yb(const x86_insn *insn);
void Yw(const x86_insn *insn);
void Yd(const x86_insn *insn);
void Yq(const x86_insn *insn);
// jump offset
void Jb(const x86_insn *insn);
void Jw(const x86_insn *insn);
void Jd(const x86_insn *insn);
};
#endif

1189
bochs/disasm/opcodes.inc Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,188 +1,305 @@
#include <stdio.h>
#include "disasm.h"
void disassembler::decode_modrm()
void disassembler::decode_modrm(x86_insn *insn)
{
modrm = fetch_byte();
BX_DECODE_MODRM(modrm, mod, nnn, rm);
insn->modrm = fetch_byte();
BX_DECODE_MODRM(insn->modrm, insn->mod, insn->nnn, insn->rm);
insn->nnn |= insn->rex_r;
if (as_32)
{
/* use 32bit addressing modes. orthogonal base & index registers,
scaling available, etc. */
if (mod == 3) {
if (insn->mod == 3) {
/* mod, reg, reg */
insn->rm |= insn->rex_b;
return;
}
else { /* mod != 3 */
if (rm != 4) { /* rm != 100b, no s-i-b byte */
if (insn->as_64)
{
if (insn->rm != 4) { /* rm != 100b, no s-i-b byte */
insn->rm |= insn->rex_b;
// one byte modrm
switch (mod) {
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0;
if (rm == 5) /* no reg, 32-bit displacement */
displacement.displ32 = fetch_dword();
resolve_modrm = &disassembler::resolve64_mod0;
if (insn->rm == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve32_mod1or2;
displacement.displ32 = (Bit8s) fetch_byte();
resolve_modrm = &disassembler::resolve64_mod1or2;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
/* reg, 32-bit displacement */
resolve_modrm = &disassembler::resolve32_mod1or2;
displacement.displ32 = fetch_dword();
resolve_modrm = &disassembler::resolve64_mod1or2;
insn->displacement.displ32 = fetch_dword();
break;
} /* switch (mod) */
} /* if (rm != 4) */
else { /* rm == 4, s-i-b byte follows */
sib = fetch_byte();
BX_DECODE_SIB(sib, scale, sib_index, sib_base);
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
switch (mod) {
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0_rm4;
if (sib_base == 5)
displacement.displ32 = fetch_dword();
resolve_modrm = &disassembler::resolve64_mod0_rm4;
if (insn->base == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
displacement.displ32 = (Bit8s) fetch_byte();
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
displacement.displ32 = fetch_dword();
resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
insn->displacement.displ32 = fetch_dword();
break;
}
} /* s-i-b byte follows */
}
else
{
if (insn->as_32)
{
if (insn->rm != 4) { /* rm != 100b, no s-i-b byte */
insn->rm |= insn->rex_b;
// one byte modrm
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0;
if (insn->rm == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve32_mod1or2;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
/* reg, 32-bit displacement */
resolve_modrm = &disassembler::resolve32_mod1or2;
insn->displacement.displ32 = fetch_dword();
break;
} /* switch (mod) */
} /* if (rm != 4) */
else { /* rm == 4, s-i-b byte follows */
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
insn->base |= insn->rex_b;
insn->index |= insn->rex_x;
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0_rm4;
if (insn->base == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
insn->displacement.displ32 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
insn->displacement.displ32 = fetch_dword();
break;
}
} /* s-i-b byte follows */
} /* if (mod != 3) */
}
else {
/* 16 bit addressing modes. */
switch (mod) {
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve16_mod0;
if(rm == 6)
displacement.displ16 = fetch_word();
if(insn->rm == 6)
insn->displacement.displ16 = fetch_word();
break;
case 1:
/* reg, 8-bit displacement, sign extend */
resolve_modrm = &disassembler::resolve16_mod1or2;
displacement.displ16 = (Bit8s) fetch_byte();
insn->displacement.displ16 = (Bit8s) fetch_byte();
break;
case 2:
resolve_modrm = &disassembler::resolve16_mod1or2;
displacement.displ16 = fetch_word();
insn->displacement.displ16 = fetch_word();
break;
case 3:
/* mod, reg, reg */
return;
} /* switch (mod) ... */
}
}
}
void disassembler::resolve16_mod0(unsigned mode)
void disassembler::resolve16_mod0(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_rm16[rm];
seg = sreg_mod00_rm16[insn->rm];
if(rm == 6)
print_memory_access16(mode, seg, NULL, displacement.displ16);
if(insn->rm == 6)
print_memory_access16(mode, seg, NULL, insn->displacement.displ16);
else
print_memory_access16(mode, seg, index16[rm], 0);
print_memory_access16(mode, seg, index16[insn->rm], 0);
}
void disassembler::resolve16_mod1or2(unsigned mode)
void disassembler::resolve16_mod1or2(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm16[rm];
seg = sreg_mod01or10_rm16[insn->rm];
print_memory_access16(mode, seg, index16[rm], displacement.displ16);
print_memory_access16(mode, seg, index16[insn->rm], insn->displacement.displ16);
}
void disassembler::resolve32_mod0(unsigned mode)
void disassembler::resolve32_mod0(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if (rm == 5) /* no reg, 32-bit displacement */
print_memory_access32(mode, seg, NULL, NULL, 0, displacement.displ32);
if (insn->rm == 5) /* no reg, 32-bit displacement */
print_memory_access(mode, seg, NULL, NULL, 0, insn->displacement.displ32);
else
print_memory_access32(mode, seg, general_32bit_regname[rm], NULL, 0, 0);
print_memory_access(mode, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
}
void disassembler::resolve32_mod1or2(unsigned mode)
void disassembler::resolve32_mod1or2(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm32[rm];
seg = sreg_mod01or10_rm32[insn->rm];
print_memory_access32(mode, seg,
general_32bit_regname[rm], NULL, 0, displacement.displ32);
print_memory_access(mode, seg,
general_32bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
}
void disassembler::resolve32_mod0_rm4(unsigned mode)
void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *base = NULL, *index = NULL;
Bit32u disp32 = 0;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_base32[sib_base];
seg = sreg_mod00_base32[insn->base];
if (sib_base != 5)
base = general_32bit_regname[sib_base];
if (insn->base != 5)
base = general_32bit_regname[insn->base];
else
disp32 = displacement.displ32;
disp32 = insn->displacement.displ32;
if (sib_index != 4)
if (insn->index != 4)
{
index = general_32bit_regname[sib_index];
index = general_32bit_regname[insn->index];
}
print_memory_access32(mode, seg, base, index, scale, disp32);
print_memory_access(mode, seg, base, index, insn->scale, disp32);
}
void disassembler::resolve32_mod1or2_rm4(unsigned mode)
void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *index = NULL;
if (seg_override)
seg = seg_override;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[sib_base];
seg = sreg_mod01or10_base32[insn->base];
if (sib_index != 4)
if (insn->index != 4)
{
index = general_32bit_regname[sib_index];
index = general_32bit_regname[insn->index];
}
print_memory_access32(mode, seg,
general_32bit_regname[sib_base], index, scale, displacement.displ32);
print_memory_access(mode, seg,
general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
}
void disassembler::print_datasize(unsigned mode)
void disassembler::resolve64_mod0(const x86_insn *insn, unsigned mode)
{
const char *seg, *rip_regname;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
if (intel_mode) rip_regname = "rip";
else rip_regname = "%rip";
if (insn->rm == 5) /* no reg, 32-bit displacement */
print_memory_access(mode, seg, rip_regname, NULL, 0, insn->displacement.displ32);
else
print_memory_access(mode, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
}
void disassembler::resolve64_mod1or2(const x86_insn *insn, unsigned mode)
{
const char *seg;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_rm32[insn->rm];
print_memory_access(mode, seg,
general_64bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
}
void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *base = NULL, *index = NULL;
Bit32u disp32 = 0;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod00_base32[insn->base];
if (insn->base != 5)
base = general_64bit_regname[insn->base];
else
disp32 = insn->displacement.displ32;
if (insn->index != 4)
{
index = general_64bit_regname[insn->index];
}
print_memory_access(mode, seg, base, index, insn->scale, disp32);
}
void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned mode)
{
const char *seg, *index = NULL;
if (insn->seg_override)
seg = segment_name[insn->seg_override];
else
seg = sreg_mod01or10_base32[insn->base];
if (insn->index != 4)
{
index = general_64bit_regname[insn->index];
}
print_memory_access(mode, seg,
general_64bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
}
void disassembler::print_datasize(unsigned size)
{
if (!intel_mode) return;
switch(mode)
switch(size)
{
case B_SIZE:
dis_sprintf("byte ptr ");
@ -193,12 +310,6 @@ void disassembler::print_datasize(unsigned mode)
case D_SIZE:
dis_sprintf("dword ptr ");
break;
case V_SIZE:
if (os_32)
dis_sprintf("dword ptr ");
else
dis_sprintf("word ptr ");
break;
case Q_SIZE:
dis_sprintf("qword ptr ");
break;
@ -210,8 +321,6 @@ void disassembler::print_datasize(unsigned mode)
break;
case P_SIZE:
break;
case S_SIZE:
break;
case X_SIZE:
break;
};
@ -252,7 +361,7 @@ void disassembler::print_memory_access16(int datasize,
}
}
void disassembler::print_memory_access32(int datasize,
void disassembler::print_memory_access(int datasize,
const char *seg, const char *base, const char *index, int scale, Bit32u disp)
{
print_datasize(datasize);

View File

@ -5,7 +5,9 @@
// Intel STYLE
//////////////////
#if BX_DISASM_SUPPORT_X86_64
#define BX_DISASM_SUPPORT_X86_64
#ifdef BX_DISASM_SUPPORT_X86_64
static const char *intel_general_16bit_regname[16] = {
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
@ -63,7 +65,7 @@ static const char *intel_index16[8] = {
// AT&T STYLE
//////////////////
#if BX_DISASM_SUPPORT_X86_64
#ifdef BX_DISASM_SUPPORT_X86_64
static const char *att_general_16bit_regname[16] = {
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
@ -177,10 +179,8 @@ void disassembler::set_syntax_intel()
general_16bit_regname = intel_general_16bit_regname;
general_8bit_regname = intel_general_8bit_regname;
general_32bit_regname = intel_general_32bit_regname;
#if BX_DISASM_SUPPORT_X86_64
general_8bit_regname_rex = intel_general_8bit_regname_rex;
general_64bit_regname = intel_general_64bit_regname;
#endif
segment_name = intel_segment_name;
index16 = intel_index16;
@ -188,56 +188,21 @@ void disassembler::set_syntax_intel()
initialize_modrm_segregs();
}
void disassembler::print_disassembly_intel(const BxDisasmOpcodeInfo_t *entry)
void disassembler::print_disassembly_intel(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
{
// print opcode
dis_sprintf("%s", entry->Opcode);
// patch opcode
disbufptr --;
switch(*disbufptr) {
case 'B':
case 'W':
case 'V':
case 'L':
case 'Q':
case 'T':
break;
case 'X': // movsx or movzx
dis_putc('x');
break;
case 'S': // string
if (os_32)
dis_putc('d');
else
dis_putc('w');
break;
case 'D':
if (os_32)
dis_putc('d');
break;
default:
disbufptr ++;
break;
}
dis_putc(' ');
dis_sprintf("%s ", entry->IntelOpcode);
if (entry->Operand1) {
(this->*entry->Operand1)(entry->Op1Attr);
(this->*entry->Operand1)(insn);
}
if (entry->Operand2) {
dis_sprintf(", ");
(this->*entry->Operand2)(entry->Op2Attr);
(this->*entry->Operand2)(insn);
}
if (entry->Operand3) {
dis_sprintf(", ");
(this->*entry->Operand3)(entry->Op3Attr);
(this->*entry->Operand3)(insn);
}
}
@ -252,10 +217,8 @@ void disassembler::set_syntax_att()
general_16bit_regname = att_general_16bit_regname;
general_8bit_regname = att_general_8bit_regname;
general_32bit_regname = att_general_32bit_regname;
#if BX_DISASM_SUPPORT_X86_64
general_8bit_regname_rex = att_general_8bit_regname_rex;
general_64bit_regname = att_general_64bit_regname;
#endif
segment_name = att_segment_name;
index16 = att_index16;
@ -263,91 +226,20 @@ void disassembler::set_syntax_att()
initialize_modrm_segregs();
}
void disassembler::print_disassembly_att(const BxDisasmOpcodeInfo_t *entry)
void disassembler::print_disassembly_att(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
{
// print opcode
dis_sprintf("%s", entry->Opcode);
// patch opcode
disbufptr --;
switch(*disbufptr) {
case 'B':
dis_putc('b');
break;
case 'W':
dis_putc('w');
break;
case 'S':
case 'V':
if (os_32)
dis_putc('l');
else
dis_putc('w');
break;
case 'L':
dis_putc('l');
break;
case 'Q':
dis_putc('q');
break;
case 'T':
dis_putc('t');
break;
case 'X':
if (entry->Op2Attr == B_SIZE)
dis_putc('b');
else if (entry->Op2Attr == W_SIZE)
dis_putc('w');
else if (entry->Op2Attr == D_SIZE)
dis_putc('l');
else
printf("Internal disassembler error !\n");
if (entry->Op1Attr == W_SIZE)
dis_putc('w');
else if (entry->Op1Attr == D_SIZE)
dis_putc('l');
else if (entry->Op1Attr == Q_SIZE)
dis_putc('q');
else if (entry->Op1Attr == V_SIZE)
{
if (os_32)
dis_putc('l');
else
dis_putc('w');
}
else
printf("Internal disassembler error !\n");
break;
case 'D':
if (os_32)
dis_putc('l');
break;
default:
disbufptr ++;
break;
}
dis_putc(' ');
dis_sprintf("%s ", entry->AttOpcode);
if (entry->Operand3) {
(this->*entry->Operand3)(entry->Op3Attr);
(this->*entry->Operand3)(insn);
dis_sprintf(", ");
}
if (entry->Operand2) {
(this->*entry->Operand2)(entry->Op2Attr);
(this->*entry->Operand2)(insn);
dis_sprintf(", ");
}
if (entry->Operand1) {
(this->*entry->Operand1)(entry->Op1Attr);
(this->*entry->Operand1)(insn);
}
}