From d20e6b61517c0d8ad87660a2caa1c131df74d188 Mon Sep 17 00:00:00 2001 From: Andrew Gardner Date: Mon, 4 Aug 2008 04:07:29 +0000 Subject: [PATCH] Improved Dsp56k CPU interrupt handling. Polygonet Commanders now advances past its first dsp handshake. --- src/emu/cpu/dsp56k/dsp56def.h | 2 +- src/emu/cpu/dsp56k/dsp56k.c | 7 +++-- src/emu/cpu/dsp56k/dsp56mem.c | 6 ++-- src/emu/cpu/dsp56k/dsp56pcu.c | 52 +++++++++++++++++++++++------------ 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/emu/cpu/dsp56k/dsp56def.h b/src/emu/cpu/dsp56k/dsp56def.h index e83b4a83057..b98a1f912d2 100644 --- a/src/emu/cpu/dsp56k/dsp56def.h +++ b/src/emu/cpu/dsp56k/dsp56def.h @@ -294,7 +294,7 @@ static void RREQ_bit_set(UINT8 value); static void CVR_set(UINT8 value); //static UINT8 HC_bit(); -//static UINT8 HV_bits(); +static UINT8 HV_bits(); static void HC_bit_set(UINT8 value); static void HV_bits_set(UINT8 value); diff --git a/src/emu/cpu/dsp56k/dsp56k.c b/src/emu/cpu/dsp56k/dsp56k.c index ef6bc2be419..d4a2befab0a 100644 --- a/src/emu/cpu/dsp56k/dsp56k.c +++ b/src/emu/cpu/dsp56k/dsp56k.c @@ -344,8 +344,8 @@ static void set_irq_line(int irqline, int state) // If the reset line isn't asserted, service interrupts // TODO: Is it right to immediately service interrupts? - if (core.reset_state != TRUE) - pcu_service_interrupts(); + //if (core.reset_state != TRUE) + // pcu_service_interrupts(); } @@ -451,7 +451,10 @@ static int dsp56k_execute(int cycles) core.interrupt_cycles = 0; while(dsp56k_icount > 0) + { execute_one(); + pcu_service_interrupts(); /* TODO: There is definitely something un-right about this */ + } dsp56k_icount -= core.interrupt_cycles; core.interrupt_cycles = 0; diff --git a/src/emu/cpu/dsp56k/dsp56mem.c b/src/emu/cpu/dsp56k/dsp56mem.c index 62ba428491f..3d6427e710e 100644 --- a/src/emu/cpu/dsp56k/dsp56mem.c +++ b/src/emu/cpu/dsp56k/dsp56mem.c @@ -409,7 +409,6 @@ static void HCP_bit_set(UINT16 value) HSR &= ~(0x0004); HSR |= (value << 2); - // TODO: Define Host Command through the IRQ structure if (value && HCIE_bit()) dsp56k_add_pending_interrupt("Host Command"); } @@ -509,6 +508,8 @@ static void RREQ_bit_set(UINT8 value) /**************************************/ /* Command Vector Register (CVR) Bits */ /**************************************/ +static UINT8 HV_bits() { return (CVR & 0x1f); } + static void CVR_set(UINT8 value) { /* A single, unified place to run all callbacks for each of the bits */ @@ -522,9 +523,6 @@ static void HC_bit_set(UINT8 value) CVR &= ~(0x80); CVR |= (value << 7); - // TODO: 5-9 Do I push a host-command interrupt here? Doesn't seem like it, but maybe i'll have to poll for it somewhere else? - // TODO: 5-9 The exception routine clears this bit after it executes. - HCP_bit_set(value); // 5-9 & 5-11 } static void HV_bits_set(UINT8 value) diff --git a/src/emu/cpu/dsp56k/dsp56pcu.c b/src/emu/cpu/dsp56k/dsp56pcu.c index c58269d98ad..81e84020321 100644 --- a/src/emu/cpu/dsp56k/dsp56pcu.c +++ b/src/emu/cpu/dsp56k/dsp56pcu.c @@ -172,6 +172,13 @@ static void pcu_reset(void) /*************************************************************************** INTERRUPT HANDLING ***************************************************************************/ +typedef struct +{ + UINT16 irq_vector; + char irq_source[128]; +} dsp56k_irq_data; + +static dsp56k_irq_data dsp56k_interrupt_sources[32]; // TODO: Figure out how to switch on level versus edge-triggered. static void pcu_service_interrupts(void) @@ -181,27 +188,43 @@ static void pcu_service_interrupts(void) // Count list of pending interrupts int num_servicable = dsp56k_count_pending_interrupts(); - if (num_servicable == 0) return; + if (num_servicable == 0) + return; - // Sort list + // Sort list according to priority dsp56k_sort_pending_interrupts(num_servicable); // Service each interrupt in order + // TODO: This just *can't* be right :) for (i = 0; i < num_servicable; i++) { + const int interrupt_index = core.PCU.pending_interrupts[i]; + // Get the priority of the interrupt - a return value of -1 means disabled! - INT8 priority = dsp56k_get_irq_priority(core.PCU.pending_interrupts[i]); + INT8 priority = dsp56k_get_irq_priority(interrupt_index); // 1-12 Make sure you're not masked out against the Interrupt Mask Bits (disabled is handled for free here) if (priority >= I_bits()) { - // If you're acceptable to go, execute the interrupt - - // TODO: 5-7 Remember the host command input has a floating vector. Do it up right. - // TODO: 5-9 5-11 Gotta' Clear HI (HCP & HC) when taking this exception too! + // Are you anything but the Host Command interrupt? + if (interrupt_index != 22) + { + // Execute a normal interrupt + PC = dsp56k_interrupt_sources[interrupt_index].irq_vector; + } + else + { + // The host command input has a floating vector. + const UINT16 irq_vector = HV_bits() << 1; + PC = irq_vector; + + // TODO: 5-9 5-11 Gotta' Clear HC (HCP gets it too) when taking this exception! + HC_bit_set(0); + } } } - + + dsp56k_clear_pending_interrupts(); } // @@ -218,18 +241,11 @@ static void dsp56k_add_pending_interrupt(const char* name) if (core.PCU.pending_interrupts[i] == -1) { core.PCU.pending_interrupts[i] = irq_index; + break; } } } -typedef struct -{ - UINT16 irq_vector; - char irq_source[128]; -} dsp56k_irq_data; - -static dsp56k_irq_data dsp56k_interrupt_sources[32]; - static void dsp56k_set_irq_source(UINT8 irq_num, UINT16 iv, const char* source) { dsp56k_interrupt_sources[irq_num].irq_vector = iv; @@ -263,7 +279,7 @@ static void dsp56k_irq_table_init(void) dsp56k_set_irq_source(19, 0x0026, "Host DMA Transmit Data"); dsp56k_set_irq_source(20, 0x0028, "Host Receive Data"); dsp56k_set_irq_source(21, 0x002a, "Host Transmit Data"); - dsp56k_set_irq_source(22, 0x002c, "Host Command 0 (Default)"); + dsp56k_set_irq_source(22, 0x002c, "Host Command"); /* Default vector for the host command */ dsp56k_set_irq_source(23, 0x002e, "Codec Receive/Transmit"); dsp56k_set_irq_source(24, 0x0030, "Host Command 1"); dsp56k_set_irq_source(25, 0x0032, "Host Command 2"); @@ -383,7 +399,7 @@ static int dsp56k_get_irq_index_by_tag(const char* tag) int i; for (i = 0; i < 32; i++) { - if (!strcmp(tag, dsp56k_interrupt_sources[i].irq_source)) + if (strcmp(tag, dsp56k_interrupt_sources[i].irq_source) == 0) { return i; }