mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
dsp56k.c: Modernised cpu core (nw)
This commit is contained in:
parent
ad52cefa2e
commit
f11344542e
@ -39,12 +39,6 @@
|
||||
|
||||
using namespace DSP56K;
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
static CPU_RESET( dsp56k );
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
COMPONENT FUNCTIONALITY
|
||||
***************************************************************************/
|
||||
@ -64,326 +58,6 @@ static CPU_RESET( dsp56k );
|
||||
#include "dsp56mem.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Direct Update Handler
|
||||
***************************************************************************/
|
||||
DIRECT_UPDATE_MEMBER( dsp56k_device::dsp56k_direct_handler )
|
||||
{
|
||||
if (address <= (0x07ff<<1))
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(&direct.space().device());
|
||||
direct.explicit_configure(0x0000<<1, 0x07ff<<1, (0x07ff<<1) | 1, cpustate->program_ram);
|
||||
return ~0;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MEMORY ACCESSORS
|
||||
***************************************************************************/
|
||||
#define ROPCODE(pc) cpustate->direct->read_decrypted_word(pc)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
IRQ HANDLING
|
||||
***************************************************************************/
|
||||
static void set_irq_line(dsp56k_core* cpustate, int irqline, int state)
|
||||
{
|
||||
//logerror("DSP56k set irq line %d %d\n", irqline, state);
|
||||
|
||||
switch(irqline)
|
||||
{
|
||||
case DSP56K_IRQ_MODA:
|
||||
// TODO: 1-12 Get this triggering right
|
||||
if (irqa_trigger(cpustate))
|
||||
logerror("DSP56k IRQA is set to fire on the \"Negative Edge\".\n");
|
||||
|
||||
if (state != CLEAR_LINE)
|
||||
cpustate->modA_state = TRUE;
|
||||
else
|
||||
cpustate->modA_state = FALSE;
|
||||
|
||||
if (cpustate->reset_state != TRUE)
|
||||
dsp56k_add_pending_interrupt(cpustate, "IRQA");
|
||||
break;
|
||||
|
||||
case DSP56K_IRQ_MODB:
|
||||
// TODO: 1-12 Get this triggering right
|
||||
if (irqb_trigger(cpustate))
|
||||
logerror("DSP56k IRQB is set to fire on the \"Negative Edge\".\n");
|
||||
|
||||
if (state != CLEAR_LINE)
|
||||
cpustate->modB_state = TRUE;
|
||||
else
|
||||
cpustate->modB_state = FALSE;
|
||||
|
||||
if (cpustate->reset_state != TRUE)
|
||||
dsp56k_add_pending_interrupt(cpustate, "IRQB");
|
||||
break;
|
||||
|
||||
case DSP56K_IRQ_MODC:
|
||||
if (state != CLEAR_LINE)
|
||||
cpustate->modC_state = TRUE;
|
||||
else
|
||||
cpustate->modC_state = FALSE;
|
||||
|
||||
// TODO : Set bus mode or whatever
|
||||
break;
|
||||
|
||||
case DSP56K_IRQ_RESET:
|
||||
if (state != CLEAR_LINE)
|
||||
cpustate->reset_state = TRUE;
|
||||
else
|
||||
{
|
||||
/* If it changes state from asserted to cleared. Call the reset function. */
|
||||
if (cpustate->reset_state == TRUE)
|
||||
CPU_RESET_NAME(dsp56k)(cpustate->device);
|
||||
|
||||
cpustate->reset_state = FALSE;
|
||||
}
|
||||
|
||||
// dsp56k_add_pending_interrupt("Hardware RESET");
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("DSP56k setting some weird irq line : %d", irqline);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the reset line isn't asserted, service interrupts */
|
||||
// TODO: Is it right to immediately service interrupts?
|
||||
//if (cpustate->reset_state != TRUE)
|
||||
// pcu_service_interrupts();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
INITIALIZATION AND SHUTDOWN
|
||||
***************************************************************************/
|
||||
static void agu_init(dsp56k_core* cpustate, device_t *device)
|
||||
{
|
||||
/* save states - dsp56k_agu members */
|
||||
device->save_item(NAME(cpustate->AGU.r0));
|
||||
device->save_item(NAME(cpustate->AGU.r1));
|
||||
device->save_item(NAME(cpustate->AGU.r2));
|
||||
device->save_item(NAME(cpustate->AGU.r3));
|
||||
device->save_item(NAME(cpustate->AGU.n0));
|
||||
device->save_item(NAME(cpustate->AGU.n1));
|
||||
device->save_item(NAME(cpustate->AGU.n2));
|
||||
device->save_item(NAME(cpustate->AGU.n3));
|
||||
device->save_item(NAME(cpustate->AGU.m0));
|
||||
device->save_item(NAME(cpustate->AGU.m1));
|
||||
device->save_item(NAME(cpustate->AGU.m2));
|
||||
device->save_item(NAME(cpustate->AGU.m3));
|
||||
device->save_item(NAME(cpustate->AGU.temp));
|
||||
}
|
||||
|
||||
static void alu_init(dsp56k_core* cpustate, device_t *device)
|
||||
{
|
||||
/* save states - dsp56k_alu members */
|
||||
device->save_item(NAME(cpustate->ALU.x));
|
||||
device->save_item(NAME(cpustate->ALU.y));
|
||||
device->save_item(NAME(cpustate->ALU.a));
|
||||
device->save_item(NAME(cpustate->ALU.b));
|
||||
}
|
||||
|
||||
static CPU_INIT( dsp56k )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
|
||||
/* Call specific module inits */
|
||||
pcu_init(cpustate, device);
|
||||
agu_init(cpustate, device);
|
||||
alu_init(cpustate, device);
|
||||
|
||||
/* HACK - You're not in bootstrap mode upon bootup */
|
||||
cpustate->bootstrap_mode = BOOTSTRAP_OFF;
|
||||
|
||||
/* Clear the irq states */
|
||||
cpustate->modA_state = FALSE;
|
||||
cpustate->modB_state = FALSE;
|
||||
cpustate->modC_state = FALSE;
|
||||
cpustate->reset_state = FALSE;
|
||||
|
||||
/* save states - dsp56k_core members */
|
||||
device->save_item(NAME(cpustate->modA_state));
|
||||
device->save_item(NAME(cpustate->modB_state));
|
||||
device->save_item(NAME(cpustate->modC_state));
|
||||
device->save_item(NAME(cpustate->reset_state));
|
||||
device->save_item(NAME(cpustate->bootstrap_mode));
|
||||
device->save_item(NAME(cpustate->repFlag));
|
||||
device->save_item(NAME(cpustate->repAddr));
|
||||
device->save_item(NAME(cpustate->ppc));
|
||||
device->save_item(NAME(cpustate->op));
|
||||
device->save_item(NAME(cpustate->interrupt_cycles));
|
||||
|
||||
/* save states - dsp56k_host_interface members */
|
||||
device->save_item(NAME(cpustate->HI.icr));
|
||||
device->save_item(NAME(cpustate->HI.cvr));
|
||||
device->save_item(NAME(cpustate->HI.isr));
|
||||
device->save_item(NAME(cpustate->HI.ivr));
|
||||
device->save_item(NAME(cpustate->HI.trxh));
|
||||
device->save_item(NAME(cpustate->HI.trxl));
|
||||
device->save_item(NAME(cpustate->HI.bootstrap_offset));
|
||||
|
||||
device->save_item(NAME(cpustate->peripheral_ram));
|
||||
device->save_item(NAME(cpustate->program_ram));
|
||||
|
||||
//cpustate->config = device->static_config();
|
||||
//cpustate->irq_callback = irqcallback;
|
||||
cpustate->device = device;
|
||||
cpustate->program = &device->space(AS_PROGRAM);
|
||||
cpustate->direct = &cpustate->program->direct();
|
||||
cpustate->data = &device->space(AS_DATA);
|
||||
|
||||
/* Setup the direct memory handler for this CPU */
|
||||
/* NOTE: Be sure to grab this guy and call him if you ever install another direct_update_hander in a driver! */
|
||||
cpustate->program->set_direct_update_handler(direct_update_delegate(FUNC(dsp56k_device::dsp56k_direct_handler), (dsp56k_device*)device));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
RESET BEHAVIOR
|
||||
***************************************************************************/
|
||||
static void agu_reset(dsp56k_core* cpustate)
|
||||
{
|
||||
/* FM.4-3 */
|
||||
R0 = 0x0000;
|
||||
R1 = 0x0000;
|
||||
R2 = 0x0000;
|
||||
R3 = 0x0000;
|
||||
|
||||
N0 = 0x0000;
|
||||
N1 = 0x0000;
|
||||
N2 = 0x0000;
|
||||
N3 = 0x0000;
|
||||
|
||||
M0 = 0xffff;
|
||||
M1 = 0xffff;
|
||||
M2 = 0xffff;
|
||||
M3 = 0xffff;
|
||||
|
||||
TEMP = 0x0000;
|
||||
}
|
||||
|
||||
static void alu_reset(dsp56k_core* cpustate)
|
||||
{
|
||||
X = 0x00000000;
|
||||
Y = 0x00000000;
|
||||
A = 0x0000000000;
|
||||
B = 0x0000000000;
|
||||
}
|
||||
|
||||
static CPU_RESET( dsp56k )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
logerror("Dsp56k reset\n");
|
||||
|
||||
cpustate->interrupt_cycles = 0;
|
||||
cpustate->ppc = 0x0000;
|
||||
|
||||
cpustate->repFlag = 0;
|
||||
cpustate->repAddr = 0x0000;
|
||||
|
||||
pcu_reset(cpustate);
|
||||
mem_reset(cpustate);
|
||||
agu_reset(cpustate);
|
||||
alu_reset(cpustate);
|
||||
|
||||
/* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */
|
||||
cpustate->program->write_word(0x0000, 0x0124);
|
||||
}
|
||||
|
||||
|
||||
static CPU_EXIT( dsp56k )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CORE INCLUDE
|
||||
***************************************************************************/
|
||||
#include "dsp56ops.inc"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CORE EXECUTION LOOP
|
||||
***************************************************************************/
|
||||
// Execute a single opcode and return how many cycles it took.
|
||||
static size_t execute_one_new(dsp56k_core* cpustate)
|
||||
{
|
||||
// For MAME
|
||||
cpustate->op = ROPCODE(ADDRESS(PC));
|
||||
debugger_instruction_hook(cpustate->device, PC);
|
||||
|
||||
UINT16 w0 = ROPCODE(ADDRESS(PC));
|
||||
UINT16 w1 = ROPCODE(ADDRESS(PC) + ADDRESS(1));
|
||||
|
||||
Opcode op(w0, w1);
|
||||
op.evaluate(cpustate);
|
||||
PC += op.evalSize(); // Special size function needed to handle jmps, etc.
|
||||
|
||||
// TODO: Currently all operations take up 4 cycles (inst->cycles()).
|
||||
return 4;
|
||||
}
|
||||
|
||||
static CPU_EXECUTE( dsp56k )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
|
||||
/* If reset line is asserted, do nothing */
|
||||
if (cpustate->reset_state)
|
||||
{
|
||||
cpustate->icount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */
|
||||
if (cpustate->bootstrap_mode != BOOTSTRAP_OFF)
|
||||
{
|
||||
cpustate->icount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//cpustate->icount -= cpustate->interrupt_cycles;
|
||||
//cpustate->interrupt_cycles = 0;
|
||||
|
||||
while(cpustate->icount > 0)
|
||||
{
|
||||
execute_one(cpustate);
|
||||
if (0) cpustate->icount -= execute_one_new(cpustate);
|
||||
pcu_service_interrupts(cpustate); // TODO: Is it incorrect to service after each instruction?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DISASSEMBLY HOOK
|
||||
***************************************************************************/
|
||||
extern CPU_DISASSEMBLE( dsp56k );
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Internal Memory Maps
|
||||
****************************************************************************/
|
||||
static ADDRESS_MAP_START( dsp56156_program_map, AS_PROGRAM, 16, dsp56k_device )
|
||||
AM_RANGE(0x0000,0x07ff) AM_READWRITE(program_r, program_w) /* 1-5 */
|
||||
// AM_RANGE(0x2f00,0x2fff) AM_ROM /* 1-5 PROM reserved memory. Is this the right spot for it? */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( dsp56156_x_data_map, AS_DATA, 16, dsp56k_device )
|
||||
AM_RANGE(0x0000,0x07ff) AM_RAM /* 1-5 */
|
||||
AM_RANGE(0xffc0,0xffff) AM_READWRITE(peripheral_register_r, peripheral_register_w) /* 1-5 On-chip peripheral registers memory mapped in data space */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Generic set_info/get_info
|
||||
**************************************************************************/
|
||||
enum
|
||||
{
|
||||
// PCU
|
||||
@ -424,190 +98,273 @@ enum
|
||||
DSP56K_ST15
|
||||
};
|
||||
|
||||
static CPU_SET_INFO( dsp56k )
|
||||
|
||||
const device_type DSP56156 = &device_creator<dsp56k_device>;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Internal Memory Maps
|
||||
****************************************************************************/
|
||||
static ADDRESS_MAP_START( dsp56156_program_map, AS_PROGRAM, 16, dsp56k_device )
|
||||
AM_RANGE(0x0000,0x07ff) AM_READWRITE(program_r, program_w) /* 1-5 */
|
||||
// AM_RANGE(0x2f00,0x2fff) AM_ROM /* 1-5 PROM reserved memory. Is this the right spot for it? */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( dsp56156_x_data_map, AS_DATA, 16, dsp56k_device )
|
||||
AM_RANGE(0x0000,0x07ff) AM_RAM /* 1-5 */
|
||||
AM_RANGE(0xffc0,0xffff) AM_READWRITE(peripheral_register_r, peripheral_register_w) /* 1-5 On-chip peripheral registers memory mapped in data space */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
dsp56k_device::dsp56k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: cpu_device(mconfig, DSP56156, "DSP56156", tag, owner, clock, "dsp56156", __FILE__)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1, ADDRESS_MAP_NAME(dsp56156_program_map))
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 16, 16, -1, ADDRESS_MAP_NAME(dsp56156_x_data_map))
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODA: set_irq_line(cpustate, DSP56K_IRQ_MODA, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODB: set_irq_line(cpustate, DSP56K_IRQ_MODB, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODC: set_irq_line(cpustate, DSP56K_IRQ_MODC, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_RESET: set_irq_line(cpustate, DSP56K_IRQ_RESET, info->i); break;
|
||||
|
||||
case CPUINFO_INT_PC:
|
||||
case CPUINFO_INT_REGISTER + DSP56K_PC: PC = info->i & 0xffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_SR: SR = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_LC: LC = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_LA: LA = info->i & 0xffff; break;
|
||||
|
||||
case CPUINFO_INT_SP:
|
||||
case CPUINFO_INT_REGISTER + DSP56K_SP: SP = info->i & 0xff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_OMR: OMR = info->i & 0xff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_X: X = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_Y: Y = info->i & 0xffffffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_A: A = info->i & (UINT64)U64(0xffffffffffffffff); break; /* could benefit from a better mask? */
|
||||
case CPUINFO_INT_REGISTER + DSP56K_B: B = info->i & (UINT64)U64(0xffffffffffffffff); break; /* could benefit from a better mask? */
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R0: R0 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R1: R1 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R2: R2 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R3: R3 = info->i & 0xffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N0: N0 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N1: N1 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N2: N2 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N3: N3 = info->i & 0xffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M0: M0 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M1: M1 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M2: M2 = info->i & 0xffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M3: M3 = info->i & 0xffff; break;
|
||||
|
||||
/* case CPUINFO_INT_REGISTER + DSP56K_TEMP: TEMP = info->i & 0xffff; break; */
|
||||
/* case CPUINFO_INT_REGISTER + DSP56K_STATUS: STATUS = info->i & 0xff; break; */
|
||||
|
||||
/* The CPU stack */
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST0: ST0 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST1: ST1 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST2: ST2 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST3: ST3 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST4: ST4 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST5: ST5 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST6: ST6 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST7: ST7 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST8: ST8 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST9: ST9 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST10: ST10 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST11: ST11 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST12: ST12 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST13: ST13 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST14: ST14 = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST15: ST15 = info->i & 0xffffffff; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CPU_GET_INFO( dsp56k )
|
||||
/***************************************************************************
|
||||
Direct Update Handler
|
||||
***************************************************************************/
|
||||
DIRECT_UPDATE_MEMBER( dsp56k_device::dsp56k_direct_handler )
|
||||
{
|
||||
dsp56k_core* cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
|
||||
|
||||
switch (state)
|
||||
if (address <= (0x07ff<<1))
|
||||
{
|
||||
/* --- the following bits of info are returned as 64-bit signed integers --- */
|
||||
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(dsp56k_core); break;
|
||||
case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
|
||||
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x0000; break;
|
||||
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
|
||||
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
|
||||
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
|
||||
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
|
||||
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
|
||||
case CPUINFO_INT_MIN_CYCLES: info->i = 1; // ? break;
|
||||
case CPUINFO_INT_MAX_CYCLES: info->i = 8; // ? break;
|
||||
direct.explicit_configure(0x0000<<1, 0x07ff<<1, (0x07ff<<1) | 1, m_dsp56k_core.program_ram);
|
||||
return ~0;
|
||||
}
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -1; break;
|
||||
case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = -1; break;
|
||||
case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
|
||||
return address;
|
||||
}
|
||||
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODA: info->i = DSP56K_IRQ_MODA; break;
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODB: info->i = DSP56K_IRQ_MODB; break;
|
||||
case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODC: info->i = DSP56K_IRQ_MODC; break;
|
||||
|
||||
case CPUINFO_INT_PC:
|
||||
case CPUINFO_INT_REGISTER + DSP56K_PC: info->i = PC; break;
|
||||
case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc; break;
|
||||
/***************************************************************************
|
||||
MEMORY ACCESSORS
|
||||
***************************************************************************/
|
||||
#define ROPCODE(pc) cpustate->direct->read_decrypted_word(pc)
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_SR: info->i = SR; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_LC: info->i = LC; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_LA: info->i = LA; break;
|
||||
|
||||
case CPUINFO_INT_SP:
|
||||
case CPUINFO_INT_REGISTER + DSP56K_SP: info->i = SP; break;
|
||||
/***************************************************************************
|
||||
IRQ HANDLING
|
||||
***************************************************************************/
|
||||
void dsp56k_device::execute_set_input(int irqline, int state)
|
||||
{
|
||||
//logerror("DSP56k set irq line %d %d\n", irqline, state);
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_OMR: info->i = OMR; break;
|
||||
switch(irqline)
|
||||
{
|
||||
case DSP56K_IRQ_MODA:
|
||||
// TODO: 1-12 Get this triggering right
|
||||
if (irqa_trigger(&m_dsp56k_core))
|
||||
logerror("DSP56k IRQA is set to fire on the \"Negative Edge\".\n");
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_X: info->i = X; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_Y: info->i = Y; break;
|
||||
if (state != CLEAR_LINE)
|
||||
m_dsp56k_core.modA_state = TRUE;
|
||||
else
|
||||
m_dsp56k_core.modA_state = FALSE;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_A: info->i = A; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_B: info->i = B; break;
|
||||
if (m_dsp56k_core.reset_state != TRUE)
|
||||
dsp56k_add_pending_interrupt(&m_dsp56k_core, "IRQA");
|
||||
break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R0: info->i = R0; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R1: info->i = R1; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R2: info->i = R2; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_R3: info->i = R3; break;
|
||||
case DSP56K_IRQ_MODB:
|
||||
// TODO: 1-12 Get this triggering right
|
||||
if (irqb_trigger(&m_dsp56k_core))
|
||||
logerror("DSP56k IRQB is set to fire on the \"Negative Edge\".\n");
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N0: info->i = N0; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N1: info->i = N1; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N2: info->i = N2; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_N3: info->i = N3; break;
|
||||
if (state != CLEAR_LINE)
|
||||
m_dsp56k_core.modB_state = TRUE;
|
||||
else
|
||||
m_dsp56k_core.modB_state = FALSE;
|
||||
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M0: info->i = M0; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M1: info->i = M1; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M2: info->i = M2; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_M3: info->i = M3; break;
|
||||
if (m_dsp56k_core.reset_state != TRUE)
|
||||
dsp56k_add_pending_interrupt(&m_dsp56k_core, "IRQB");
|
||||
break;
|
||||
|
||||
/* case CPUINFO_INT_REGISTER + DSP56K_TEMP: info->i = TEMP; break; */
|
||||
/* case CPUINFO_INT_REGISTER + DSP56K_STATUS: info->i = STATUS; break; */
|
||||
case DSP56K_IRQ_MODC:
|
||||
if (state != CLEAR_LINE)
|
||||
m_dsp56k_core.modC_state = TRUE;
|
||||
else
|
||||
m_dsp56k_core.modC_state = FALSE;
|
||||
|
||||
/* The CPU stack */
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST0: info->i = ST0; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST1: info->i = ST1; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST2: info->i = ST2; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST3: info->i = ST3; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST4: info->i = ST4; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST5: info->i = ST5; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST6: info->i = ST6; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST7: info->i = ST7; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST8: info->i = ST8; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST9: info->i = ST9; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST10: info->i = ST10; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST11: info->i = ST11; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST12: info->i = ST12; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST13: info->i = ST13; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST14: info->i = ST14; break;
|
||||
case CPUINFO_INT_REGISTER + DSP56K_ST15: info->i = ST15; break;
|
||||
// TODO : Set bus mode or whatever
|
||||
break;
|
||||
|
||||
/* --- the following bits of info are returned as pointers to data or functions --- */
|
||||
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(dsp56k); break;
|
||||
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(dsp56k); break;
|
||||
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(dsp56k); break;
|
||||
case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(dsp56k); break;
|
||||
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(dsp56k); break;
|
||||
case CPUINFO_FCT_BURN: info->burn = NULL; break;
|
||||
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(dsp56k); break;
|
||||
case CPUINFO_FCT_DEBUG_INIT: info->debug_init = NULL; break;
|
||||
case CPUINFO_FCT_TRANSLATE: info->translate = NULL; break;
|
||||
case CPUINFO_FCT_READ: info->read = NULL; break;
|
||||
case CPUINFO_FCT_WRITE: info->write = NULL; break;
|
||||
case CPUINFO_FCT_READOP: info->readop = NULL; break;
|
||||
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
|
||||
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA:
|
||||
info->internal_map16 = ADDRESS_MAP_NAME(dsp56156_x_data_map); break;
|
||||
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM:
|
||||
info->internal_map16 = ADDRESS_MAP_NAME(dsp56156_program_map); break;
|
||||
case DSP56K_IRQ_RESET:
|
||||
if (state != CLEAR_LINE)
|
||||
m_dsp56k_core.reset_state = TRUE;
|
||||
else
|
||||
{
|
||||
/* If it changes state from asserted to cleared. Call the reset function. */
|
||||
if (m_dsp56k_core.reset_state == TRUE)
|
||||
device_reset();
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case CPUINFO_STR_NAME: strcpy(info->s, "DSP56156"); break;
|
||||
case CPUINFO_STR_SHORTNAME: strcpy(info->s, "dsp56156"); break;
|
||||
case CPUINFO_STR_FAMILY: strcpy(info->s, "Motorola DSP56156"); break;
|
||||
case CPUINFO_STR_VERSION: strcpy(info->s, "0.1"); break;
|
||||
case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
|
||||
case CPUINFO_STR_CREDITS: strcpy(info->s, "Andrew Gardner"); break;
|
||||
m_dsp56k_core.reset_state = FALSE;
|
||||
}
|
||||
|
||||
case CPUINFO_STR_FLAGS:
|
||||
sprintf(info->s, "%s%s %s%s%s%s%s%s%s%s %s%s",
|
||||
// dsp56k_add_pending_interrupt("Hardware RESET");
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("DSP56k setting some weird irq line : %d", irqline);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the reset line isn't asserted, service interrupts */
|
||||
// TODO: Is it right to immediately service interrupts?
|
||||
//if (cpustate->reset_state != TRUE)
|
||||
// pcu_service_interrupts();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
INITIALIZATION AND SHUTDOWN
|
||||
***************************************************************************/
|
||||
void dsp56k_device::agu_init()
|
||||
{
|
||||
/* save states - dsp56k_agu members */
|
||||
save_item(NAME(m_dsp56k_core.AGU.r0));
|
||||
save_item(NAME(m_dsp56k_core.AGU.r1));
|
||||
save_item(NAME(m_dsp56k_core.AGU.r2));
|
||||
save_item(NAME(m_dsp56k_core.AGU.r3));
|
||||
save_item(NAME(m_dsp56k_core.AGU.n0));
|
||||
save_item(NAME(m_dsp56k_core.AGU.n1));
|
||||
save_item(NAME(m_dsp56k_core.AGU.n2));
|
||||
save_item(NAME(m_dsp56k_core.AGU.n3));
|
||||
save_item(NAME(m_dsp56k_core.AGU.m0));
|
||||
save_item(NAME(m_dsp56k_core.AGU.m1));
|
||||
save_item(NAME(m_dsp56k_core.AGU.m2));
|
||||
save_item(NAME(m_dsp56k_core.AGU.m3));
|
||||
save_item(NAME(m_dsp56k_core.AGU.temp));
|
||||
}
|
||||
|
||||
void dsp56k_device::alu_init()
|
||||
{
|
||||
/* save states - dsp56k_alu members */
|
||||
save_item(NAME(m_dsp56k_core.ALU.x));
|
||||
save_item(NAME(m_dsp56k_core.ALU.y));
|
||||
save_item(NAME(m_dsp56k_core.ALU.a));
|
||||
save_item(NAME(m_dsp56k_core.ALU.b));
|
||||
}
|
||||
|
||||
void dsp56k_device::device_start()
|
||||
{
|
||||
memset(&m_dsp56k_core, 0, sizeof(m_dsp56k_core));
|
||||
|
||||
m_dsp56k_core.device = this;
|
||||
|
||||
/* Call specific module inits */
|
||||
pcu_init(&m_dsp56k_core, this);
|
||||
agu_init();
|
||||
alu_init();
|
||||
|
||||
/* HACK - You're not in bootstrap mode upon bootup */
|
||||
m_dsp56k_core.bootstrap_mode = BOOTSTRAP_OFF;
|
||||
|
||||
/* Clear the irq states */
|
||||
m_dsp56k_core.modA_state = FALSE;
|
||||
m_dsp56k_core.modB_state = FALSE;
|
||||
m_dsp56k_core.modC_state = FALSE;
|
||||
m_dsp56k_core.reset_state = FALSE;
|
||||
|
||||
/* save states - dsp56k_core members */
|
||||
save_item(NAME(m_dsp56k_core.modA_state));
|
||||
save_item(NAME(m_dsp56k_core.modB_state));
|
||||
save_item(NAME(m_dsp56k_core.modC_state));
|
||||
save_item(NAME(m_dsp56k_core.reset_state));
|
||||
save_item(NAME(m_dsp56k_core.bootstrap_mode));
|
||||
save_item(NAME(m_dsp56k_core.repFlag));
|
||||
save_item(NAME(m_dsp56k_core.repAddr));
|
||||
save_item(NAME(m_dsp56k_core.ppc));
|
||||
save_item(NAME(m_dsp56k_core.op));
|
||||
save_item(NAME(m_dsp56k_core.interrupt_cycles));
|
||||
|
||||
/* save states - dsp56k_host_interface members */
|
||||
save_item(NAME(m_dsp56k_core.HI.icr));
|
||||
save_item(NAME(m_dsp56k_core.HI.cvr));
|
||||
save_item(NAME(m_dsp56k_core.HI.isr));
|
||||
save_item(NAME(m_dsp56k_core.HI.ivr));
|
||||
save_item(NAME(m_dsp56k_core.HI.trxh));
|
||||
save_item(NAME(m_dsp56k_core.HI.trxl));
|
||||
save_item(NAME(m_dsp56k_core.HI.bootstrap_offset));
|
||||
|
||||
save_item(NAME(m_dsp56k_core.peripheral_ram));
|
||||
save_item(NAME(m_dsp56k_core.program_ram));
|
||||
|
||||
m_dsp56k_core.program = &space(AS_PROGRAM);
|
||||
m_dsp56k_core.direct = &m_dsp56k_core.program->direct();
|
||||
m_dsp56k_core.data = &space(AS_DATA);
|
||||
|
||||
/* Setup the direct memory handler for this CPU */
|
||||
/* NOTE: Be sure to grab this guy and call him if you ever install another direct_update_hander in a driver! */
|
||||
m_dsp56k_core.program->set_direct_update_handler(direct_update_delegate(FUNC(dsp56k_device::dsp56k_direct_handler), this));
|
||||
|
||||
state_add(DSP56K_PC, "PC", m_dsp56k_core.PCU.pc).formatstr("%04X");
|
||||
state_add(DSP56K_SR, "SR", m_dsp56k_core.PCU.sr).formatstr("%04X");
|
||||
state_add(DSP56K_LC, "LC", m_dsp56k_core.PCU.lc).formatstr("%04X");
|
||||
state_add(DSP56K_LA, "LA", m_dsp56k_core.PCU.la).formatstr("%04X");
|
||||
state_add(DSP56K_SP, "SP", m_dsp56k_core.PCU.sp).formatstr("%02X");
|
||||
state_add(DSP56K_OMR, "OMR", m_dsp56k_core.PCU.omr).formatstr("%02X");
|
||||
|
||||
state_add(DSP56K_X, "X", m_dsp56k_core.ALU.x.d).mask(0xffffffff).formatstr("%9s");
|
||||
state_add(DSP56K_Y, "Y", m_dsp56k_core.ALU.y.d).mask(0xffffffff).formatstr("%9s");
|
||||
|
||||
state_add(DSP56K_A, "A", m_dsp56k_core.ALU.a.q).mask((UINT64)U64(0xffffffffffffffff)).formatstr("%12s"); /* could benefit from a better mask? */
|
||||
state_add(DSP56K_B, "B", m_dsp56k_core.ALU.b.q).mask((UINT64)U64(0xffffffffffffffff)).formatstr("%12s"); /* could benefit from a better mask? */
|
||||
|
||||
state_add(DSP56K_R0, "R0", m_dsp56k_core.AGU.r0).formatstr("%04X");
|
||||
state_add(DSP56K_R1, "R1", m_dsp56k_core.AGU.r1).formatstr("%04X");
|
||||
state_add(DSP56K_R2, "R2", m_dsp56k_core.AGU.r2).formatstr("%04X");
|
||||
state_add(DSP56K_R3, "R3", m_dsp56k_core.AGU.r3).formatstr("%04X");
|
||||
|
||||
state_add(DSP56K_N0, "N0", m_dsp56k_core.AGU.n0).formatstr("%04X");
|
||||
state_add(DSP56K_N1, "N1", m_dsp56k_core.AGU.n1).formatstr("%04X");
|
||||
state_add(DSP56K_N2, "N2", m_dsp56k_core.AGU.n2).formatstr("%04X");
|
||||
state_add(DSP56K_N3, "N3", m_dsp56k_core.AGU.n3).formatstr("%04X");
|
||||
|
||||
state_add(DSP56K_M0, "M0", m_dsp56k_core.AGU.m0).formatstr("%04X");
|
||||
state_add(DSP56K_M1, "M1", m_dsp56k_core.AGU.m1).formatstr("%04X");
|
||||
state_add(DSP56K_M2, "M2", m_dsp56k_core.AGU.m2).formatstr("%04X");
|
||||
state_add(DSP56K_M3, "M3", m_dsp56k_core.AGU.m3).formatstr("%04X");
|
||||
|
||||
state_add(DSP56K_TEMP, "TMP", m_dsp56k_core.AGU.temp).formatstr("%04X").noshow();
|
||||
//state_add(DSP56K_STATUS, "STS", STATUS).formatstr("%02X");
|
||||
|
||||
state_add(DSP56K_ST0, "ST0", m_dsp56k_core.PCU.ss[0].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST1, "ST1", m_dsp56k_core.PCU.ss[1].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST2, "ST2", m_dsp56k_core.PCU.ss[2].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST3, "ST3", m_dsp56k_core.PCU.ss[3].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST4, "ST4", m_dsp56k_core.PCU.ss[4].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST5, "ST5", m_dsp56k_core.PCU.ss[5].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST6, "ST6", m_dsp56k_core.PCU.ss[6].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST7, "ST7", m_dsp56k_core.PCU.ss[7].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST8, "ST8", m_dsp56k_core.PCU.ss[8].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST9, "ST9", m_dsp56k_core.PCU.ss[9].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST10, "ST10", m_dsp56k_core.PCU.ss[10].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST11, "ST11", m_dsp56k_core.PCU.ss[11].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST12, "ST12", m_dsp56k_core.PCU.ss[12].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST13, "ST13", m_dsp56k_core.PCU.ss[13].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST14, "ST14", m_dsp56k_core.PCU.ss[14].d).formatstr("%08X");
|
||||
state_add(DSP56K_ST15, "ST15", m_dsp56k_core.PCU.ss[15].d).formatstr("%08X");
|
||||
|
||||
state_add(STATE_GENPC, "GENPC", m_dsp56k_core.PCU.pc).noshow();
|
||||
state_add(STATE_GENSP, "GENSP", m_dsp56k_core.PCU.sp).noshow();
|
||||
state_add(STATE_GENPCBASE, "GENPCBASE", m_dsp56k_core.ppc).noshow();
|
||||
state_add(STATE_GENFLAGS, "GENFLAGS", m_dsp56k_core.PCU.sr).formatstr("%14s").noshow();
|
||||
|
||||
m_icountptr = &m_dsp56k_core.icount;
|
||||
}
|
||||
|
||||
|
||||
void dsp56k_device::state_string_export(const device_state_entry &entry, astring &string)
|
||||
{
|
||||
dsp56k_core *cpustate = &m_dsp56k_core;
|
||||
|
||||
switch (entry.index())
|
||||
{
|
||||
case STATE_GENFLAGS:
|
||||
string.printf("%s%s %s%s%s%s%s%s%s%s %s%s",
|
||||
/* Status Register */
|
||||
LF_bit(cpustate) ? "L" : ".",
|
||||
FV_bit(cpustate) ? "F" : ".",
|
||||
@ -626,55 +383,135 @@ CPU_GET_INFO( dsp56k )
|
||||
SE_bit(cpustate) ? "S" : ".");
|
||||
break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + DSP56K_PC: sprintf(info->s, "PC : %04x", PC); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_SR: sprintf(info->s, "SR : %04x", SR); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_LC: sprintf(info->s, "LC : %04x", LC); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_LA: sprintf(info->s, "LA : %04x", LA); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_SP: sprintf(info->s, "SP : %02x", SP); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_OMR: sprintf(info->s, "OMR: %02x", OMR); break;
|
||||
case DSP56K_X:
|
||||
string.printf("%04x %04x", X1, X0);
|
||||
break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + DSP56K_X: sprintf(info->s, "X : %04x %04x", X1, X0); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_Y: sprintf(info->s, "Y : %04x %04x", Y1, Y0); break;
|
||||
case DSP56K_Y:
|
||||
string.printf("%04x %04x", Y1, Y0);
|
||||
break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + DSP56K_A: sprintf(info->s, "A : %02x %04x %04x", A2,A1,A0); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_B: sprintf(info->s, "B : %02x %04x %04x", B2,B1,B0); break;
|
||||
case DSP56K_A:
|
||||
string.printf("%02x %04x %04x", A2,A1,A0);
|
||||
break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + DSP56K_R0: sprintf(info->s, "R0 : %04x", R0); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_R1: sprintf(info->s, "R1 : %04x", R1); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_R2: sprintf(info->s, "R2 : %04x", R2); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_R3: sprintf(info->s, "R3 : %04x", R3); break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + DSP56K_N0: sprintf(info->s, "N0 : %04x", N0); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_N1: sprintf(info->s, "N1 : %04x", N1); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_N2: sprintf(info->s, "N2 : %04x", N2); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_N3: sprintf(info->s, "N3 : %04x", N3); break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + DSP56K_M0: sprintf(info->s, "M0 : %04x", M0); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_M1: sprintf(info->s, "M1 : %04x", M1); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_M2: sprintf(info->s, "M2 : %04x", M2); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_M3: sprintf(info->s, "M3 : %04x", M3); break;
|
||||
|
||||
/* case CPUINFO_STR_REGISTER + DSP56K_TEMP: sprintf(info->s, "TMP: %04x", TEMP); break; */
|
||||
/* case CPUINFO_STR_REGISTER + DSP56K_STATUS: sprintf(info->s, "STS: %02x", STATUS); break; */
|
||||
|
||||
/* The CPU stack */
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST0: sprintf(info->s, "ST0 : %08x", ST0); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST1: sprintf(info->s, "ST1 : %08x", ST1); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST2: sprintf(info->s, "ST2 : %08x", ST2); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST3: sprintf(info->s, "ST3 : %08x", ST3); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST4: sprintf(info->s, "ST4 : %08x", ST4); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST5: sprintf(info->s, "ST5 : %08x", ST5); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST6: sprintf(info->s, "ST6 : %08x", ST6); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST7: sprintf(info->s, "ST7 : %08x", ST7); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST8: sprintf(info->s, "ST8 : %08x", ST8); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST9: sprintf(info->s, "ST9 : %08x", ST9); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST10: sprintf(info->s, "ST10: %08x", ST10); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST11: sprintf(info->s, "ST11: %08x", ST11); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST12: sprintf(info->s, "ST12: %08x", ST12); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST13: sprintf(info->s, "ST13: %08x", ST13); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST14: sprintf(info->s, "ST14: %08x", ST14); break;
|
||||
case CPUINFO_STR_REGISTER + DSP56K_ST15: sprintf(info->s, "ST15: %08x", ST15); break;
|
||||
case DSP56K_B:
|
||||
string.printf("%02x %04x %04x", B2,B1,B0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_LEGACY_CPU_DEVICE(DSP56156, dsp56k);
|
||||
/***************************************************************************
|
||||
RESET BEHAVIOR
|
||||
***************************************************************************/
|
||||
static void agu_reset(dsp56k_core* cpustate)
|
||||
{
|
||||
/* FM.4-3 */
|
||||
R0 = 0x0000;
|
||||
R1 = 0x0000;
|
||||
R2 = 0x0000;
|
||||
R3 = 0x0000;
|
||||
|
||||
N0 = 0x0000;
|
||||
N1 = 0x0000;
|
||||
N2 = 0x0000;
|
||||
N3 = 0x0000;
|
||||
|
||||
M0 = 0xffff;
|
||||
M1 = 0xffff;
|
||||
M2 = 0xffff;
|
||||
M3 = 0xffff;
|
||||
|
||||
TEMP = 0x0000;
|
||||
}
|
||||
|
||||
static void alu_reset(dsp56k_core* cpustate)
|
||||
{
|
||||
X = 0x00000000;
|
||||
Y = 0x00000000;
|
||||
A = 0x0000000000;
|
||||
B = 0x0000000000;
|
||||
}
|
||||
|
||||
void dsp56k_device::device_reset()
|
||||
{
|
||||
logerror("Dsp56k reset\n");
|
||||
|
||||
m_dsp56k_core.interrupt_cycles = 0;
|
||||
m_dsp56k_core.ppc = 0x0000;
|
||||
|
||||
m_dsp56k_core.repFlag = 0;
|
||||
m_dsp56k_core.repAddr = 0x0000;
|
||||
|
||||
pcu_reset(&m_dsp56k_core);
|
||||
mem_reset(&m_dsp56k_core);
|
||||
agu_reset(&m_dsp56k_core);
|
||||
alu_reset(&m_dsp56k_core);
|
||||
|
||||
/* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */
|
||||
m_dsp56k_core.program->write_word(0x0000, 0x0124);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CORE INCLUDE
|
||||
***************************************************************************/
|
||||
#include "dsp56ops.inc"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CORE EXECUTION LOOP
|
||||
***************************************************************************/
|
||||
// Execute a single opcode and return how many cycles it took.
|
||||
static size_t execute_one_new(dsp56k_core* cpustate)
|
||||
{
|
||||
// For MAME
|
||||
cpustate->op = ROPCODE(ADDRESS(PC));
|
||||
debugger_instruction_hook(cpustate->device, PC);
|
||||
|
||||
UINT16 w0 = ROPCODE(ADDRESS(PC));
|
||||
UINT16 w1 = ROPCODE(ADDRESS(PC) + ADDRESS(1));
|
||||
|
||||
Opcode op(w0, w1);
|
||||
op.evaluate(cpustate);
|
||||
PC += op.evalSize(); // Special size function needed to handle jmps, etc.
|
||||
|
||||
// TODO: Currently all operations take up 4 cycles (inst->cycles()).
|
||||
return 4;
|
||||
}
|
||||
|
||||
void dsp56k_device::execute_run()
|
||||
{
|
||||
/* If reset line is asserted, do nothing */
|
||||
if (m_dsp56k_core.reset_state)
|
||||
{
|
||||
m_dsp56k_core.icount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */
|
||||
if (m_dsp56k_core.bootstrap_mode != BOOTSTRAP_OFF)
|
||||
{
|
||||
m_dsp56k_core.icount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//m_dsp56k_core.icount -= m_dsp56k_core.interrupt_cycles;
|
||||
//m_dsp56k_core.interrupt_cycles = 0;
|
||||
|
||||
while(m_dsp56k_core.icount > 0)
|
||||
{
|
||||
execute_one(&m_dsp56k_core);
|
||||
if (0) m_dsp56k_core.icount -= execute_one_new(&m_dsp56k_core);
|
||||
pcu_service_interrupts(&m_dsp56k_core); // TODO: Is it incorrect to service after each instruction?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
offs_t dsp56k_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
|
||||
{
|
||||
extern CPU_DISASSEMBLE( dsp56k );
|
||||
return CPU_DISASSEMBLE_NAME(dsp56k)(this, buffer, pc, oprom, opram, options);
|
||||
}
|
||||
|
||||
|
@ -22,23 +22,6 @@
|
||||
#define DSP56K_IRQ_MODC 2
|
||||
#define DSP56K_IRQ_RESET 3 /* Is this needed? */
|
||||
|
||||
// Needed for MAME
|
||||
CPU_GET_INFO( dsp56k );
|
||||
|
||||
class dsp56k_device : public legacy_cpu_device
|
||||
{
|
||||
public:
|
||||
dsp56k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_DIRECT_UPDATE_MEMBER(dsp56k_direct_handler);
|
||||
DECLARE_READ16_MEMBER( program_r );
|
||||
DECLARE_WRITE16_MEMBER( program_w );
|
||||
DECLARE_READ16_MEMBER( peripheral_register_r );
|
||||
DECLARE_WRITE16_MEMBER( peripheral_register_w );
|
||||
};
|
||||
|
||||
extern const device_type DSP56156;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
STRUCTURES & TYPEDEFS
|
||||
@ -204,7 +187,7 @@ struct dsp56k_core
|
||||
UINT32 op;
|
||||
int interrupt_cycles;
|
||||
void (*output_pins_changed)(UINT32 pins);
|
||||
legacy_cpu_device *device;
|
||||
cpu_device *device;
|
||||
address_space *program;
|
||||
direct_read_data *direct;
|
||||
address_space *data;
|
||||
@ -214,20 +197,61 @@ struct dsp56k_core
|
||||
};
|
||||
|
||||
|
||||
INLINE dsp56k_core *get_safe_token(device_t *device)
|
||||
class dsp56k_device : public cpu_device
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == DSP56156);
|
||||
return (dsp56k_core *)downcast<legacy_cpu_device *>(device)->token();
|
||||
}
|
||||
public:
|
||||
dsp56k_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
|
||||
|
||||
DECLARE_DIRECT_UPDATE_MEMBER(dsp56k_direct_handler);
|
||||
DECLARE_READ16_MEMBER( program_r );
|
||||
DECLARE_WRITE16_MEMBER( program_w );
|
||||
DECLARE_READ16_MEMBER( peripheral_register_r );
|
||||
DECLARE_WRITE16_MEMBER( peripheral_register_w );
|
||||
|
||||
void host_interface_write(UINT8 offset, UINT8 data);
|
||||
UINT8 host_interface_read(UINT8 offset);
|
||||
|
||||
UINT16 get_peripheral_memory(UINT16 addr);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 2 - 1) / 2; }
|
||||
virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 2); }
|
||||
virtual UINT32 execute_min_cycles() const { return 1; }
|
||||
virtual UINT32 execute_max_cycles() const { return 8; }
|
||||
virtual UINT32 execute_input_lines() const { return 4; }
|
||||
virtual UINT32 execute_default_irq_vector() const { return 0; }
|
||||
virtual void execute_run();
|
||||
virtual void execute_set_input(int inputnum, int state);
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : ((spacenum == AS_DATA) ? &m_data_config : NULL ); }
|
||||
|
||||
// device_state_interface overrides
|
||||
void state_string_export(const device_state_entry &entry, astring &string);
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
|
||||
virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
|
||||
private:
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_data_config;
|
||||
|
||||
dsp56k_core m_dsp56k_core;
|
||||
|
||||
void agu_init();
|
||||
void alu_init();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
PUBLIC FUNCTIONS - ACCESSIBLE TO DRIVERS
|
||||
***************************************************************************/
|
||||
void dsp56k_host_interface_write(device_t* device, UINT8 offset, UINT8 data);
|
||||
UINT8 dsp56k_host_interface_read(device_t* device, UINT8 offset);
|
||||
extern const device_type DSP56156;
|
||||
|
||||
UINT16 dsp56k_get_peripheral_memory(device_t* device, UINT16 addr);
|
||||
|
||||
#endif /* __DSP56K_H__ */
|
||||
|
@ -488,20 +488,18 @@ void dsp56k_io_reset(dsp56k_core* cpustate)
|
||||
|
||||
READ16_MEMBER( dsp56k_device::program_r )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(this);
|
||||
return cpustate->program_ram[offset];
|
||||
return m_dsp56k_core.program_ram[offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( dsp56k_device::program_w )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(this);
|
||||
cpustate->program_ram[offset] = data;
|
||||
m_dsp56k_core.program_ram[offset] = data;
|
||||
}
|
||||
|
||||
/* Work */
|
||||
READ16_MEMBER( dsp56k_device::peripheral_register_r )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(this);
|
||||
dsp56k_core* cpustate = &m_dsp56k_core;
|
||||
// (printf) logerror("Peripheral read 0x%04x\n", O2A(offset));
|
||||
|
||||
switch (O2A(offset))
|
||||
@ -635,7 +633,7 @@ READ16_MEMBER( dsp56k_device::peripheral_register_r )
|
||||
|
||||
WRITE16_MEMBER( dsp56k_device::peripheral_register_w )
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(this);
|
||||
dsp56k_core* cpustate = &m_dsp56k_core;
|
||||
|
||||
// Its primary behavior is RAM
|
||||
// COMBINE_DATA(&cpustate->peripheral_ram[offset]);
|
||||
@ -790,9 +788,9 @@ WRITE16_MEMBER( dsp56k_device::peripheral_register_w )
|
||||
|
||||
/* These two functions are exposed to the outside world */
|
||||
/* They represent the host side of the dsp56k's host interface */
|
||||
void dsp56k_host_interface_write(device_t* device, UINT8 offset, UINT8 data)
|
||||
void dsp56k_device::host_interface_write(UINT8 offset, UINT8 data)
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
dsp56k_core* cpustate = &m_dsp56k_core;
|
||||
|
||||
/* Not exactly correct since the bootstrap hack doesn't need this to be true */
|
||||
/*
|
||||
@ -886,9 +884,9 @@ void dsp56k_host_interface_write(device_t* device, UINT8 offset, UINT8 data)
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 dsp56k_host_interface_read(device_t* device, UINT8 offset)
|
||||
UINT8 dsp56k_device::host_interface_read(UINT8 offset)
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
dsp56k_core* cpustate = &m_dsp56k_core;
|
||||
|
||||
/* Not exactly correct since the bootstrap hack doesn't need this to be true */
|
||||
/*
|
||||
@ -951,8 +949,8 @@ UINT8 dsp56k_host_interface_read(device_t* device, UINT8 offset)
|
||||
}
|
||||
|
||||
/* MISC*/
|
||||
UINT16 dsp56k_get_peripheral_memory(device_t* device, UINT16 addr)
|
||||
UINT16 dsp56k_device::get_peripheral_memory(UINT16 addr)
|
||||
{
|
||||
dsp56k_core* cpustate = get_safe_token(device);
|
||||
dsp56k_core* cpustate = &m_dsp56k_core;
|
||||
return cpustate->peripheral_ram[A2O(addr)];
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ READ32_MEMBER(polygonet_state::dsp_host_interface_r)
|
||||
if (mem_mask == 0x0000ff00) { hi_addr++; } /* Low byte */
|
||||
if (mem_mask == 0xff000000) {} /* High byte */
|
||||
|
||||
value = dsp56k_host_interface_read(m_dsp, hi_addr);
|
||||
value = m_dsp->host_interface_read(hi_addr);
|
||||
|
||||
if (mem_mask == 0x0000ff00) { value <<= 8; }
|
||||
if (mem_mask == 0xff000000) { value <<= 24; }
|
||||
@ -278,7 +278,7 @@ WRITE32_MEMBER(polygonet_state::dsp_host_interface_w)
|
||||
if (mem_mask == 0xff000000) { hi_data = (data & 0xff000000) >> 24; }
|
||||
|
||||
logerror("write (host-side) %08x %08x %08x (HI %04x)\n", offset, mem_mask, data, hi_addr);
|
||||
dsp56k_host_interface_write(m_dsp, hi_addr, hi_data);
|
||||
m_dsp->host_interface_write(hi_addr, hi_data);
|
||||
}
|
||||
|
||||
|
||||
@ -353,7 +353,7 @@ DIRECT_UPDATE_MEMBER(polygonet_state::plygonet_dsp56k_direct_handler)
|
||||
|
||||
static UINT8 dsp56k_bank_group(device_t* cpu)
|
||||
{
|
||||
UINT16 portC = dsp56k_get_peripheral_memory(cpu, 0xffe3);
|
||||
UINT16 portC = ((dsp56k_device *)cpu)->get_peripheral_memory(0xffe3);
|
||||
|
||||
/* If bank group B is on, it overrides bank group A */
|
||||
if (portC & 0x0002)
|
||||
@ -366,7 +366,7 @@ static UINT8 dsp56k_bank_group(device_t* cpu)
|
||||
|
||||
static UINT8 dsp56k_bank_num(device_t* cpu, UINT8 bank_group)
|
||||
{
|
||||
UINT16 portC = dsp56k_get_peripheral_memory(cpu, 0xffe3);
|
||||
UINT16 portC = ((dsp56k_device *)cpu)->get_peripheral_memory(0xffe3);
|
||||
|
||||
if (bank_group == BANK_GROUP_A)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "machine/eepromser.h"
|
||||
#include "video/k053936.h"
|
||||
#include "cpu/dsp56k/dsp56k.h"
|
||||
|
||||
|
||||
static const UINT16 dsp56k_bank00_size = 0x1000;
|
||||
@ -28,7 +29,7 @@ public:
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<cpu_device> m_dsp;
|
||||
required_device<dsp56k_device> m_dsp;
|
||||
required_device<eeprom_serial_er5911_device> m_eeprom;
|
||||
required_device<k053936_device> m_k053936;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user