diff options
Diffstat (limited to 'src/devices/cpu/m6809/hd6309.cpp')
-rw-r--r-- | src/devices/cpu/m6809/hd6309.cpp | 176 |
1 files changed, 80 insertions, 96 deletions
diff --git a/src/devices/cpu/m6809/hd6309.cpp b/src/devices/cpu/m6809/hd6309.cpp index 8ca8c3d15c5..caba599adef 100644 --- a/src/devices/cpu/m6809/hd6309.cpp +++ b/src/devices/cpu/m6809/hd6309.cpp @@ -26,7 +26,11 @@ machine must be twos complement History: - + +July 2016 ErikGav: + Unify with 6809 pairs and quads (A+B=D, E+F=W, D+W=Q) + Initialize V register to $FFFF at startup + March 2013 NPW: Rewrite of 6809/6309/Konami CPU; attempted to make cycle exact. @@ -134,7 +138,6 @@ hd6309_device::hd6309_device(const machine_config &mconfig, const char *tag, dev { } - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -144,20 +147,27 @@ void hd6309_device::device_start() super::device_start(); // register our state for the debugger - state_add(HD6309_E, "E", m_w.b.h).mask(0xff); - state_add(HD6309_F, "F", m_w.b.l).mask(0xff); - state_add(HD6309_W, "W", m_w.w).mask(0xffff); - state_add(HD6309_V, "V", m_v.w).mask(0xffff); - state_add(HD6309_MD, "MD", m_md).mask(0xff); + state_add(HD6309_MD, "MD", m_md).mask(0xff); + state_add(HD6309_V, "V", m_v.w).mask(0xffff); + state_add(HD6309_A, "A", m_q.r.a).mask(0xff); + state_add(HD6309_B, "B", m_q.r.b).mask(0xff); + state_add(HD6309_D, "D", m_q.r.d).mask(0xffff); + state_add(HD6309_E, "E", m_q.r.e).mask(0xff); + state_add(HD6309_F, "F", m_q.r.f).mask(0xff); + state_add(HD6309_W, "W", m_q.r.w).mask(0xffff); + state_add(HD6309_Q, "Q", m_q.q).mask(0xffffffff); + state_add(HD6309_X, "X", m_x.w).mask(0xffff); + state_add(HD6309_Y, "Y", m_y.w).mask(0xffff); + state_add(HD6309_U, "U", m_u.w).mask(0xffff); // initialize variables - m_w.w = 0x0000; - m_v.w = 0x0000; + m_q.q = 0x00000000; + m_v.w = 0xffff; // v is initialized to $ffff at reset m_md = 0x00; m_temp_im = 0x00; // setup regtable - save_item(NAME(m_w.w)); + save_item(NAME(m_q.r.w)); save_item(NAME(m_v.w)); save_item(NAME(m_md)); save_item(NAME(m_temp_im)); @@ -184,22 +194,22 @@ void hd6309_device::device_reset() void hd6309_device::device_pre_save() { - if (m_reg8 == &m_d.b.h) m_reg = HD6309_A; - else if (m_reg8 == &m_d.b.l) m_reg = HD6309_B; - else if (m_reg8 == &m_w.b.h) m_reg = HD6309_E; - else if (m_reg8 == &m_w.b.l) m_reg = HD6309_F; + if (m_reg8 == &m_q.r.a) m_reg = HD6309_A; + else if (m_reg8 == &m_q.r.b) m_reg = HD6309_B; + else if (m_reg8 == &m_q.r.e) m_reg = HD6309_E; + else if (m_reg8 == &m_q.r.f) m_reg = HD6309_F; else if (m_reg8 == &m_cc) m_reg = HD6309_CC; else if (m_reg8 == &m_dp) m_reg = HD6309_DP; else if (m_reg8 == &m_md) m_reg = HD6309_MD; else if (m_reg8 == &m_temp.b.l) m_reg = HD6309_ZERO_BYTE; - else if (m_reg16 == &m_d) m_reg = HD6309_D; + else if (m_reg16 == &m_q.p.d) m_reg = HD6309_D; else if (m_reg16 == &m_x) m_reg = HD6309_X; else if (m_reg16 == &m_y) m_reg = HD6309_Y; else if (m_reg16 == &m_u) m_reg = HD6309_U; else if (m_reg16 == &m_s) m_reg = HD6309_S; else if (m_reg16 == &m_pc) m_reg = HD6309_PC; - else if (m_reg16 == &m_w) m_reg = HD6309_W; + else if (m_reg16 == &m_q.p.w) m_reg = HD6309_W; else if (m_reg16 == &m_v) m_reg = HD6309_V; else if (m_reg16 == &m_temp) m_reg = HD6309_ZERO_WORD; else @@ -219,16 +229,16 @@ void hd6309_device::device_post_load() switch(m_reg) { case HD6309_A: - set_regop8(m_d.b.h); + set_regop8(m_q.r.a); break; case HD6309_B: - set_regop8(m_d.b.l); + set_regop8(m_q.r.b); break; case HD6309_E: - set_regop8(m_w.b.h); + set_regop8(m_q.r.e); break; case HD6309_F: - set_regop8(m_w.b.l); + set_regop8(m_q.r.f); break; case HD6309_CC: set_regop8(m_cc); @@ -244,7 +254,7 @@ void hd6309_device::device_post_load() break; case HD6309_D: - set_regop16(m_d); + set_regop16(m_q.p.d); break; case HD6309_X: set_regop16(m_x); @@ -262,7 +272,7 @@ void hd6309_device::device_post_load() set_regop16(m_pc); break; case HD6309_W: - set_regop16(m_w); + set_regop16(m_q.p.w); break; case HD6309_V: set_regop16(m_v); @@ -321,10 +331,10 @@ inline UINT8 hd6309_device::read_operand() { case ADDRESSING_MODE_EA: return read_memory(m_ea.w); case ADDRESSING_MODE_IMMEDIATE: return read_opcode_arg(); - case ADDRESSING_MODE_REGISTER_A: return m_d.b.h; - case ADDRESSING_MODE_REGISTER_B: return m_d.b.l; - case ADDRESSING_MODE_REGISTER_E: return m_w.b.h; - case ADDRESSING_MODE_REGISTER_F: return m_w.b.l; + case ADDRESSING_MODE_REGISTER_A: return m_q.r.a; + case ADDRESSING_MODE_REGISTER_B: return m_q.r.b; + case ADDRESSING_MODE_REGISTER_E: return m_q.r.e; + case ADDRESSING_MODE_REGISTER_F: return m_q.r.f; default: fatalerror("Unexpected"); } } @@ -340,8 +350,8 @@ inline UINT8 hd6309_device::read_operand(int ordinal) { case ADDRESSING_MODE_EA: return read_memory(m_ea.w + ordinal); case ADDRESSING_MODE_IMMEDIATE: return read_opcode_arg(); - case ADDRESSING_MODE_REGISTER_D: return (ordinal & 1) ? m_d.b.l : m_d.b.h; - case ADDRESSING_MODE_REGISTER_W: return (ordinal & 1) ? m_w.b.l : m_w.b.h; + case ADDRESSING_MODE_REGISTER_D: return (ordinal & 1) ? m_q.r.b : m_q.r.a; + case ADDRESSING_MODE_REGISTER_W: return (ordinal & 1) ? m_q.r.f : m_q.r.e; case ADDRESSING_MODE_REGISTER_X: return (ordinal & 1) ? m_x.b.l : m_x.b.h; case ADDRESSING_MODE_REGISTER_Y: return (ordinal & 1) ? m_y.b.l : m_y.b.h; case ADDRESSING_MODE_REGISTER_U: return (ordinal & 1) ? m_u.b.l : m_u.b.h; @@ -363,10 +373,10 @@ inline void hd6309_device::write_operand(UINT8 data) switch(m_addressing_mode) { case ADDRESSING_MODE_EA: write_memory(m_ea.w, data); break; - case ADDRESSING_MODE_REGISTER_A: m_d.b.h = data; break; - case ADDRESSING_MODE_REGISTER_B: m_d.b.l = data; break; - case ADDRESSING_MODE_REGISTER_E: m_w.b.h = data; break; - case ADDRESSING_MODE_REGISTER_F: m_w.b.l = data; break; + case ADDRESSING_MODE_REGISTER_A: m_q.r.a = data; break; + case ADDRESSING_MODE_REGISTER_B: m_q.r.b = data; break; + case ADDRESSING_MODE_REGISTER_E: m_q.r.e = data; break; + case ADDRESSING_MODE_REGISTER_F: m_q.r.f = data; break; case ADDRESSING_MODE_ZERO: break; default: fatalerror("Unexpected"); } @@ -382,8 +392,8 @@ inline void hd6309_device::write_operand(int ordinal, UINT8 data) switch(m_addressing_mode) { case ADDRESSING_MODE_EA: write_memory(m_ea.w + ordinal, data); break; - case ADDRESSING_MODE_REGISTER_D: *((ordinal & 1) ? &m_d.b.l : &m_d.b.h) = data; break; - case ADDRESSING_MODE_REGISTER_W: *((ordinal & 1) ? &m_w.b.l : &m_w.b.h) = data; break; + case ADDRESSING_MODE_REGISTER_D: *((ordinal & 1) ? &m_q.r.b : &m_q.r.a) = data; break; + case ADDRESSING_MODE_REGISTER_W: *((ordinal & 1) ? &m_q.r.f : &m_q.r.e) = data; break; case ADDRESSING_MODE_REGISTER_X: *((ordinal & 1) ? &m_x.b.l : &m_x.b.h) = data; break; case ADDRESSING_MODE_REGISTER_Y: *((ordinal & 1) ? &m_y.b.l : &m_y.b.h) = data; break; case ADDRESSING_MODE_REGISTER_U: *((ordinal & 1) ? &m_u.b.l : &m_u.b.h) = data; break; @@ -405,8 +415,8 @@ inline UINT8 &hd6309_device::bittest_register() switch(m_temp_im & 0xC0) { case 0x00: return m_cc; - case 0x40: return m_d.b.h; - case 0x80: return m_d.b.l; + case 0x40: return m_q.r.a; + case 0x80: return m_q.r.b; default: return m_temp.b.l; } } @@ -456,22 +466,22 @@ inline m6809_base_device::exgtfr_register hd6309_device::read_exgtfr_register(UI switch(reg & 0x0F) { - case 0: value = m_d.w; break; // D + case 0: value = m_q.r.d; break; // D case 1: value = m_x.w; break; // X case 2: value = m_y.w; break; // Y case 3: value = m_u.w; break; // U case 4: value = m_s.w; break; // S case 5: value = m_pc.w; break; // PC - case 6: value = m_w.w; break; // W + case 6: value = m_q.r.w; break; // W case 7: value = m_v.w; break; // V - case 8: value = ((UINT16) m_d.b.h) << 8 | m_d.b.h; break; // A - case 9: value = ((UINT16) m_d.b.l) << 8 | m_d.b.l; break; // B + case 8: value = ((UINT16) m_q.r.a) << 8 | m_q.r.a; break; // A + case 9: value = ((UINT16) m_q.r.b) << 8 | m_q.r.b; break; // B case 10: value = ((UINT16) m_cc) << 8 | m_cc; break; // CC case 11: value = ((UINT16) m_dp) << 8 | m_dp; break; // DP case 12: value = 0; break; // 0 case 13: value = 0; break; // 0 - case 14: value = ((UINT16) m_w.b.h) << 8 | m_w.b.h; break; // E - case 15: value = ((UINT16) m_w.b.l) << 8 | m_w.b.l; break; // F + case 14: value = ((UINT16) m_q.r.e) << 8 | m_q.r.e; break; // E + case 15: value = ((UINT16) m_q.r.f) << 8 | m_q.r.f; break; // F default: fatalerror("Should not reach here"); } @@ -492,22 +502,22 @@ inline void hd6309_device::write_exgtfr_register(UINT8 reg, m6809_base_device::e { switch(reg & 0x0F) { - case 0: m_d.w = value.word_value; break; // D + case 0: m_q.r.d = value.word_value; break; // D case 1: m_x.w = value.word_value; break; // X case 2: m_y.w = value.word_value; break; // Y case 3: m_u.w = value.word_value; break; // U case 4: m_s.w = value.word_value; break; // S case 5: m_pc.w = value.word_value; break; // PC - case 6: m_w.w = value.word_value; break; // W + case 6: m_q.r.w = value.word_value; break; // W case 7: m_v.w = value.word_value; break; // V - case 8: m_d.b.h = (UINT8) (value.word_value >> 8); break; // A - case 9: m_d.b.l = (UINT8) (value.word_value >> 0); break; // B + case 8: m_q.r.a = (UINT8) (value.word_value >> 8); break; // A + case 9: m_q.r.b = (UINT8) (value.word_value >> 0); break; // B case 10: m_cc = (UINT8) (value.word_value >> 0); break; // CC case 11: m_dp = (UINT8) (value.word_value >> 8); break; // DP case 12: break; // 0 case 13: break; // 0 - case 14: m_w.b.h = (UINT8) (value.word_value >> 8); break; // E - case 15: m_w.b.l = (UINT8) (value.word_value >> 0); break; // F + case 14: m_q.r.e = (UINT8) (value.word_value >> 8); break; // E + case 15: m_q.r.f = (UINT8) (value.word_value >> 0); break; // F default: fatalerror("Should not reach here"); } @@ -525,7 +535,7 @@ inline bool hd6309_device::tfr_read(UINT8 opcode, UINT8 arg, UINT8 &data) switch(arg & 0xF0) { - case 0x00: reg = &m_d; break; + case 0x00: reg = &m_q.p.d; break; case 0x10: reg = &m_x; break; case 0x20: reg = &m_y; break; case 0x30: reg = &m_u; break; @@ -558,7 +568,7 @@ inline bool hd6309_device::tfr_write(UINT8 opcode, UINT8 arg, UINT8 data) switch(arg & 0x0F) { - case 0x00: reg = &m_d; break; + case 0x00: reg = &m_q.p.d; break; case 0x01: reg = &m_x; break; case 0x02: reg = &m_y; break; case 0x03: reg = &m_u; break; @@ -598,22 +608,22 @@ void hd6309_device::register_register_op() // set destination switch((operand >> 0) & 0x0F) { - case 0: set_regop16(m_d); break; // D + case 0: set_regop16(m_q.p.d); break; // D case 1: set_regop16(m_x); break; // X case 2: set_regop16(m_y); break; // Y case 3: set_regop16(m_u); break; // U case 4: set_regop16(m_s); break; // S case 5: set_regop16(m_pc); break; // PC - case 6: set_regop16(m_w); break; // W + case 6: set_regop16(m_q.p.w); break; // W case 7: set_regop16(m_v); break; // V - case 8: if (promote) set_regop16(m_d); else set_regop8(m_d.b.h); break; // A - case 9: if (promote) set_regop16(m_d); else set_regop8(m_d.b.l); break; // B + case 8: if (promote) set_regop16(m_q.p.d); else set_regop8(m_q.r.a); break; // A + case 9: if (promote) set_regop16(m_q.p.d); else set_regop8(m_q.r.b); break; // B case 10: if (promote) set_regop16(m_temp); else set_regop8(m_cc); break; // CC case 11: if (promote) set_regop16(m_temp); else set_regop8(m_dp); break; // DP case 12: if (promote) set_regop16(m_temp); else set_regop8(m_temp.b.l); break; // 0 case 13: if (promote) set_regop16(m_temp); else set_regop8(m_temp.b.l); break; // 0 - case 14: if (promote) set_regop16(m_w); else set_regop8(m_w.b.h); break; // E - case 15: if (promote) set_regop16(m_w); else set_regop8(m_w.b.l); break; // F + case 14: if (promote) set_regop16(m_q.p.w); else set_regop8(m_q.r.e); break; // E + case 15: if (promote) set_regop16(m_q.p.w); else set_regop8(m_q.r.f); break; // F default: fatalerror("Should not reach here"); } @@ -645,33 +655,6 @@ void hd6309_device::register_register_op() eat(1); } - -//------------------------------------------------- -// get_q -//------------------------------------------------- - -UINT32 hd6309_device::get_q() -{ - PAIR result; - result.w.h = m_d.w; - result.w.l = m_w.w; - return result.d; -} - - -//------------------------------------------------- -// put_q -//------------------------------------------------- - -void hd6309_device::put_q(UINT32 value) -{ - PAIR pair; - pair.d = value; - m_d.w = pair.w.h; - m_w.w = pair.w.l; -} - - //------------------------------------------------- // muld - (Q := D * operand) //------------------------------------------------- @@ -679,8 +662,8 @@ void hd6309_device::put_q(UINT32 value) void hd6309_device::muld() { UINT32 result; - result = ((INT16) m_d.w) * ((INT16) m_temp.w); - put_q(set_flags<UINT32>(CC_NZ, result)); + result = ((INT16) m_q.r.d) * ((INT16) m_temp.w); + m_q.q = (set_flags<UINT32>(CC_NZ, result)); m_cc &= ~CC_VC; } @@ -697,18 +680,18 @@ bool hd6309_device::divq() if (m_temp.w == 0) return false; - INT32 q = get_q(); + INT32 q = m_q.q; INT32 old_q = q; // do the divide/modulo result = q / (INT16) m_temp.w; - m_d.w = q % (INT16) m_temp.w; + m_q.r.d = q % (INT16) m_temp.w; // set NZ condition codes - m_w.w = set_flags<UINT16>(CC_NZ, result); + m_q.r.w = set_flags<UINT16>(CC_NZ, result); // set C condition code - if (m_w.w & 0x0001) + if (m_q.r.w & 0x0001) m_cc |= CC_C; else m_cc &= ~CC_C; @@ -726,7 +709,7 @@ bool hd6309_device::divq() else if (old_q == 0 ) m_cc |= CC_Z; - put_q(old_q); + m_q.q = old_q; } } else @@ -749,18 +732,18 @@ bool hd6309_device::divd() if (m_temp.b.l == 0) return false; - INT16 old_d = m_d.w; + INT16 old_d = m_q.r.d; INT16 result; // do the divide/modulo - result = ((INT16) m_d.w) / (INT8) m_temp.b.l; - m_d.b.h = ((INT16) m_d.w) % (INT8) m_temp.b.l; + result = ((INT16) m_q.r.d) / (INT8) m_temp.b.l; + m_q.r.a = ((INT16) m_q.r.d) % (INT8) m_temp.b.l; // set NZ condition codes - m_d.b.l = set_flags<UINT8>(CC_NZ, result); + m_q.r.b = set_flags<UINT8>(CC_NZ, result); // set C condition code - if (m_d.b.l & 0x01) + if (m_q.r.b & 0x01) m_cc |= CC_C; else m_cc &= ~CC_C; @@ -774,7 +757,7 @@ bool hd6309_device::divd() { // hard overflow - division is aborted set_flags<UINT16>(CC_NZ, old_d); - m_d.w = abs(old_d); + m_q.r.d = abs(old_d); } } else @@ -812,3 +795,4 @@ void hd6309_device::execute_run() execute_one(); } while(m_icount > 0); } + |