mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
dsp16: Additional work (nw).
I'll do a full writeup when the whatsnew.txt comes out.
This commit is contained in:
parent
b41802d6ce
commit
cef23d614c
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user