diff --git a/src/emu/cpu/dsp16/dsp16.c b/src/emu/cpu/dsp16/dsp16.c index 6917717d423..e082c81f8a0 100644 --- a/src/emu/cpu/dsp16/dsp16.c +++ b/src/emu/cpu/dsp16/dsp16.c @@ -10,6 +10,11 @@ #include "debugger.h" #include "dsp16.h" +// +// TODO: +// * Store the cache in 15 unique memory locations as it is on-chip. +// * Modify cycle counts when running from within the cache +// //************************************************************************** // DEVICE INTERFACE @@ -52,6 +57,10 @@ dsp16_device::dsp16_device(const machine_config &mconfig, const char *tag, devic m_sioc(0), m_pioc(0), m_ppc(0), + m_cacheStart(CACHE_INVALID), + m_cacheEnd(CACHE_INVALID), + m_cacheRedoNextPC(CACHE_INVALID), + m_cacheIterations(0), m_program(NULL), m_direct(NULL), m_icount(0) @@ -69,6 +78,7 @@ void dsp16_device::device_start() { // register state with the debugger state_add(STATE_GENPC, "GENPC", m_pc).noshow(); + //state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_psw).callimport().callexport().formatstr("%10s").noshow(); state_add(DSP16_PC, "PC", m_pc); state_add(DSP16_I, "I", m_i); @@ -96,6 +106,7 @@ void dsp16_device::device_start() state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%16s"); state_add(DSP16_PIOC, "PIOC", m_pioc); //.formatstr("%16s"); + // register our state for saving save_item(NAME(m_i)); save_item(NAME(m_pc)); save_item(NAME(m_pt)); @@ -121,6 +132,11 @@ void dsp16_device::device_start() save_item(NAME(m_c2)); save_item(NAME(m_sioc)); save_item(NAME(m_pioc)); + save_item(NAME(m_ppc)); + save_item(NAME(m_cacheStart)); + save_item(NAME(m_cacheEnd)); + save_item(NAME(m_cacheRedoNextPC)); + save_item(NAME(m_cacheIterations)); // get our address spaces m_program = &space(AS_PROGRAM); @@ -145,6 +161,12 @@ void dsp16_device::device_reset() m_re = 0x0000; // AUC is not affected by reset m_ppc = m_pc; + + // Hacky cache emulation. + m_cacheStart = CACHE_INVALID; + m_cacheEnd = CACHE_INVALID; + m_cacheRedoNextPC = CACHE_INVALID; + m_cacheIterations = 0; } @@ -170,7 +192,7 @@ void dsp16_device::state_string_export(const device_state_entry &entry, astring switch (entry.index()) { case STATE_GENFLAGS: - string.printf("(multiple below)"); + string.printf("(below)"); break; // Placeholder for a better view later (TODO) @@ -290,11 +312,13 @@ void dsp16_device::execute_run() // instruction fetch & execute UINT8 cycles; - UINT8 pcAdvance; + INT16 pcAdvance; const UINT16 op = opcode_read(); + printf("%d ", m_cacheIterations); execute_one(op, cycles, pcAdvance); + printf("%d\n", m_cacheIterations); - // step forward + // step m_pc += pcAdvance; m_icount -= cycles; diff --git a/src/emu/cpu/dsp16/dsp16.h b/src/emu/cpu/dsp16/dsp16.h index 9ce0f773049..ed69aff5b99 100644 --- a/src/emu/cpu/dsp16/dsp16.h +++ b/src/emu/cpu/dsp16/dsp16.h @@ -12,15 +12,6 @@ #define __DSP16_H__ -//************************************************************************** -// INTERFACE CONFIGURATION MACROS -//************************************************************************** - -//#define MCFG_DSP16_CONFIG(_config) -// dsp16_device::static_set_config(*device, _config); - - - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -95,6 +86,14 @@ protected: // internal stuff UINT16 m_ppc; + // This core handles the cache as more of a loop than 15 seperate memory elements. + // It's a bit of a hack, but it's easier this way. + UINT16 m_cacheStart; + UINT16 m_cacheEnd; + UINT16 m_cacheRedoNextPC; + UINT16 m_cacheIterations; + static const UINT16 CACHE_INVALID = 0xffff; + // memory access inline UINT32 program_read(UINT32 addr); inline void program_write(UINT32 addr, UINT32 data); @@ -108,13 +107,14 @@ protected: int m_icount; // operations - void execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance); + void execute_one(const UINT16& op, UINT8& cycles, INT16& pcAdvance); + // table decoders + void* registerFromRImmediateField(const UINT8& R); void* registerFromRTable(const UINT8& R); // helpers void* addressYL(); - //void writeYxRegister(const UINT16& value); void writeRegister(void* reg, const UINT16& value); }; diff --git a/src/emu/cpu/dsp16/dsp16dis.c b/src/emu/cpu/dsp16/dsp16dis.c index 9ba01683ac6..819c90eaa25 100644 --- a/src/emu/cpu/dsp16/dsp16dis.c +++ b/src/emu/cpu/dsp16/dsp16dis.c @@ -523,7 +523,7 @@ CPU_DISASSEMBLE( dsp16a ) // R = N const UINT8 R = (op & 0x03f0) >> 4; astring rString = disasmRField(R); - sprintf(buffer, "%s = 0x%x", rString.cstr(), op2); + sprintf(buffer, "%s = 0x%04x", rString.cstr(), op2); opSize = 2; break; } diff --git a/src/emu/cpu/dsp16/dsp16ops.c b/src/emu/cpu/dsp16/dsp16ops.c index c0400cd13bd..88962fcc873 100644 --- a/src/emu/cpu/dsp16/dsp16ops.c +++ b/src/emu/cpu/dsp16/dsp16ops.c @@ -10,30 +10,60 @@ void* dsp16_device::addressYL() void dsp16_device::writeRegister(void* reg, const UINT16 &value) { + // Make sure you're not attempting to write somewhere this function doesn't support. + if (reg == &m_p || reg == &m_a0 || reg == &m_a1) + { + logerror("dsp16::writeRegister called on invalid register at PC 0x%04x.\n", m_pc); + return; + } + if (reg == &m_auc || reg == &m_c0 || reg == &m_c1 || reg == &m_c2) { - *(UINT8*)reg = value & 0x00ff; // 8 bit registers + // 8 bit registers + *(UINT8*)reg = value & 0x00ff; } else if (reg == &m_i) { - m_i = value & 0x0fff; // 12 bit register + // 12 bit register + m_i = value & 0x0fff; } else if (reg == &m_y) { - //writeYxRegister(value); // TODO - check a flag to see if clearing yl is necessary - m_y = (value << 16) | (m_y & 0x0000ffff); // Temporary + // Y register [[TODO - check a flag to see if clearing yl is necessary]] + m_y = (value << 16) | (m_y & 0x0000ffff); } else if (reg == addressYL()) { - m_y = value | (m_y & 0xffff0000); // Temporary + // Yl register + m_y = value | (m_y & 0xffff0000); } else { - *(UINT16*)reg = value; // The rest + // Everything else + *(UINT16*)reg = value; } } +void* dsp16_device::registerFromRImmediateField(const UINT8& R) +{ + switch (R) + { + case 0x00: return (void*)&m_j; + case 0x01: return (void*)&m_k; + case 0x02: return (void*)&m_rb; + case 0x03: return (void*)&m_re; + case 0x04: return (void*)&m_r0; + case 0x05: return (void*)&m_r1; + case 0x06: return (void*)&m_r2; + case 0x07: return (void*)&m_r3; + + default: return NULL; + } + return NULL; +} + + void* dsp16_device::registerFromRTable(const UINT8 &R) { switch (R) @@ -73,7 +103,7 @@ void* dsp16_device::registerFromRTable(const UINT8 &R) } -void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance) +void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, INT16& pcAdvance) { cycles = 1; pcAdvance = 1; @@ -286,7 +316,6 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance const UINT16 iVal = opcode_read(1); void* reg = registerFromRTable(R); writeRegister(reg, iVal); - cycles = 2; pcAdvance = 2; break; @@ -296,8 +325,11 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance case 0x02: case 0x03: { // R = M - //const UINT8 M = (op & 0x00ff); - //const UINT8 R = (op & 0x0e00) >> 9; + const INT8 M = (op & 0x00ff); + const UINT8 R = (op & 0x0e00) >> 9; + void* reg = registerFromRImmediateField(R); + writeRegister(reg, (INT16)M); // Sign extend 8 bit int + cycles = 1; break; } @@ -305,8 +337,24 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance case 0x0e: { // do|redo K - //const UINT8 K = (op & 0x007f); - //const UINT8 NI = (op & 0x0780) >> 7; + const UINT8 K = (op & 0x007f); + const UINT8 NI = (op & 0x0780) >> 7; + if (NI != 0) + { + // Do + m_cacheStart = m_pc + 1; + m_cacheEnd = m_pc + NI + 1; + m_cacheIterations = K+1; + cycles = 1; + } + else + { + // Redo + m_cacheIterations = K+1; + m_cacheRedoNextPC = m_pc + 1; + pcAdvance = m_cacheStart - m_pc; + cycles = 2; + } break; } @@ -322,4 +370,18 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance break; } } + + // Handle end-of-cache conditions for do|redos + if (m_cacheIterations == 0 && m_cacheRedoNextPC != CACHE_INVALID) + { + // You've reached the end of a cache loop after a redo opcode. + pcAdvance = m_cacheRedoNextPC - m_pc; + m_cacheRedoNextPC = CACHE_INVALID; + } + if (m_cacheIterations > 0 && (m_pc+pcAdvance == m_cacheEnd)) + { + // A regular iteration on a cached loop. + m_cacheIterations--; + pcAdvance = m_cacheStart - m_pc; + } }