From 456d6b7619624b210f496d4b90e9e70414a119eb Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 2 Apr 2025 22:32:01 +0200 Subject: [PATCH] konami cpu: corrections to EXG/TFR opcode [hap, Jim Westfall] --- src/devices/cpu/m6809/6x09dasm.cpp | 30 ++++++++++++--------- src/devices/cpu/m6809/konami.cpp | 43 +++++++++++++++++------------- src/devices/cpu/m6809/konami.lst | 31 +++++++++++---------- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/devices/cpu/m6809/6x09dasm.cpp b/src/devices/cpu/m6809/6x09dasm.cpp index 55911016942..d41c9bc00b7 100644 --- a/src/devices/cpu/m6809/6x09dasm.cpp +++ b/src/devices/cpu/m6809/6x09dasm.cpp @@ -16,6 +16,11 @@ Thanks to Franklin Bowen for bug fixes, ideas + TODO: + - KONAMI EXG/TFR isn't disassembled accurately: + 0x3E/0x3F + param bit 7 clear = EXG + 0x3E/0x3F + param bit 7 set = TFR + *****************************************************************************/ #include "emu.h" @@ -27,7 +32,7 @@ const char *const m6x09_base_disassembler::m6x09_regs[5] = { "X", "Y", "U", "S", const char *const m6x09_base_disassembler::m6x09_btwregs[5] = { "CC", "A", "B", "inv" }; const char *const m6x09_base_disassembler::hd6309_tfmregs[16] = { - "D", "X", "Y", "U", "S", "inv", "inv", "inv", + "D", "X", "Y", "U", "S", "inv", "inv", "inv", "inv", "inv", "inv", "inv", "inv", "inv", "inv", "inv" }; @@ -50,7 +55,7 @@ m6x09_base_disassembler::m6x09_base_disassembler(const opcodeinfo *opcodes, size : m_level(level), m_page(0) { // create filtered opcode table - for (int i=0; i> 0) & 0x7], konami_teregs[(pb >> 4) & 0x7]); } diff --git a/src/devices/cpu/m6809/konami.cpp b/src/devices/cpu/m6809/konami.cpp index 19eed8e8bc0..aeba236e2e9 100644 --- a/src/devices/cpu/m6809/konami.cpp +++ b/src/devices/cpu/m6809/konami.cpp @@ -10,6 +10,9 @@ TODO: - verify cycle timing - verify status flag handling + - EXG/TFR DP: DP here is apparently part of a 16-bit register. DP is + the high byte, and the low byte is an unknown hidden register? It + doesn't look like any game uses this. See MAME issue #13544. References: @@ -184,15 +187,15 @@ inline uint16_t &konami_cpu_device::ireg() { switch(m_opcode & 0x70) { - case 0x20: return m_x.w; - case 0x30: return m_y.w; - case 0x50: return m_u.w; - case 0x60: return m_s.w; - case 0x70: return m_pc.w; + case 0x20: return m_x.w; // X + case 0x30: return m_y.w; // Y + case 0x50: return m_u.w; // U + case 0x60: return m_s.w; // S + case 0x70: return m_pc.w; // PC + default: fatalerror("Should not get here"); // never executed - //return m_x.w; } } @@ -207,12 +210,14 @@ inline uint16_t konami_cpu_device::read_exgtfr_register(uint8_t reg) switch(reg & 0x07) { - case 0: result = m_q.r.a; break; // A - case 1: result = m_q.r.b; break; // B - case 2: result = m_x.w; break; // X - case 3: result = m_y.w; break; // Y - case 4: result = m_s.w; break; // S - case 5: result = m_u.w; break; // U + case 0: result = m_q.r.a; break; // A + case 1: result = m_q.r.d; break; // D + case 2: result = m_x.w; break; // X + case 3: result = m_y.w; break; // Y + case 4: logerror("EXG/TFR unemulated DP reg\n"); break; // DP + case 5: result = m_u.w; break; // U + case 6: result = m_s.w; break; // S + case 7: result = m_pc.w; break; // PC } return result; @@ -227,12 +232,14 @@ inline void konami_cpu_device::write_exgtfr_register(uint8_t reg, uint16_t value { switch(reg & 0x07) { - case 0: m_q.r.a = value; break; // A - case 1: m_q.r.b = value; break; // B - case 2: m_x.w = value; break; // X - case 3: m_y.w = value; break; // Y - case 4: m_s.w = value; break; // S - case 5: m_u.w = value; break; // U + case 0: m_q.r.a = value; break; // A + case 1: m_q.r.b = value; break; // B + case 2: m_x.w = value; break; // X + case 3: m_y.w = value; break; // Y + case 4: logerror("EXG/TFR unemulated DP reg\n"); break; // DP + case 5: m_u.w = value; break; // U + case 6: m_s.w = value; break; // S + case 7: m_pc.w = value; break; // PC } } diff --git a/src/devices/cpu/m6809/konami.lst b/src/devices/cpu/m6809/konami.lst index 5f8f8a81102..3dee835611f 100644 --- a/src/devices/cpu/m6809/konami.lst +++ b/src/devices/cpu/m6809/konami.lst @@ -76,8 +76,7 @@ MAIN: case 0x3B: set_regop8(m_q.r.b); %INDEXED; %ST8; return; case 0x3C: set_imm(); %ANDCC; return; case 0x3D: set_imm(); %ORCC; return; - case 0x3E: %EXG; return; - case 0x3F: %TFR; return; + case 0x3E: case 0x3F: %EXGTFR; return; case 0x40: set_regop16(m_q.p.d); set_imm(); %LD16; return; case 0x41: set_regop16(m_q.p.d); %INDEXED; %LD16; return; @@ -434,24 +433,24 @@ INDEXED: set_ea(m_temp.w); return; -EXG: +EXGTFR: { - // konami's EXG instruction differs enough from 6809 to fork the code - uint8_t param = read_opcode_arg(); - uint16_t reg1 = read_exgtfr_register(param >> 0); - uint16_t reg2 = read_exgtfr_register(param >> 4); - write_exgtfr_register(param >> 0, reg2); - write_exgtfr_register(param >> 4, reg1); - } - eat(3); - return; - -TFR: - { - // konami's TFR instruction differs enough from 6809 to fork the code + // konami's EXG/TFR instruction differs enough from HD6309 to fork the code uint8_t param = read_opcode_arg(); uint16_t reg = read_exgtfr_register(param >> 0); + + // Opcodes 0x3E and 0x3F are the same! The bit that distinguishes between EXG and TFR + // is actually opcode_arg bit 7. Although Konami software behaves as expected. + if (!BIT(param, 7)) + { + uint16_t reg2 = read_exgtfr_register(param >> 4); + write_exgtfr_register(param >> 0, reg2); + eat(1); + } write_exgtfr_register(param >> 4, reg); + + //if (BIT(m_opcode, 0) != BIT(param, 7)) + // logerror("KONAMI: Malformed EXG/TFR opcode\n"); } eat(2); return;