diff --git a/src/emu/cpu/e0c6200/e0c6200.c b/src/emu/cpu/e0c6200/e0c6200.c index 9ee588455be..915231cb8eb 100644 --- a/src/emu/cpu/e0c6200/e0c6200.c +++ b/src/emu/cpu/e0c6200/e0c6200.c @@ -16,6 +16,8 @@ #include "e0c6200.h" #include "debugger.h" +#include "e0c6200op.inc" + const device_type EPSON_E0C6S46 = &device_creator; @@ -448,82 +450,82 @@ void e0c6200_cpu_device::execute_one() case 0xf0f: // AND r,q: logical AND register with register (affect flags: Z) - case 0xac0: m_icount -= 2; /* m_a &= m_a; */ set_zf(m_a); break; - case 0xac1: m_icount -= 2; m_a &= m_b; set_zf(m_a); break; - case 0xac2: m_icount -= 2; m_a &= read_mx(); set_zf(m_a); break; - case 0xac3: m_icount -= 2; m_a &= read_my(); set_zf(m_a); break; - case 0xac4: m_icount -= 2; m_b &= m_a; set_zf(m_b); break; - case 0xac5: m_icount -= 2; /* m_b &= m_b; */ set_zf(m_b); break; - case 0xac6: m_icount -= 2; m_b &= read_mx(); set_zf(m_b); break; - case 0xac7: m_icount -= 2; m_b &= read_my(); set_zf(m_b); break; - case 0xac8: m_icount -= 2; { UINT8 t = read_mx() & m_a; write_mx(t); set_zf(t); break; } - case 0xac9: m_icount -= 2; { UINT8 t = read_mx() & m_b; write_mx(t); set_zf(t); break; } - case 0xaca: m_icount -= 2; { UINT8 t = read_mx() & read_mx(); write_mx(t); set_zf(t); break; } - case 0xacb: m_icount -= 2; { UINT8 t = read_mx() & read_my(); write_mx(t); set_zf(t); break; } - case 0xacc: m_icount -= 2; { UINT8 t = read_my() & m_a; write_my(t); set_zf(t); break; } - case 0xacd: m_icount -= 2; { UINT8 t = read_my() & m_b; write_my(t); set_zf(t); break; } - case 0xace: m_icount -= 2; { UINT8 t = read_my() & read_mx(); write_my(t); set_zf(t); break; } - case 0xacf: m_icount -= 2; { UINT8 t = read_my() & read_my(); write_my(t); set_zf(t); break; } + case 0xac0: m_a = op_and(m_a, m_a); break; + case 0xac1: m_a = op_and(m_a, m_b); break; + case 0xac2: m_a = op_and(m_a, read_mx()); break; + case 0xac3: m_a = op_and(m_a, read_my()); break; + case 0xac4: m_b = op_and(m_b, m_a); break; + case 0xac5: m_b = op_and(m_b, m_b); break; + case 0xac6: m_b = op_and(m_b, read_mx()); break; + case 0xac7: m_b = op_and(m_b, read_my()); break; + case 0xac8: write_mx(op_and(read_mx(), m_a)); break; + case 0xac9: write_mx(op_and(read_mx(), m_b)); break; + case 0xaca: write_mx(op_and(read_mx(), read_mx())); break; + case 0xacb: write_mx(op_and(read_mx(), read_my())); break; + case 0xacc: write_my(op_and(read_my(), m_a)); break; + case 0xacd: write_my(op_and(read_my(), m_b)); break; + case 0xace: write_my(op_and(read_my(), read_mx())); break; + case 0xacf: write_my(op_and(read_my(), read_my())); break; // FAN r,q: AND r,q, but discard result - case 0xf10: m_icount -= 2; set_zf(m_a /* & m_a */); break; - case 0xf11: m_icount -= 2; set_zf(m_a & m_b); break; - case 0xf12: m_icount -= 2; set_zf(m_a & read_mx()); break; - case 0xf13: m_icount -= 2; set_zf(m_a & read_my()); break; - case 0xf14: m_icount -= 2; set_zf(m_b & m_a); break; - case 0xf15: m_icount -= 2; set_zf(m_b /* & m_b */); break; - case 0xf16: m_icount -= 2; set_zf(m_b & read_mx()); break; - case 0xf17: m_icount -= 2; set_zf(m_b & read_my()); break; - case 0xf18: m_icount -= 2; set_zf(read_mx() & m_a); break; - case 0xf19: m_icount -= 2; set_zf(read_mx() & m_b); break; - case 0xf1a: m_icount -= 2; set_zf(read_mx() & read_mx()); break; - case 0xf1b: m_icount -= 2; set_zf(read_mx() & read_my()); break; - case 0xf1c: m_icount -= 2; set_zf(read_my() & m_a); break; - case 0xf1d: m_icount -= 2; set_zf(read_my() & m_b); break; - case 0xf1e: m_icount -= 2; set_zf(read_my() & read_mx()); break; - case 0xf1f: m_icount -= 2; set_zf(read_my() & read_my()); break; + case 0xf10: op_and(m_a, m_a); break; + case 0xf11: op_and(m_a, m_b); break; + case 0xf12: op_and(m_a, read_mx()); break; + case 0xf13: op_and(m_a, read_my()); break; + case 0xf14: op_and(m_b, m_a); break; + case 0xf15: op_and(m_b, m_b); break; + case 0xf16: op_and(m_b, read_mx()); break; + case 0xf17: op_and(m_b, read_my()); break; + case 0xf18: op_and(read_mx(), m_a); break; + case 0xf19: op_and(read_mx(), m_b); break; + case 0xf1a: op_and(read_mx(), read_mx()); break; + case 0xf1b: op_and(read_mx(), read_my()); break; + case 0xf1c: op_and(read_my(), m_a); break; + case 0xf1d: op_and(read_my(), m_b); break; + case 0xf1e: op_and(read_my(), read_mx()); break; + case 0xf1f: op_and(read_my(), read_my()); break; // OR r,q: logical OR register with register (affect flags: Z) - case 0xad0: m_icount -= 2; /* m_a |= m_a; */ set_zf(m_a); break; - case 0xad1: m_icount -= 2; m_a |= m_b; set_zf(m_a); break; - case 0xad2: m_icount -= 2; m_a |= read_mx(); set_zf(m_a); break; - case 0xad3: m_icount -= 2; m_a |= read_my(); set_zf(m_a); break; - case 0xad4: m_icount -= 2; m_b |= m_a; set_zf(m_b); break; - case 0xad5: m_icount -= 2; /* m_b |= m_b; */ set_zf(m_b); break; - case 0xad6: m_icount -= 2; m_b |= read_mx(); set_zf(m_b); break; - case 0xad7: m_icount -= 2; m_b |= read_my(); set_zf(m_b); break; - case 0xad8: m_icount -= 2; { UINT8 t = read_mx() | m_a; write_mx(t); set_zf(t); break; } - case 0xad9: m_icount -= 2; { UINT8 t = read_mx() | m_b; write_mx(t); set_zf(t); break; } - case 0xada: m_icount -= 2; { UINT8 t = read_mx() | read_mx(); write_mx(t); set_zf(t); break; } - case 0xadb: m_icount -= 2; { UINT8 t = read_mx() | read_my(); write_mx(t); set_zf(t); break; } - case 0xadc: m_icount -= 2; { UINT8 t = read_my() | m_a; write_my(t); set_zf(t); break; } - case 0xadd: m_icount -= 2; { UINT8 t = read_my() | m_b; write_my(t); set_zf(t); break; } - case 0xade: m_icount -= 2; { UINT8 t = read_my() | read_mx(); write_my(t); set_zf(t); break; } - case 0xadf: m_icount -= 2; { UINT8 t = read_my() | read_my(); write_my(t); set_zf(t); break; } + case 0xad0: m_a = op_or(m_a, m_a); break; + case 0xad1: m_a = op_or(m_a, m_b); break; + case 0xad2: m_a = op_or(m_a, read_mx()); break; + case 0xad3: m_a = op_or(m_a, read_my()); break; + case 0xad4: m_b = op_or(m_b, m_a); break; + case 0xad5: m_b = op_or(m_b, m_b); break; + case 0xad6: m_b = op_or(m_b, read_mx()); break; + case 0xad7: m_b = op_or(m_b, read_my()); break; + case 0xad8: write_mx(op_or(read_mx(), m_a)); break; + case 0xad9: write_mx(op_or(read_mx(), m_b)); break; + case 0xada: write_mx(op_or(read_mx(), read_mx())); break; + case 0xadb: write_mx(op_or(read_mx(), read_my())); break; + case 0xadc: write_my(op_or(read_my(), m_a)); break; + case 0xadd: write_my(op_or(read_my(), m_b)); break; + case 0xade: write_my(op_or(read_my(), read_mx())); break; + case 0xadf: write_my(op_or(read_my(), read_my())); break; // XOR r,q: exclusive-OR register with register (affect flags: Z) - case 0xae0: m_icount -= 2; m_a ^= m_a; set_zf(m_a); break; - case 0xae1: m_icount -= 2; m_a ^= m_b; set_zf(m_a); break; - case 0xae2: m_icount -= 2; m_a ^= read_mx(); set_zf(m_a); break; - case 0xae3: m_icount -= 2; m_a ^= read_my(); set_zf(m_a); break; - case 0xae4: m_icount -= 2; m_b ^= m_a; set_zf(m_b); break; - case 0xae5: m_icount -= 2; m_b ^= m_b; set_zf(m_b); break; - case 0xae6: m_icount -= 2; m_b ^= read_mx(); set_zf(m_b); break; - case 0xae7: m_icount -= 2; m_b ^= read_my(); set_zf(m_b); break; - case 0xae8: m_icount -= 2; { UINT8 t = read_mx() ^ m_a; write_mx(t); set_zf(t); break; } - case 0xae9: m_icount -= 2; { UINT8 t = read_mx() ^ m_b; write_mx(t); set_zf(t); break; } - case 0xaea: m_icount -= 2; { UINT8 t = read_mx() ^ read_mx(); write_mx(t); set_zf(t); break; } - case 0xaeb: m_icount -= 2; { UINT8 t = read_mx() ^ read_my(); write_mx(t); set_zf(t); break; } - case 0xaec: m_icount -= 2; { UINT8 t = read_my() ^ m_a; write_my(t); set_zf(t); break; } - case 0xaed: m_icount -= 2; { UINT8 t = read_my() ^ m_b; write_my(t); set_zf(t); break; } - case 0xaee: m_icount -= 2; { UINT8 t = read_my() ^ read_mx(); write_my(t); set_zf(t); break; } - case 0xaef: m_icount -= 2; { UINT8 t = read_my() ^ read_my(); write_my(t); set_zf(t); break; } + case 0xae0: m_a = op_xor(m_a, m_a); break; + case 0xae1: m_a = op_xor(m_a, m_b); break; + case 0xae2: m_a = op_xor(m_a, read_mx()); break; + case 0xae3: m_a = op_xor(m_a, read_my()); break; + case 0xae4: m_b = op_xor(m_b, m_a); break; + case 0xae5: m_b = op_xor(m_b, m_b); break; + case 0xae6: m_b = op_xor(m_b, read_mx()); break; + case 0xae7: m_b = op_xor(m_b, read_my()); break; + case 0xae8: write_mx(op_xor(read_mx(), m_a)); break; + case 0xae9: write_mx(op_xor(read_mx(), m_b)); break; + case 0xaea: write_mx(op_xor(read_mx(), read_mx())); break; + case 0xaeb: write_mx(op_xor(read_mx(), read_my())); break; + case 0xaec: write_my(op_xor(read_my(), m_a)); break; + case 0xaed: write_my(op_xor(read_my(), m_b)); break; + case 0xaee: write_my(op_xor(read_my(), read_mx())); break; + case 0xaef: write_my(op_xor(read_my(), read_my())); break; // RLC r: rotate register left through carry (affect flags: C, Z) - case 0xaf0: m_icount -= 2; - case 0xaf5: m_icount -= 2; - case 0xafa: m_icount -= 2; read_mx(); - case 0xaff: m_icount -= 2; read_my(); + case 0xaf0: + case 0xaf5: + case 0xafa: read_mx(); + case 0xaff: read_my(); // RRC r: rotate register right through carry (affect flags: C, Z) case 0xe8c: @@ -645,27 +647,13 @@ void e0c6200_cpu_device::execute_one() // INC Mn: increment memory (affect flags: C, Z) case 0xf60: - { - m_icount -= 2; - UINT8 t = read_mn(); - t = (t + 1) & 0xf; - write_mn(t); - m_f = (m_f & ~1) | ((t == 0) ? 1 : 0); - set_zf(t); + write_mn(op_inc(read_mn())); break; - } // DEC Mn: decrement memory (affect flags: C, Z) case 0xf70: - { - m_icount -= 2; - UINT8 t = read_mn(); - t = (t - 1) & 0xf; - write_mn(t); - m_f = (m_f & ~1) | ((t == 0xf) ? 1 : 0); - set_zf(t); + write_mn(op_dec(read_mn())); break; - } // ADD r,i case 0xc00: @@ -733,28 +721,28 @@ void e0c6200_cpu_device::execute_one() // AND r,i: logical AND register with 4-bit immediate data (affect flags: Z) - case 0xc80: m_icount -= 2; m_a &= m_op & 0xf; set_zf(m_a); break; - case 0xc90: m_icount -= 2; m_b &= m_op & 0xf; set_zf(m_b); break; - case 0xca0: m_icount -= 2; { UINT8 t = read_mx() & (m_op & 0xf); write_mx(t); set_zf(t); break; } - case 0xcb0: m_icount -= 2; { UINT8 t = read_my() & (m_op & 0xf); write_my(t); set_zf(t); break; } + case 0xc80: m_a = op_and(m_a, m_op & 0xf); break; + case 0xc90: m_b = op_and(m_b, m_op & 0xf); break; + case 0xca0: write_mx(op_and(read_mx(), m_op & 0xf)); break; + case 0xcb0: write_my(op_and(read_my(), m_op & 0xf)); break; // FAN r,i: AND r,i, but discard result - case 0xd80: m_icount -= 2; set_zf(m_a & (m_op & 0xf)); break; - case 0xd90: m_icount -= 2; set_zf(m_b & (m_op & 0xf)); break; - case 0xda0: m_icount -= 2; set_zf(read_mx() & (m_op & 0xf)); break; - case 0xdb0: m_icount -= 2; set_zf(read_my() & (m_op & 0xf)); break; + case 0xd80: op_and(m_a, m_op & 0xf); break; + case 0xd90: op_and(m_b, m_op & 0xf); break; + case 0xda0: op_and(read_mx(), m_op & 0xf); break; + case 0xdb0: op_and(read_my(), m_op & 0xf); break; // OR r,i: logical OR register with 4-bit immediate data (affect flags: Z) - case 0xcc0: m_icount -= 2; m_a |= m_op & 0xf; set_zf(m_a); break; - case 0xcd0: m_icount -= 2; m_b |= m_op & 0xf; set_zf(m_b); break; - case 0xce0: m_icount -= 2; { UINT8 t = read_mx() | (m_op & 0xf); write_mx(t); set_zf(t); break; } - case 0xcf0: m_icount -= 2; { UINT8 t = read_my() | (m_op & 0xf); write_my(t); set_zf(t); break; } + case 0xcc0: m_a = op_or(m_a, m_op & 0xf); break; + case 0xcd0: m_b = op_or(m_b, m_op & 0xf); break; + case 0xce0: write_mx(op_or(read_mx(), m_op & 0xf)); break; + case 0xcf0: write_my(op_or(read_my(), m_op & 0xf)); break; // XOR r,i: exclusive-OR register with 4-bit immediate data (affect flags: Z) - case 0xd00: m_icount -= 2; m_a ^= m_op & 0xf; set_zf(m_a); break; - case 0xd10: m_icount -= 2; m_b ^= m_op & 0xf; set_zf(m_b); break; - case 0xd20: m_icount -= 2; { UINT8 t = read_mx() ^ (m_op & 0xf); write_mx(t); set_zf(t); break; } - case 0xd30: m_icount -= 2; { UINT8 t = read_my() ^ (m_op & 0xf); write_my(t); set_zf(t); break; } + case 0xd00: m_a = op_xor(m_a, m_op & 0xf); break; + case 0xd10: m_b = op_xor(m_b, m_op & 0xf); break; + case 0xd20: write_mx(op_xor(read_mx(), m_op & 0xf)); break; + case 0xd30: write_my(op_xor(read_my(), m_op & 0xf)); break; // SET F,i: set flag(s), this includes opcodes SCF, SZF, SDF, EI case 0xf40: diff --git a/src/emu/cpu/e0c6200/e0c6200.h b/src/emu/cpu/e0c6200/e0c6200.h index fab5263f3a3..930eee25abf 100644 --- a/src/emu/cpu/e0c6200/e0c6200.h +++ b/src/emu/cpu/e0c6200/e0c6200.h @@ -73,29 +73,36 @@ protected: UINT8 m_sp; // stackpointer (SPH, SPL) UINT8 m_f; // flags - // misc internal helpers - inline void set_zf(UINT8 data) { m_f = (m_f & ~2) | ((data & 0xf) ? 0 : 2); } - - // internal read/write (MX, MY, Mn/RP) - inline UINT8 read_mx() { return m_data->read_byte(m_xp << 8 | m_xh << 4 | m_xl) & 0xf; } - inline void write_mx(UINT8 data) { m_data->write_byte(m_xp << 8 | m_xh << 4 | m_xl, data); } - inline UINT8 read_my() { return m_data->read_byte(m_yp << 8 | m_yh << 4 | m_yl) & 0xf; } - inline void write_my(UINT8 data) { m_data->write_byte(m_yp << 8 | m_yh << 4 | m_yl, data); } - inline UINT8 read_mn() { return m_data->read_byte(m_op & 0xf) & 0xf; } - inline void write_mn(UINT8 data) { m_data->write_byte(m_op & 0xf, data); } - - inline void inc_x() { m_xl++; m_xh = (m_xh + (m_xl >> 4 & 1)) & 0xf; m_xl &= 0xf; } - inline void inc_y() { m_yl++; m_yh = (m_yh + (m_yl >> 4 & 1)) & 0xf; m_yl &= 0xf; } + // internal data memory read/write + inline UINT8 read_mx(); + inline UINT8 read_my(); + inline UINT8 read_mn(); + inline void write_mx(UINT8 data); + inline void write_my(UINT8 data); + inline void write_mn(UINT8 data); // common stack ops - inline void push(UINT8 data) { m_data->write_byte(--m_sp, data); } - inline UINT8 pop() { return m_data->read_byte(m_sp++) & 0xf; } - inline void push_pc() { push(m_pc >> 8 & 0xf); push(m_pc >> 4 & 0xf); push(m_pc & 0xf); } - inline void pop_pc() { UINT16 bank = m_pc & 0x1000; m_pc = pop(); m_pc |= pop() << 4; m_pc |= pop() << 8; m_pc |= bank; } + inline void push(UINT8 data); + inline UINT8 pop(); + inline void push_pc(); + inline void pop_pc(); + + // misc internal helpers + inline void set_cf(UINT8 data); + inline void set_zf(UINT8 data); + inline void inc_x(); + inline void inc_y(); // opcode handlers - //UINT8 op_rlc(UINT8 data); - //UINT8 op_rrc(UINT8 data); + UINT8 op_inc(UINT8 x); + UINT8 op_dec(UINT8 x); + + UINT8 op_and(UINT8 x, UINT8 y); + UINT8 op_or(UINT8 x, UINT8 y); + UINT8 op_xor(UINT8 x, UINT8 y); + + //UINT8 op_rlc(UINT8 x); + //UINT8 op_rrc(UINT8 x); }; diff --git a/src/emu/cpu/e0c6200/e0c6200op.inc b/src/emu/cpu/e0c6200/e0c6200op.inc new file mode 100644 index 00000000000..f85d0a4c2ba --- /dev/null +++ b/src/emu/cpu/e0c6200/e0c6200op.inc @@ -0,0 +1,166 @@ +// E0C6200 opcode handlers + +enum +{ + FLAG_C = 1, + FLAG_Z = 2, + FLAG_D = 4, + FLAG_I = 8 +}; + + +// internal data memory read/write + +// MX/MY + +inline UINT8 e0c6200_cpu_device::read_mx() +{ + UINT16 address = m_xp << 8 | m_xh << 4 | m_xl; + return m_data->read_byte(address) & 0xf; +} + +inline UINT8 e0c6200_cpu_device::read_my() +{ + UINT16 address = m_yp << 8 | m_yh << 4 | m_yl; + return m_data->read_byte(address) & 0xf; +} + +inline void e0c6200_cpu_device::write_mx(UINT8 data) +{ + UINT16 address = m_xp << 8 | m_xh << 4 | m_xl; + m_data->write_byte(address, data); +} + +inline void e0c6200_cpu_device::write_my(UINT8 data) +{ + UINT16 address = m_yp << 8 | m_yh << 4 | m_yl; + m_data->write_byte(address, data); +} + +// Mn(RP) + +inline UINT8 e0c6200_cpu_device::read_mn() +{ + return m_data->read_byte(m_op & 0xf) & 0xf; +} + +inline void e0c6200_cpu_device::write_mn(UINT8 data) +{ + m_data->write_byte(m_op & 0xf, data); +} + + +// common stack ops + +inline void e0c6200_cpu_device::push(UINT8 data) +{ + m_data->write_byte(--m_sp, data); +} + +inline UINT8 e0c6200_cpu_device::pop() +{ + return m_data->read_byte(m_sp++) & 0xf; +} + +inline void e0c6200_cpu_device::push_pc() +{ + // the highest bit(bank bit) is not pushed onto the stack + push(m_pc >> 8 & 0xf); + push(m_pc >> 4 & 0xf); + push(m_pc & 0xf); +} + +inline void e0c6200_cpu_device::pop_pc() +{ + // the highest bit(bank bit) is unchanged + UINT16 bank = m_pc & 0x1000; + m_pc = pop(); + m_pc |= pop() << 4; + m_pc |= pop() << 8; + m_pc |= bank; +} + + +// misc internal helpers + +inline void e0c6200_cpu_device::set_cf(UINT8 data) +{ + // set carry flag if bit 4 is set, reset otherwise + m_f = (m_f & ~FLAG_C) | ((data & 0x10) ? FLAG_C : 0); +} + +inline void e0c6200_cpu_device::set_zf(UINT8 data) +{ + // set zero flag if 4-bit data is 0, reset otherwise + m_f = (m_f & ~FLAG_Z) | ((data & 0xf) ? 0 : FLAG_Z); +} + +inline void e0c6200_cpu_device::inc_x() +{ + // increment X (XH.XL) + m_xl++; + m_xh = (m_xh + (m_xl >> 4 & 1)) & 0xf; + m_xl &= 0xf; +} + +inline void e0c6200_cpu_device::inc_y() +{ + // increment Y (YH.YL) + m_yl++; + m_yh = (m_yh + (m_yl >> 4 & 1)) & 0xf; + m_yl &= 0xf; +} + + +// common opcodes +// note: it is implied that all handled opcodes below take 7 clock cycles (5 already deducted) + +// artithmetic instructions + +UINT8 e0c6200_cpu_device::op_inc(UINT8 x) +{ + // INC x: increment x (affect flags: C, Z) + m_icount -= 2; + x++; + set_cf(x); set_zf(x); + return x & 0xf; +} + +UINT8 e0c6200_cpu_device::op_dec(UINT8 x) +{ + // DEC x: decrement x (affect flags: C, Z) + m_icount -= 2; + x--; + set_cf(x); set_zf(x); + return x & 0xf; +} + + +// logical instructions + +UINT8 e0c6200_cpu_device::op_and(UINT8 x, UINT8 y) +{ + // AND x,y: logical AND x with y (affect flags: Z) + m_icount -= 2; + x &= y; + set_zf(x); + return x; +} + +UINT8 e0c6200_cpu_device::op_or(UINT8 x, UINT8 y) +{ + // OR x,y: logical OR x with y (affect flags: Z) + m_icount -= 2; + x |= y; + set_zf(x); + return x; +} + +UINT8 e0c6200_cpu_device::op_xor(UINT8 x, UINT8 y) +{ + // XOR x,y: exclusive-OR x with y (affect flags: Z) + m_icount -= 2; + x ^= y; + set_zf(x); + return x; +}