Merge new disasm module with x96-64 support
This commit is contained in:
parent
520da21dcf
commit
276c006129
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
4804
bochs/disasm/dis_tables.inc
Executable file
File diff suppressed because it is too large
Load Diff
@ -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
1189
bochs/disasm/opcodes.inc
Executable file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user