konami cpu: corrections to EXG/TFR opcode [hap, Jim Westfall]

This commit is contained in:
hap 2025-04-02 22:32:01 +02:00
parent c6e93c06f3
commit 456d6b7619
3 changed files with 58 additions and 46 deletions

View File

@ -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"
@ -1513,11 +1518,12 @@ void konami_disassembler::indexed(std::ostream &stream, uint8_t mode, const data
void konami_disassembler::register_register(std::ostream &stream, uint8_t pb)
{
static const char konami_teregs[8] =
const char *const konami_teregs[8] =
{
'A', 'B', 'X', 'Y', 'S', 'U', '?', '?'
// B: D when reading, B when writing
"A", "B", "X", "Y", "DP", "U", "S", "PC"
};
util::stream_format(stream, "%c,%c",
util::stream_format(stream, "%s,%s",
konami_teregs[(pb >> 0) & 0x7],
konami_teregs[(pb >> 4) & 0x7]);
}

View File

@ -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;
}
}
@ -208,11 +211,13 @@ 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 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: result = m_s.w; break; // S
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;
@ -231,8 +236,10 @@ inline void konami_cpu_device::write_exgtfr_register(uint8_t reg, uint16_t value
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 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
}
}

View File

@ -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;