Bochs/bochs/disasm/dis_groups.cc

662 lines
16 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////
// $Id: dis_groups.cc,v 1.41 2009-01-19 19:01:03 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <assert.h>
2004-01-04 21:53:02 +03:00
#include "disasm.h"
/*
#if BX_DEBUGGER
2004-01-04 21:53:02 +03:00
#include "../bx_debug/debug.h"
#endif
*/
void disassembler::Apw(const x86_insn *insn)
{
Bit16u imm16 = fetch_word();
Bit16u cs_selector = fetch_word();
dis_sprintf("%04x:%04x", (unsigned) cs_selector, (unsigned) imm16);
}
void disassembler::Apd(const x86_insn *insn)
{
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_Reg(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rAX_REG]); }
void disassembler::CL_Reg(const x86_insn *insn) { dis_sprintf("%s", general_8bit_regname[rCX_REG]); }
// 16-bit general purpose registers
void disassembler::AX_Reg(const x86_insn *insn) {
dis_sprintf("%s", general_16bit_regname[rAX_REG]);
}
void disassembler::DX_Reg(const x86_insn *insn) {
dis_sprintf("%s", general_16bit_regname[rDX_REG]);
2003-08-04 20:03:09 +04:00
}
// 32-bit general purpose registers
void disassembler::EAX_Reg(const x86_insn *insn)
2003-08-04 20:03:09 +04:00
{
dis_sprintf("%s", general_32bit_regname[rAX_REG]);
2003-08-04 20:03:09 +04:00
}
// 64-bit general purpose registers
void disassembler::RAX_Reg(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::Reg8(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::RX(const x86_insn *insn)
{
dis_sprintf("%s", general_16bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// 32-bit general purpose register
void disassembler::ERX(const x86_insn *insn)
{
dis_sprintf("%s", general_32bit_regname[(insn->b1 & 7) | insn->rex_b]);
}
// 64-bit general purpose register
void disassembler::RRX(const x86_insn *insn)
{
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
dis_sprintf("%s", general_8bit_regname[insn->rm]);
}
else
(this->*resolve_modrm)(insn, B_SIZE);
}
void disassembler::Ew(const x86_insn *insn)
{
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);
}
void disassembler::Hbd(const x86_insn *insn)
2007-04-19 20:12:21 +04:00
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->nnn]);
else
(this->*resolve_modrm)(insn, B_SIZE);
}
void disassembler::Hwd(const x86_insn *insn)
2007-04-19 20:12:21 +04:00
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->nnn]);
else
(this->*resolve_modrm)(insn, W_SIZE);
}
void disassembler::Hd(const x86_insn *insn)
2007-04-19 20:12:21 +04:00
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->nnn]);
else
(this->*resolve_modrm)(insn, D_SIZE);
}
void disassembler::Hq(const x86_insn *insn)
2007-04-19 20:12:21 +04:00
{
if (insn->mod == 3)
dis_sprintf("%s", general_32bit_regname[insn->nnn]);
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::IbIb(const x86_insn *insn)
{
Bit8u ib1 = fetch_byte();
Bit8u ib2 = fetch_byte();
if (intel_mode) {
dis_sprintf("0x%02x, 0x%02x", ib1, ib2);
}
else {
dis_sprintf("$0x%02x, $0x%02x", ib2, ib1);
}
}
void disassembler::IwIb(const x86_insn *insn)
{
Bit16u iw = fetch_word();
Bit8u ib = fetch_byte();
if (intel_mode) {
dis_sprintf("0x%04x, 0x%02x", iw, ib);
}
else {
dis_sprintf("$0x%02x, $0x%04x", ib, iw);
}
}
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", GET32H(value), GET32L(value));
}
// 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)
{
2004-12-15 20:15:43 +03:00
if (! intel_mode) dis_putc('$');
Bit64u imm64 = (Bit8s) fetch_byte();
dis_sprintf ("0x%08x%08x", GET32H(imm64), GET32L(imm64));
}
// 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", GET32H(imm64), GET32L(imm64));
}
// 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);
}
2006-02-17 16:33:05 +03:00
void disassembler::Nq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("mm%d", insn->rm);
else
dis_sprintf("%%mm%d", insn->rm);
}
void disassembler::Qd(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, D_SIZE);
}
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
2006-02-17 16:33:05 +03:00
void disassembler::Udq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
void disassembler::Vq(const x86_insn *insn)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->nnn);
else
dis_sprintf("%%xmm%d", insn->nnn);
}
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); }
2007-04-19 20:12:21 +04:00
void disassembler::Ww(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
else
2007-04-19 20:12:21 +04:00
(this->*resolve_modrm)(insn, W_SIZE);
}
- apply patch.ifdef-disabled-options. Comments from that patch are below: For a whole lot of configure options, I put #if...#endif around code that is specific to the option, even in files which are normally only compiled when the option is on. This allows me to create a MS Visual C++ 6.0 workspace that supports many of these options. The workspace will basically compile every file all the time, but the code for disabled options will be commented out by the #if...#endif. This may one day lead to simplification of the Makefiles and configure scripts, but for the moment I'm leaving Makefiles and configure scripts alone. Affected options: BX_SUPPORT_APIC (cpu/apic.cc) BX_SUPPORT_X86_64 (cpu/*64.cc) BX_DEBUGGER (debug/*) BX_DISASM (disasm/*) BX_WITH_nameofgui (gui/*) BX_SUPPORT_CDROM (iodev/cdrom.cc) BX_NE2K_SUPPORT (iodev/eth*.cc, iodev/ne2k.cc) BX_SUPPORT_APIC (iodev/ioapic.cc) BX_IODEBUG_SUPPORT (iodev/iodebug.cc) BX_PCI_SUPPORT (iodev/pci*.cc) BX_SUPPORT_SB16 (iodev/sb*.cc) Modified Files: cpu/apic.cc cpu/arith64.cc cpu/ctrl_xfer64.cc cpu/data_xfer64.cc cpu/fetchdecode64.cc cpu/logical64.cc cpu/mult64.cc cpu/resolve64.cc cpu/shift64.cc cpu/stack64.cc debug/Makefile.in debug/crc.cc debug/dbg_main.cc debug/lexer.l debug/linux.cc debug/parser.c debug/parser.y disasm/dis_decode.cc disasm/dis_groups.cc gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/macintosh.cc gui/rfb.cc gui/sdl.cc gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxmain.cc gui/x.cc iodev/cdrom.cc iodev/eth.cc iodev/eth_arpback.cc iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_packetmaker.cc iodev/eth_tap.cc iodev/eth_tuntap.cc iodev/eth_win32.cc iodev/ioapic.cc iodev/iodebug.cc iodev/ne2k.cc iodev/pci.cc iodev/pci2isa.cc iodev/sb16.cc iodev/soundlnx.cc iodev/soundwin.cc
2002-11-19 08:47:45 +03:00
2007-04-19 20:12:21 +04:00
void disassembler::Wd(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
else
2007-04-19 20:12:21 +04:00
(this->*resolve_modrm)(insn, D_SIZE);
}
2007-04-19 20:12:21 +04:00
void disassembler::Wq(const x86_insn *insn)
{
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
else
(this->*resolve_modrm)(insn, Q_SIZE);
}
2006-02-17 16:33:05 +03:00
2007-04-19 20:12:21 +04:00
void disassembler::Wdq(const x86_insn *insn)
{
2006-02-17 16:33:05 +03:00
if (insn->mod == 3)
{
if (intel_mode)
dis_sprintf ("xmm%d", insn->rm);
else
dis_sprintf("%%xmm%d", insn->rm);
}
else
2007-04-19 20:12:21 +04:00
(this->*resolve_modrm)(insn, O_SIZE);
2006-02-17 16:33:05 +03:00
}
2007-04-19 20:12:21 +04:00
void disassembler::Wsd(const x86_insn *insn) { Wq(insn); }
void disassembler::Wss(const x86_insn *insn) { Wd(insn); }
void disassembler::Wpd(const x86_insn *insn) { Wdq(insn); }
2006-02-17 16:33:05 +03:00
void disassembler::Wps(const x86_insn *insn) { Wdq(insn); }
// direct memory access
void disassembler::OP_O(const x86_insn *insn, unsigned size)
{
const char *seg;
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
print_datasize(size);
2006-08-13 13:40:07 +04:00
if (insn->as_64) {
Bit64u imm64 = fetch_qword();
dis_sprintf("%s:0x%08x%08x", seg, GET32H(imm64), GET32L(imm64));
2006-08-13 13:40:07 +04:00
}
else if (insn->as_32) {
Bit32u imm32 = fetch_dword();
dis_sprintf("%s:0x%x", seg, (unsigned) imm32);
}
else {
Bit16u imm16 = fetch_word();
dis_sprintf("%s:0x%x", seg, (unsigned) imm16);
}
}
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)
{
if(insn->mod == 3)
dis_sprintf("(bad)");
else
(this->*resolve_modrm)(insn, size);
}
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); }
void disassembler::Mss(const x86_insn *insn) { OP_M(insn, D_SIZE); }
void disassembler::Msd(const x86_insn *insn) { OP_M(insn, Q_SIZE); }
// string instructions
void disassembler::OP_X(const x86_insn *insn, unsigned size)
{
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
rsi = general_16bit_regname[rSI_REG];
}
if (insn->is_seg_override())
seg = segment_name[insn->seg_override];
else
seg = segment_name[DS_REG];
print_datasize(size);
if (intel_mode)
dis_sprintf("%s:[%s]", seg, rsi);
else
dis_sprintf("%s:(%s)", seg, rsi);
}
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::OP_Y(const x86_insn *insn, unsigned size)
{
const char *rdi;
if (insn->as_64) {
rdi = general_64bit_regname[rDI_REG];
}
else {
if (insn->as_32)
rdi = general_32bit_regname[rDI_REG];
else
rdi = general_16bit_regname[rDI_REG];
}
print_datasize(size);
if (intel_mode)
dis_sprintf("%s:[%s]", segment_name[ES_REG], rdi);
else
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); }
#define BX_JUMP_TARGET_NOT_REQ ((bx_address)(-1))
// jump offset
void disassembler::Jb(const x86_insn *insn)
{
Bit8s imm8 = (Bit8s) fetch_byte();
if (insn->is_64) {
2007-12-30 21:02:22 +03:00
Bit64u imm64 = (Bit8s) imm8;
dis_sprintf(".+0x%08x%08x", GET32H(imm64), GET32L(imm64));
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
2007-12-30 21:02:22 +03:00
Bit64u target = db_eip + imm64;
target += db_base;
dis_sprintf(" (0x%08x%08x)", GET32H(target), GET32L(target));
}
return;
}
if (insn->os_32) {
2007-12-30 21:02:22 +03:00
Bit32u imm32 = (Bit8s) imm8;
dis_sprintf(".+0x%08x", (unsigned) imm32);
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
2007-12-30 21:02:22 +03:00
Bit32u target = (Bit32u)(db_eip + (Bit32s) imm32);
target += db_base;
dis_sprintf(" (0x%08x)", target);
}
}
else {
2007-12-30 21:02:22 +03:00
Bit16u imm16 = (Bit8s) imm8;
dis_sprintf(".+0x%04x", (unsigned) imm16);
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
2007-12-30 21:02:22 +03:00
Bit16u target = (Bit16u)((db_eip + (Bit16s) imm16) & 0xffff);
dis_sprintf(" (0x%08x)", target + db_base);
}
}
}
void disassembler::Jw(const x86_insn *insn)
{
// Jw supported in 16-bit mode only
assert(! insn->is_64);
Bit16u imm16 = (Bit16s) fetch_word();
dis_sprintf(".+0x%04x", (unsigned) imm16);
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
Bit16u target = (db_eip + (Bit16s) imm16) & 0xffff;
dis_sprintf(" (0x%08x)", target + db_base);
}
}
void disassembler::Jd(const x86_insn *insn)
{
Bit32s imm32 = (Bit32s) fetch_dword();
if (insn->is_64) {
2007-12-30 21:02:22 +03:00
Bit64u imm64 = (Bit32s) imm32;
dis_sprintf(".+0x%08x%08x", GET32H(imm64), GET32L(imm64));
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
2007-12-30 21:02:22 +03:00
Bit64u target = db_eip + (Bit64s) imm64;
target += db_base;
dis_sprintf(" (0x%08x%08x)", GET32H(target), GET32L(target));
}
return;
}
dis_sprintf(".+0x%08x", (unsigned) imm32);
if (db_base != BX_JUMP_TARGET_NOT_REQ) {
2007-12-30 21:02:22 +03:00
Bit32u target = (Bit32u)(db_eip + (Bit32s) imm32);
target += db_base;
dis_sprintf(" (0x%08x)", target);
}
}