From 42eafe6237309856895136356f787bccbc24d717 Mon Sep 17 00:00:00 2001 From: hap Date: Thu, 5 Mar 2015 21:12:20 +0100 Subject: [PATCH] hmcs40 WIP --- src/emu/cpu/hmcs40/hmcs40.c | 47 +++++++++++-- src/emu/cpu/hmcs40/hmcs40.h | 13 +++- src/emu/cpu/hmcs40/hmcs40op.inc | 114 ++++++++++++++++++++++++-------- 3 files changed, 139 insertions(+), 35 deletions(-) diff --git a/src/emu/cpu/hmcs40/hmcs40.c b/src/emu/cpu/hmcs40/hmcs40.c index c3bf2c93a4e..1a6c8d178c7 100644 --- a/src/emu/cpu/hmcs40/hmcs40.c +++ b/src/emu/cpu/hmcs40/hmcs40.c @@ -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(); } } diff --git a/src/emu/cpu/hmcs40/hmcs40.h b/src/emu/cpu/hmcs40/hmcs40.h index 0ff2af82267..166688d8cbf 100644 --- a/src/emu/cpu/hmcs40/hmcs40.h +++ b/src/emu/cpu/hmcs40/hmcs40.h @@ -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(); diff --git a/src/emu/cpu/hmcs40/hmcs40op.inc b/src/emu/cpu/hmcs40/hmcs40op.inc index 2c07d6f74bd..eff24fef960 100644 --- a/src/emu/cpu/hmcs40/hmcs40op.inc +++ b/src/emu/cpu/hmcs40/hmcs40op.inc @@ -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; }