î8089: rewrote disassembler

This commit is contained in:
Dirk Best 2014-01-14 17:58:30 +00:00
parent a1e0f39b2c
commit 88e7355999

View File

@ -7,296 +7,442 @@
Disassembler
Note: Incomplete
***************************************************************************/
#include "emu.h"
INT16 displacement(offs_t &pc, int wb, const UINT8 *oprom, bool aa1)
class i8089_instruction
{
INT16 result = 0;
switch (wb)
public:
i8089_instruction(offs_t pc, const UINT8 *oprom) :
m_oprom(oprom), m_ppc(pc), m_pc(0), m_flags(DASMFLAG_SUPPORTED)
{
case 1:
result = (INT16)(INT8)oprom[2 + aa1];
pc += 1;
break;
case 2:
result = oprom[2 + aa1] | (oprom[3 + aa1] << 8);
pc += 2;
break;
// instruction
m_brp = (oprom[0] >> 5) & 0x07;
m_wb = (oprom[0] >> 3) & 0x03;
m_aa = (oprom[0] >> 1) & 0x03;
m_w = (oprom[0] >> 0) & 0x01;
m_opc = (oprom[1] >> 2) & 0x3f;
m_mm = (oprom[1] >> 0) & 0x03;
// clear buffers
memset(m_buffer, 0, sizeof(m_buffer));
memset(m_offset, 0, sizeof(m_offset));
// start working
disassemble();
}
return result;
}
char *buffer() { return m_buffer; }
int length() { return m_pc; }
int flags() { return m_flags; }
void offset(char *buffer, offs_t &pc, int aa, int mm, const UINT8 *oprom)
{
const char *mm_name[] = { "ga", "gb", "gc", "pp" };
private:
const UINT8 *m_oprom;
switch (aa)
char m_buffer[256];
char m_offset[100];
offs_t m_ppc;
int m_pc;
// decoded instruction
int m_brp;
int m_wb;
int m_aa;
int m_w;
int m_opc;
int m_mm;
// dasm flags
int m_flags;
// register names
static const char *m_reg[];
// register index
enum
{
case 0: sprintf(buffer, "[%s]", mm_name[mm]); break;
case 1: sprintf(buffer, "[%s].%x", mm_name[mm], oprom[2]); pc++; break;
case 2: sprintf(buffer, "[%s+ix]", mm_name[mm]); break;
case 3: sprintf(buffer, "[%s+ix+]", mm_name[mm]); break;
GA, // 20-bit general purpose address a
GB, // 20-bit general purpose address b
GC, // 20-bit general purpose address c
BC, // byte count
TP, // 20-bit task pointer
IX, // byte count
CC, // mask compare
MC // channel control
};
// fetch 1-byte value
UINT8 fetch_value8()
{
UINT8 i = m_oprom[m_pc];
m_pc += 1;
return i;
}
}
UINT8 imm8(offs_t &pc, const UINT8 *oprom, bool aa1)
// fetch 2-byte value
UINT16 fetch_value16()
{
UINT16 i = m_oprom[m_pc] | m_oprom[m_pc + 1] << 8;
m_pc += 2;
return i;
}
// fetch a 1 or 2 byte immediate value
UINT16 fetch_immediate()
{
return (m_wb & 1) ? fetch_value8() : fetch_value16();
}
// print memory offset
void offset()
{
const char *mm_name[] = { "ga", "gb", "gc", "pp" };
switch (m_aa)
{
case 0: sprintf(m_offset, "[%s]", mm_name[m_mm]); break;
case 1: sprintf(m_offset, "[%s].%02x", mm_name[m_mm], m_oprom[m_pc]); m_pc++; break;
case 2: sprintf(m_offset, "[%s+ix]", mm_name[m_mm]); break;
case 3: sprintf(m_offset, "[%s+ix+]", mm_name[m_mm]); break;
}
}
// to register or memory from immediate
void from_i(const char *instr8, const char *instr16, const char *target)
{
if (m_w == 0 && m_wb == 1)
sprintf(m_buffer, "%s %s, %02x", instr8, target, fetch_immediate());
else if (m_w == 1 && m_wb == 2)
sprintf(m_buffer, "%s %s, %04x", instr16, target, fetch_immediate());
else
invalid();
}
// register, immediate
void inst_ri(const char *instr8, const char *instr16)
{
if (m_mm == 0)
from_i(instr8, instr16, m_reg[m_brp]);
else
invalid();
}
// register
void inst_r(const char *instr)
{
if (m_mm == 0 && m_w == 0 && m_aa == 0 && m_wb == 0)
sprintf(m_buffer, "%s %s", instr, m_reg[m_brp]);
else
invalid();
}
// jump register
void inst_jr(const char *instr8, const char *instr16)
{
UINT16 i = fetch_immediate();
if (m_mm == 0 && m_w == 0 && m_wb == 1)
sprintf(m_buffer, "%s %s, %05x", instr8, m_reg[m_brp], m_ppc + m_pc + (INT8) i);
else if (m_mm == 0 && m_w == 0 && m_wb == 2)
sprintf(m_buffer, "%s %s, %05x", instr16, m_reg[m_brp], m_ppc + m_pc + (INT16) i);
else
invalid();
}
// memory immediate
void inst_mi(const char *instr8, const char *instr16)
{
offset();
from_i(instr8, instr16, m_offset);
}
// register memory
void inst_rm(const char *instr8, const char *instr16)
{
offset();
if (m_w == 0 && m_wb == 0)
sprintf(m_buffer, "%s %s, %s", instr8, m_reg[m_brp], m_offset);
else if (m_w == 1 && m_wb == 0)
sprintf(m_buffer, "%s %s, %s", instr16, m_reg[m_brp], m_offset);
else
invalid();
}
// jump memory
void inst_jm(const char *jump8short, const char *jump8long)
{
offset();
UINT16 i = fetch_immediate();
if (m_w == 0 && m_wb == 1 && m_brp == 0)
sprintf(m_buffer, "%s %s, %05x", jump8short, m_offset, m_ppc + m_pc + (INT8) i);
else if (m_w == 0 && m_wb == 2 && m_brp == 0)
sprintf(m_buffer, "%s %s, %05x", jump8long, m_offset, m_ppc + m_pc + (INT16) i);
else
invalid();
}
// jump memory bit
void inst_jmb(const char *jump8short, const char *jump8long)
{
offset();
UINT16 i = fetch_immediate();
if (m_w == 0 && m_wb == 1)
sprintf(m_buffer, "%s %s, %d, %05x", jump8short, m_offset, m_brp, m_ppc + m_pc + (INT8) i);
else if (m_w == 0 && m_wb == 2)
sprintf(m_buffer, "%s %s, %d, %05x", jump8long, m_offset, m_brp, m_ppc + m_pc + (INT16) i);
else
invalid();
}
// memory register
void inst_mr(const char *instr8, const char *instr16)
{
offset();
if (m_w == 0 && m_wb == 0)
sprintf(m_buffer, "%s %s, %s", instr8, m_offset, m_reg[m_brp]);
else if (m_w == 1 && m_wb == 0)
sprintf(m_buffer, "%s %s, %s", instr16, m_offset, m_reg[m_brp]);
else
invalid();
}
// pointer memory
void inst_pm(const char *instr16)
{
offset();
if (m_w == 1 && m_wb == 0)
sprintf(m_buffer, "%s %s, %s", instr16, m_reg[m_brp], m_offset);
else
invalid();
}
// memory pointer
void inst_mp(const char *instr16)
{
offset();
if (m_w == 1 && m_wb == 0)
sprintf(m_buffer, "%s %s, %s", instr16, m_offset, m_reg[m_brp]);
else
invalid();
}
// jump memory
void inst_j16(const char *jump8short, const char *jump16short, const char *jump8long, const char *jump16long)
{
offset();
UINT16 i = fetch_immediate();
if (m_w == 0 && m_wb == 1)
sprintf(m_buffer, "%s %s, %05x", jump8short, m_offset, m_ppc + m_pc + (INT8) i);
else if (m_w == 1 && m_wb == 1)
sprintf(m_buffer, "%s %s, %05x", jump16short, m_offset, m_ppc + m_pc + (INT8) i);
else if (m_w == 0 && m_wb == 2)
sprintf(m_buffer, "%s %s, %05x", jump8long, m_offset, m_ppc + m_pc + (INT16) i);
else if (m_w == 1 && m_wb == 2)
sprintf(m_buffer, "%s %s, %05x", jump16long, m_offset, m_ppc + m_pc + (INT16) i);
else
invalid();
}
// memory
void inst_m(const char *instr8, const char *instr16)
{
offset();
if (m_w == 0 && m_wb == 0)
sprintf(m_buffer, "%s %s", instr8, m_offset);
else if (m_w == 1 && m_wb == 0)
sprintf(m_buffer, "%s %s", instr16, m_offset);
else
invalid();
}
// memory bit
void inst_b(const char *instr)
{
offset();
if (m_w == 0 && m_wb == 0)
sprintf(m_buffer, "%s %s, %d", instr, m_offset, m_brp);
else
invalid();
}
// invalid instruction
void invalid()
{
sprintf(m_buffer, "???");
}
void disassemble()
{
m_pc += 2;
switch (m_opc)
{
case 0x00:
if (m_mm == 0 && m_w == 0 && m_aa == 0 && m_wb == 0)
{
switch (m_brp)
{
case 0: sprintf(m_buffer, "nop"); break;
case 1: invalid(); break;
case 2: sprintf(m_buffer, "sintr"); break;
case 3: sprintf(m_buffer, "xfer"); break;
case 4: sprintf(m_buffer, "wid 8, 8"); break;
case 5: sprintf(m_buffer, "wid 8, 16"); break;
case 6: sprintf(m_buffer, "wid 16, 8"); break;
case 7: sprintf(m_buffer, "wid 16, 16"); break;
}
}
else
invalid();
break;
case 0x02:
if (m_w == 1 && m_aa == 0 && m_wb == 2)
{
UINT16 offs = fetch_immediate();
UINT16 segm = fetch_immediate();
sprintf(m_buffer, "lpdi %s, %05x", m_reg[m_brp], ((segm << 4) + offs) & 0xfffff);
}
else
invalid();
break;
case 0x08:
if (m_mm == 0)
{
UINT16 i = fetch_immediate();
if (m_w == 0 && m_aa == 0 && m_wb == 1 && m_brp == TP)
sprintf(m_buffer, "jmp %05x", m_ppc + m_pc + (INT8) i);
else if (m_w == 1 && m_aa == 0 && m_wb == 2 && m_brp == TP)
sprintf(m_buffer, "ljmp %05x", m_ppc + m_pc + (INT16) i);
else if (m_w == 0 && m_wb == 1)
sprintf(m_buffer, "addbi %s, %02x", m_reg[m_brp], i);
else if (m_w == 1 && m_wb == 2)
sprintf(m_buffer, "addi %s, %04x", m_reg[m_brp], i);
else
invalid();
}
else
invalid();
break;
case 0x09: inst_ri("orbi", "ori"); break;
case 0x0a: inst_ri("andbi", "andi"); break;
case 0x0b: inst_r("not"); break;
case 0x0c: inst_ri("movbi", "movi"); break;
case 0x0e: inst_r("inc"); break;
case 0x0f: inst_r("dec"); break;
case 0x10: inst_jr("jnz", "ljnz"); break;
case 0x11: inst_jr("jz", "ljz"); break;
case 0x12:
if (m_mm == 0 && m_w == 0 && m_aa == 0 && m_wb == 0 && m_brp == 1)
sprintf(m_buffer, "hlt");
else
invalid();
break;
case 0x13: inst_mi("movbi", "movi"); break;
case 0x20: inst_rm("movb", "mov"); break;
case 0x21: inst_mr("movb", "mov"); break;
case 0x22: inst_pm("lpd"); break;
case 0x23: inst_pm("movp"); break;
case 0x24:
if (m_wb == 0)
{
offset();
i8089_instruction *tmp = new i8089_instruction(m_pc, m_oprom + m_pc);
m_pc += tmp->length();
if (m_w == 0)
sprintf(m_buffer, "movb %s, %s", tmp->buffer(), m_offset);
else
sprintf(m_buffer, "mov %s, %s", tmp->buffer(), m_offset);
delete(tmp);
}
else
invalid();
break;
case 0x25:
if (m_w == 0 && m_wb == 3 && m_brp == 0)
{
offset();
UINT16 i = fetch_immediate();
int displacement = (INT8) fetch_immediate();
sprintf(m_buffer, "tsl %s, %02x, %05x", m_offset, i, m_ppc + m_pc + displacement);
}
else
invalid();
break;
case 0x26: inst_mp("movp"); break;
case 0x27:
if (m_w == 1 && m_brp == TP && (m_wb == 1 || m_wb == 2))
{
offset();
UINT16 i = fetch_immediate();
if (m_wb == 1)
sprintf(m_buffer, "call %s, %05x", m_offset, m_ppc + m_pc + (INT8) i);
else if (m_wb == 2)
sprintf(m_buffer, "lcall %s, %05x", m_offset, m_ppc + m_pc + (INT16) i);
m_flags = DASMFLAG_STEP_OVER;
}
else
invalid();
break;
case 0x28: inst_rm("addb", "add"); break;
case 0x29: inst_rm("orb", "or"); break;
case 0x2a: inst_mr("andb", "and"); break;
case 0x2b: inst_rm("notb", "not"); break;
case 0x2c: inst_jm("jmce", "ljmce"); break;
case 0x2d: inst_jm("jmcne", "ljmcne"); break;
case 0x2e: inst_jmb("jnbt", "ljnbt"); break;
case 0x2f: inst_jmb("jbt", "ljbt"); break;
case 0x30: inst_mi("addbi", "addi"); break;
case 0x31: inst_mi("orbi", "ori"); break;
case 0x32: inst_mi("andbi", "andi"); break;
case 0x33:
offset();
sprintf(m_buffer, "%s", m_offset);
break;
case 0x34: inst_mr("addb", "add"); break;
case 0x35: inst_mr("orb", "or"); break;
case 0x36: inst_mr("andb", "and"); break;
case 0x37: inst_mr("notb", "not"); break;
case 0x38: inst_j16("jnzb", "jnz", "ljnzb", "ljnz"); break;
case 0x39: inst_j16("jzb", "jz", "ljzb", "ljz"); break;
case 0x3a: inst_m("incb", "inc"); break;
case 0x3b: inst_m("decb", "dec"); break;
case 0x3d: inst_b("setb"); break;
case 0x3e: inst_b("clr"); break;
default:
invalid();
}
}
};
const char *i8089_instruction::m_reg[] =
{
pc += 1;
return oprom[2 + aa1];
}
UINT16 imm16(offs_t &pc, const UINT8 *oprom, bool aa1)
{
pc += 2;
return oprom[2 + aa1] | (oprom[3 + aa1] << 8);
}
#define BRP brp_name[brp]
#define SDISP displacement(pc, wb, oprom, (aa == 1))
#define OFFSET(x) offset(x, pc, aa, mm, oprom)
#define IMM8 imm8(pc, oprom, (aa == 1))
#define IMM16 imm16(pc, oprom, (aa == 1))
"ga", "gb", "gc", "bc", "tp", "ix", "cc", "mc"
};
CPU_DISASSEMBLE( i8089 )
{
const char *brp_name[] = { "ga", "gb", "gc", "bc", "tp", "ix", "cc", "mc" };
UINT32 flags = 0;
offs_t ppc = pc;
// temporary storage
char o[10], o2[10];
memset(o, 0, sizeof(o));
memset(o2, 0, sizeof(o2));
UINT16 off, seg;
// decode instruction
int brp = (oprom[0] >> 5) & 0x07;
int wb = (oprom[0] >> 3) & 0x03;
int aa = (oprom[0] >> 1) & 0x03;
int w = (oprom[0] >> 0) & 0x01;
int opc = (oprom[1] >> 2) & 0x3f;
int mm = (oprom[1] >> 0) & 0x03;
pc += 2;
switch (opc)
{
case 0x00:
switch (brp)
{
case 0: sprintf(buffer, "nop"); break;
case 1: sprintf(buffer, "???"); break;
case 2: sprintf(buffer, "sintr"); break;
case 3: sprintf(buffer, "xfer"); break;
default: sprintf(buffer, "wid %d, %d", BIT(brp, 1) ? 16 : 8, BIT(brp, 0) ? 16 : 8); break;
}
break;
case 0x02:
off = IMM16;
seg = IMM16;
sprintf(buffer, "lpdi %s, %4x %4x", BRP, off, seg);
break;
case 0x08:
if(brp == 4)
{
INT16 offset = (w ? IMM16 : (INT8)IMM8);
sprintf(buffer, "jmp %06x", pc + offset);
break;
}
if (w) sprintf(buffer, "addi %s, %04x", BRP, IMM16);
else sprintf(buffer, "addbi %s, %02x", BRP, IMM8);
break;
case 0x09:
if (w) sprintf(buffer, "ori %s, %04x", BRP, IMM16);
else sprintf(buffer, "orbi %s, %02x", BRP, IMM8);
break;
case 0x0a:
if (w) sprintf(buffer, "andi %s, %04x", BRP, IMM16);
else sprintf(buffer, "andbi %s, %02x", BRP, IMM8);
break;
case 0x0b:
sprintf(buffer, "not %s", BRP);
break;
case 0x0c:
if (w) sprintf(buffer, "movi %s, %04x", BRP, IMM16);
else sprintf(buffer, "movbi %s, %02x", BRP, IMM8);
break;
case 0x0e:
sprintf(buffer, "inc %s", BRP);
break;
case 0x0f:
sprintf(buffer, "dec %s", BRP);
break;
case 0x10:
sprintf(buffer, "jnz %s, %06x", BRP, pc + SDISP);
break;
case 0x11:
sprintf(buffer, "jz %s, %06x", BRP, pc + SDISP);
break;
case 0x12:
sprintf(buffer, "hlt");
break;
case 0x13:
OFFSET(o);
if (w) sprintf(buffer, "movi %s, %04x", o, IMM16);
else sprintf(buffer, "movbi %s, %02x", o, IMM8);
break;
case 0x20:
OFFSET(o);
if (w) sprintf(buffer, "mov %s, %s", BRP, o);
else sprintf(buffer, "movb %s, %s", BRP, o);
break;
case 0x21:
OFFSET(o);
if (w) sprintf(buffer, "mov %s, %s", o, BRP);
else sprintf(buffer, "movb %s, %s", o, BRP);
break;
case 0x22:
OFFSET(o);
sprintf(buffer, "lpd %s, %s", BRP, o);
break;
case 0x23:
OFFSET(o);
sprintf(buffer, "movp %s, %s", BRP, o);
break;
case 0x24:
{
char buf[20];
OFFSET(o);
pc += cpu_disassemble_i8089(device, buf, pc, oprom + (pc - ppc), opram, options) & 0xffff;
if(w) sprintf(buffer, "mov %s, %s", buf, o);
else sprintf(buffer, "movb %s, %s", buf, o);
break;
}
case 0x25:
{
OFFSET(o);
UINT16 i = IMM16;
sprintf(buffer, "tsl %s, %02x, %06x", o, i & 0xff, pc + (i >> 8));
break;
}
case 0x26:
OFFSET(o);
sprintf(buffer, "movp %s, %s", o, BRP);
break;
case 0x27:
OFFSET(o);
sprintf(buffer, "call %s, %06x", o, pc + SDISP);
flags = DASMFLAG_STEP_OVER;
break;
case 0x28:
OFFSET(o);
if (w) sprintf(buffer, "add %s, %s", BRP, o);
else sprintf(buffer, "addb %s, %s", BRP, o);
break;
case 0x29:
OFFSET(o);
if (w) sprintf(buffer, "or %s, %s", BRP, o);
else sprintf(buffer, "orb %s, %s", BRP, o);
break;
case 0x2a:
OFFSET(o);
if (w) sprintf(buffer, "and %s, %s", BRP, o);
else sprintf(buffer, "andb %s, %s", BRP, o);
break;
case 0x2b:
OFFSET(o);
if(w) sprintf(buffer, "not %s, %s", BRP, o);
else sprintf(buffer, "notb %s, %s", BRP, o);
break;
case 0x2c:
OFFSET(o);
sprintf(buffer, "jmce %s, %06x", o, pc + SDISP);
break;
case 0x2d:
OFFSET(o);
sprintf(buffer, "jmcne %s, %06x", o, pc + SDISP);
break;
case 0x2e:
OFFSET(o);
sprintf(buffer, "jnbt %s, %d, %06x", o, brp, pc + SDISP);
break;
case 0x2f:
OFFSET(o);
sprintf(buffer, "jbt %s, %d, %06x", o, brp, pc + SDISP);
break;
case 0x30:
OFFSET(o);
if (w) sprintf(buffer, "addi %s, %04x", o, IMM16);
else sprintf(buffer, "addbi %s, %02x", o, IMM8);
break;
case 0x31:
OFFSET(o);
if (w) sprintf(buffer, "ori %s, %04x", o, IMM16);
else sprintf(buffer, "orib %s, %02x", o, IMM8);
break;
case 0x32:
OFFSET(o);
if (w) sprintf(buffer, "andi %s, %04x", o, IMM16);
else sprintf(buffer, "andbi %s, %02x", o, IMM8);
break;
case 0x33:
OFFSET(o);
sprintf(buffer, "%s", o);
break;
case 0x34:
OFFSET(o);
if (w) sprintf(buffer, "add %s, %s", o, BRP);
else sprintf(buffer, "addb %s, %s", o, BRP);
break;
case 0x35:
OFFSET(o);
if (w) sprintf(buffer, "or %s, %s", o, BRP);
else sprintf(buffer, "orb %s, %s", o, BRP);
break;
case 0x36:
OFFSET(o);
if (w) sprintf(buffer, "and %s, %s", o, BRP);
else sprintf(buffer, "andb %s, %s", o, BRP);
break;
case 0x37:
OFFSET(o);
if(w) sprintf(buffer, "not %s", o);
else sprintf(buffer, "notb %s", o);
break;
case 0x38:
OFFSET(o);
if(w) sprintf(buffer, "jnz %s, %06x", o, pc + SDISP);
else sprintf(buffer, "jnzb %s, %06x", o, pc + SDISP);
break;
case 0x39:
OFFSET(o);
if(w) sprintf(buffer, "jz %s, %06x", o, pc + SDISP);
else sprintf(buffer, "jzb %s, %06x", o, pc + SDISP);
break;
case 0x3a:
OFFSET(o);
if (w) sprintf(buffer, "inc %s", o);
else sprintf(buffer, "incb %s", o);
break;
case 0x3b:
OFFSET(o);
if (w) sprintf(buffer, "dec %s", o);
else sprintf(buffer, "decb %s", o);
break;
case 0x3d:
OFFSET(o);
sprintf(buffer, "setb %s, %d", o, brp);
break;
case 0x3e:
OFFSET(o);
sprintf(buffer, "clr %s, %d", o, brp);
break;
default:
sprintf(buffer, "???");
}
return (pc - ppc) | flags | DASMFLAG_SUPPORTED;
i8089_instruction *i = new i8089_instruction(pc, oprom);
strcpy(buffer, i->buffer());
offs_t result = i->length() | i->flags();
delete(i);
return result;
}