hmcs40 WIP

This commit is contained in:
hap 2015-03-05 21:12:20 +01:00
parent 9000997384
commit 42eafe6237
3 changed files with 139 additions and 35 deletions

View File

@ -65,7 +65,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(data_160x4, AS_DATA, 8, hmcs40_cpu_device)
AM_RANGE(0x00, 0x7f) AM_RAM
AM_RANGE(0x80, 0x9f) AM_RAM AM_MIRROR(0x70)
AM_RANGE(0x80, 0x8f) AM_RAM AM_MIRROR(0x30)
AM_RANGE(0xc0, 0xcf) AM_RAM AM_MIRROR(0x30)
ADDRESS_MAP_END
@ -95,6 +96,10 @@ void hmcs40_cpu_device::state_string_export(const device_state_entry &entry, ast
);
break;
case STATE_GENPC:
string.printf("%03X", m_pc << 1);
break;
default: break;
}
}
@ -123,6 +128,7 @@ void hmcs40_cpu_device::device_start()
m_data = &space(AS_DATA);
m_prgmask = (1 << m_prgwidth) - 1;
m_datamask = (1 << m_datawidth) - 1;
m_xmask = (1 << (m_datawidth - 4)) - 1;
m_read_d.resolve_safe(0);
m_write_d.resolve_safe();
@ -130,6 +136,7 @@ void hmcs40_cpu_device::device_start()
// zerofill
memset(m_stack, 0, sizeof(m_stack));
m_op = 0;
m_arg = 0;
m_pc = 0;
m_a = 0;
m_b = 0;
@ -143,6 +150,7 @@ void hmcs40_cpu_device::device_start()
// register for savestates
save_item(NAME(m_stack));
save_item(NAME(m_op));
save_item(NAME(m_arg));
save_item(NAME(m_pc));
save_item(NAME(m_a));
save_item(NAME(m_b));
@ -162,7 +170,7 @@ void hmcs40_cpu_device::device_start()
state_add(HMCS40_Y, "Y", m_y).formatstr("%01X");
state_add(HMCS40_SPY, "SPY", m_spy).formatstr("%01X");
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow();
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%03X").noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_s).formatstr("%2s").noshow();
m_icountptr = &m_icount;
@ -176,7 +184,7 @@ void hmcs40_cpu_device::device_start()
void hmcs40_cpu_device::device_reset()
{
m_pc = 0;
m_pc = 0xffff & m_prgmask;
m_op = 0;
}
@ -186,14 +194,41 @@ void hmcs40_cpu_device::device_reset()
// execute
//-------------------------------------------------
inline void hmcs40_cpu_device::increment_pc()
{
// PC lower bits is a LFSR identical to TI TMS1000
UINT8 mask = 0x3f;
UINT8 low = m_pc & mask;
int fb = (low << 1 & 0x20) == (low & 0x20);
if (low == (mask >> 1))
fb = 1;
else if (low == mask)
fb = 0;
m_pc = (m_pc & ~mask) | ((m_pc << 1 | fb) & mask);
}
inline void hmcs40_cpu_device::fetch_arg()
{
// P is the only 2-byte opcode
if (m_op == 0x3ff)
{
m_icount--;
m_arg = m_program->read_word(m_pc << 1);
increment_pc();
}
}
void hmcs40_cpu_device::execute_run()
{
while (m_icount > 0)
{
m_icount--;
debugger_instruction_hook(this, m_pc);
m_op = m_program->read_byte(m_pc);
m_pc = (m_pc + 1) & m_prgmask;
debugger_instruction_hook(this, m_pc << 1);
m_op = m_program->read_word(m_pc << 1);
increment_pc();
fetch_arg();
}
}

View File

@ -68,9 +68,11 @@ protected:
int m_datawidth;
int m_prgmask;
int m_datamask;
int m_xmask;
int m_stack_levels; // number of callstack levels
UINT16 m_stack[4]; // max 4
UINT16 m_op;
UINT16 m_arg;
int m_icount;
UINT16 m_pc; // Program Counter
@ -87,6 +89,15 @@ protected:
devcb_read16 m_read_d;
devcb_write16 m_write_d;
// misc internal helpers
void increment_pc();
void fetch_arg();
UINT8 ram_r();
void ram_w(UINT8 data);
void pop_stack();
void push_stack();
// opcode handlers
void op_lab();
void op_lba();
@ -104,7 +115,7 @@ protected:
void op_ayy();
void op_syy();
void op_xspx();
void op_sxpy();
void op_xspy();
void op_xspxy();
void op_lam();

View File

@ -2,6 +2,32 @@
// internal helpers
inline UINT8 hmcs40_cpu_device::ram_r()
{
UINT8 address = (m_x << 4 | m_y) & m_datamask;
return m_data->read_byte(address) & 0xf;
}
inline void hmcs40_cpu_device::ram_w(UINT8 data)
{
UINT8 address = (m_x << 4 | m_y) & m_datamask;
m_data->write_byte(address, data & 0xf);
}
void hmcs40_cpu_device::pop_stack()
{
m_pc = m_stack[0] & m_prgmask;
for (int i = 0; i < m_stack_levels-1; i++)
m_stack[i] = m_stack[i+1];
}
void hmcs40_cpu_device::push_stack()
{
for (int i = m_stack_levels-1; i >= 1; i--)
m_stack[i] = m_stack[i-1];
m_stack[0] = m_pc;
}
void hmcs40_cpu_device::op_illegal()
{
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_pc);
@ -16,37 +42,45 @@ void hmcs40_cpu_device::op_illegal()
void hmcs40_cpu_device::op_lab()
{
// LAB: Load A from B
op_illegal();
m_a = m_b;
}
void hmcs40_cpu_device::op_lba()
{
// LBA: Load B from A
op_illegal();
m_b = m_a;
}
void hmcs40_cpu_device::op_lay()
{
// LAY: Load A from Y
op_illegal();
m_a = m_y;
}
void hmcs40_cpu_device::op_laspx()
{
// LASPX: Load A from SPX
op_illegal();
m_a = m_spx;
}
void hmcs40_cpu_device::op_laspy()
{
// LASPY: Load A from SPY
op_illegal();
m_a = m_spy;
}
void hmcs40_cpu_device::op_xamr()
{
// XAMR m: Exchange A and MR(m)
op_illegal();
// determine MR(Memory Register) location
UINT8 y = m_op & 0xf;
UINT8 x = (y > 3) ? 0xf : (y + 12);
UINT8 address = (x << 4 | y) & m_datamask;
UINT8 old_a = m_a;
m_a = m_data->read_byte(address) & 0xf;
m_data->write_byte(address, old_a & 0xf);
}
@ -55,67 +89,78 @@ void hmcs40_cpu_device::op_xamr()
void hmcs40_cpu_device::op_lxa()
{
// LXA: Load X from A
op_illegal();
m_x = m_a;
}
void hmcs40_cpu_device::op_lya()
{
// LYA: Load Y from A
op_illegal();
m_y = m_a;
}
void hmcs40_cpu_device::op_lxi()
{
// LXI i: Load X from Immediate
op_illegal();
m_x = m_op & 0xf;
}
void hmcs40_cpu_device::op_lyi()
{
// LYI i: Load Y from Immediate
op_illegal();
m_y = m_op & 0xf;
}
void hmcs40_cpu_device::op_iy()
{
// IY: Increment Y
op_illegal();
m_y = (m_y + 1) & 0xf;
m_s = (m_y != 0);
}
void hmcs40_cpu_device::op_dy()
{
// DY: Decrement Y
op_illegal();
m_y = (m_y - 1) & 0xf;
m_s = (m_y != 0xf);
}
void hmcs40_cpu_device::op_ayy()
{
// AYY: Add A to Y
op_illegal();
m_y += m_a;
m_s = m_y >> 4 & 1;
m_y &= 0xf;
}
void hmcs40_cpu_device::op_syy()
{
// SYY: Subtract A from Y
op_illegal();
m_y -= m_a;
m_s = ~m_y >> 4 & 1;
m_y &= 0xf;
}
void hmcs40_cpu_device::op_xspx()
{
// XSPX: Exchange X and SPX
op_illegal();
UINT8 old_x = m_x;
m_x = m_spx;
m_spx = old_x;
}
void hmcs40_cpu_device::op_sxpy()
void hmcs40_cpu_device::op_xspy()
{
// SXPY: Exchange Y and SPY
op_illegal();
// XSPY: Exchange Y and SPY
UINT8 old_y = m_y;
m_y = m_spy;
m_spy = old_y;
}
void hmcs40_cpu_device::op_xspxy()
{
// XSPXY: Exchange X and SPX, Y and SPY
op_illegal();
op_xspx();
op_xspy();
}
@ -124,37 +169,49 @@ void hmcs40_cpu_device::op_xspxy()
void hmcs40_cpu_device::op_lam()
{
// LAM (XY): Load A from Memory
op_illegal();
m_a = ram_r();
op_xspxy();
}
void hmcs40_cpu_device::op_lbm()
{
// LBM (XY): Load B from Memory
op_illegal();
m_b = ram_r();
op_xspxy();
}
void hmcs40_cpu_device::op_xma()
{
// XMA (XY): Exchange Memory and A
op_illegal();
UINT8 old_a = m_a;
m_a = ram_r();
ram_w(old_a);
op_xspxy();
}
void hmcs40_cpu_device::op_xmb()
{
// XMB (XY): Exchange Memory and B
op_illegal();
UINT8 old_b = m_b;
m_b = ram_r();
ram_w(old_b);
op_xspxy();
}
void hmcs40_cpu_device::op_lmaiy()
{
// LMAIY (X): Load Memory from A, Increment Y
op_illegal();
ram_w(m_a);
op_iy();
op_xspx();
}
void hmcs40_cpu_device::op_lmady()
{
// LMADY (X): Load Memory from A, Decrement Y
op_illegal();
ram_w(m_a);
op_dy();
op_xspx();
}
@ -163,19 +220,20 @@ void hmcs40_cpu_device::op_lmady()
void hmcs40_cpu_device::op_lmiiy()
{
// LMIIY i: Load Memory from Immediate, Increment Y
op_illegal();
ram_w(m_op & 0xf);
op_iy();
}
void hmcs40_cpu_device::op_lai()
{
// LAI i: Load A from Immediate
op_illegal();
m_a = m_op & 0xf;
}
void hmcs40_cpu_device::op_lbi()
{
// LBI i: Load B from Immediate
op_illegal();
m_b = m_op & 0xf;
}