mirror of
https://github.com/holub/mame
synced 2025-04-09 18:17:44 +03:00
konami cpu: corrections to EXG/TFR opcode [hap, Jim Westfall]
This commit is contained in:
parent
c6e93c06f3
commit
456d6b7619
@ -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<opcode_count; i++)
|
||||
for (int i = 0; i < opcode_count; i++)
|
||||
{
|
||||
if (opcodes[i].level() & level)
|
||||
{
|
||||
@ -1242,7 +1247,7 @@ const m6x09_base_disassembler::opcodeinfo konami_disassembler::konami_opcodes[]
|
||||
{ 0x8C, 0, "DECA", INH, M6x09_GENERAL },
|
||||
{ 0x8D, 0, "DECB", INH, M6x09_GENERAL },
|
||||
{ 0x8E, 1, "DEC", IND, M6x09_GENERAL },
|
||||
{ 0x8F, 0, "RTS", INH , M6x09_GENERAL, STEP_OUT },
|
||||
{ 0x8F, 0, "RTS", INH, M6x09_GENERAL, STEP_OUT },
|
||||
|
||||
{ 0x90, 0, "TSTA", INH, M6x09_GENERAL },
|
||||
{ 0x91, 0, "TSTB", INH, M6x09_GENERAL },
|
||||
@ -1259,7 +1264,7 @@ const m6x09_base_disassembler::opcodeinfo konami_disassembler::konami_opcodes[]
|
||||
{ 0x9C, 0, "ASLA", INH, M6x09_GENERAL },
|
||||
{ 0x9D, 0, "ASLB", INH, M6x09_GENERAL },
|
||||
{ 0x9E, 1, "ASL", IND, M6x09_GENERAL },
|
||||
{ 0x9F, 0, "RTI", INH , M6x09_GENERAL, STEP_OUT },
|
||||
{ 0x9F, 0, "RTI", INH, M6x09_GENERAL, STEP_OUT },
|
||||
|
||||
{ 0xA0, 0, "ROLA", INH, M6x09_GENERAL },
|
||||
{ 0xA1, 0, "ROLB", INH, M6x09_GENERAL },
|
||||
@ -1281,10 +1286,10 @@ const m6x09_base_disassembler::opcodeinfo konami_disassembler::konami_opcodes[]
|
||||
{ 0xB1, 0, "DAA", INH, M6x09_GENERAL },
|
||||
{ 0xB2, 0, "SEX", INH, M6x09_GENERAL },
|
||||
{ 0xB3, 0, "MUL", INH, M6x09_GENERAL },
|
||||
{ 0xB4, 0, "LMUL", INH, M6x09_GENERAL },
|
||||
{ 0xB5, 0, "DIV X,B", INH, M6x09_GENERAL },
|
||||
{ 0xB4, 0, "LMUL", INH, M6x09_GENERAL },
|
||||
{ 0xB5, 0, "DIV X,B", INH, M6x09_GENERAL },
|
||||
{ 0xB6, 0, "BMOVE Y,X,U", INH, M6x09_GENERAL },
|
||||
{ 0xB7, 0, "MOVE Y,X,U", INH, M6x09_GENERAL },
|
||||
{ 0xB7, 0, "MOVE Y,X,U", INH, M6x09_GENERAL },
|
||||
{ 0xB8, 1, "LSRD", IMM, M6x09_GENERAL },
|
||||
{ 0xB9, 1, "LSRD", IND, M6x09_GENERAL },
|
||||
{ 0xBA, 1, "RORD", IMM, M6x09_GENERAL },
|
||||
@ -1309,9 +1314,9 @@ const m6x09_base_disassembler::opcodeinfo konami_disassembler::konami_opcodes[]
|
||||
{ 0xCC, 0, "ABSA", INH, M6x09_GENERAL },
|
||||
{ 0xCD, 0, "ABSB", INH, M6x09_GENERAL },
|
||||
{ 0xCE, 0, "ABSD", INH, M6x09_GENERAL },
|
||||
{ 0xCF, 0, "BSET A,X,U", INH, M6x09_GENERAL },
|
||||
{ 0xCF, 0, "BSET A,X,U", INH, M6x09_GENERAL },
|
||||
|
||||
{ 0xD0, 0, "BSET D,X,U", INH, M6x09_GENERAL }
|
||||
{ 0xD0, 0, "BSET D,X,U", INH, M6x09_GENERAL }
|
||||
};
|
||||
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user