--- hatari/src/falcon/dsp.c 2019/04/09 08:48:46 1.1.1.4 +++ hatari/src/falcon/dsp.c 2019/04/09 08:53:22 1.1.1.9 @@ -28,9 +28,10 @@ #include "dsp.h" #include "crossbar.h" #include "configuration.h" +#include "cycInt.h" +#include "m68000.h" #if ENABLE_DSP_EMU -#include "m68000.h" #include "debugdsp.h" #include "dsp_cpu.h" #include "dsp_disasm.h" @@ -43,16 +44,22 @@ #define Dprintf(a) #endif -#define BITMASK(x) ((1<<(x))-1) - #define DSP_HW_OFFSET 0xFFA200 #if ENABLE_DSP_EMU -static dsp_core_t dsp_core; -static dsp_core_t dsp_core_save; +static const char* x_ext_memory_addr_name[] = { + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "PBC", "PCC", "PBDDR", "PCDDR", "PBD", "PCD", "", "", + "HCR", "HSR", "", "HRX/HTX", "CRA", "CRB", "SSISR/TSR", "RX/TX", + "SCR", "SSR", "SCCR", "STXA", "SRX/STX", "SRX/STX", "SRX/STX", "", + "", "", "", "", "", "", "BCR", "IPR" +}; + static Sint32 save_cycles; #endif + static bool bDspDebugging; bool bDspEnabled = false; @@ -66,12 +73,28 @@ bool bDspHostInterruptPending = false; static void DSP_TriggerHostInterrupt(void) { bDspHostInterruptPending = true; + M68000_SetSpecial(SPCFLAG_DSP); +} +#endif + + +/** + * This function is called from the CPU emulation part when SPCFLAG_DSP is set. + * If the DSP's IRQ signal is set, we check that SR allows a level 6 interrupt, + * and if so, we call M68000_Exception. + */ +#if ENABLE_DSP_EMU +bool DSP_ProcessIRQ(void) +{ + if (bDspHostInterruptPending && regs.intmask < 6) + { + M68000_Exception(IoMem_ReadByte(0xffa203)*4, M68000_EXC_SRC_INT_DSP); + bDspHostInterruptPending = false; + M68000_UnsetSpecial(SPCFLAG_DSP); + return true; + } - /* Note: The DSP interrupt is not wired to the MFP on a real Falcon - * (but to the COMBEL chip). But in Hatari we still handle it with - * the SPCFLAG_MFP to avoid taking care of another special flag in - * the CPU core! */ - M68000_SetSpecial(SPCFLAG_MFP); + return false; } #endif @@ -82,10 +105,10 @@ static void DSP_TriggerHostInterrupt(voi void DSP_Init(void) { #if ENABLE_DSP_EMU - if (ConfigureParams.System.nDSPType != DSP_TYPE_EMU) + if (bDspEnabled || ConfigureParams.System.nDSPType != DSP_TYPE_EMU) return; - dsp_core_init(&dsp_core, DSP_TriggerHostInterrupt); - dsp56k_init_cpu(&dsp_core); + dsp_core_init(DSP_TriggerHostInterrupt); + dsp56k_init_cpu(); bDspEnabled = true; save_cycles = 0; #endif @@ -98,9 +121,9 @@ void DSP_Init(void) void DSP_UnInit(void) { #if ENABLE_DSP_EMU - if (ConfigureParams.System.nDSPType != DSP_TYPE_EMU) + if (!bDspEnabled) return; - dsp_core_shutdown(&dsp_core); + dsp_core_shutdown(); bDspEnabled = false; #endif } @@ -112,7 +135,7 @@ void DSP_UnInit(void) void DSP_Reset(void) { #if ENABLE_DSP_EMU - dsp_core_reset(&dsp_core); + dsp_core_reset(); bDspHostInterruptPending = false; save_cycles = 0; #endif @@ -140,32 +163,32 @@ void DSP_MemorySnapShot_Capture(bool bSa void DSP_Run(int nHostCycles) { #if ENABLE_DSP_EMU - /* Cycles emulation should be correctly tuned now */ - Sint32 i = nHostCycles * ( DSP_FREQ / CPU_FREQ ) - save_cycles + 1; - Sint32 dsp_cycle = 0; + save_cycles += nHostCycles * 2; - if (dsp_core.running == 0) - return; + if (dsp_core.running == 0) + return; - if (unlikely(bDspDebugging)) { - while (i > dsp_cycle) - { - DebugDsp_Check(); - dsp56k_execute_instruction(); - dsp_cycle += dsp_core.instr_cycle; - } - } else { - while (i > dsp_cycle) - { - dsp56k_execute_instruction(); - dsp_cycle += dsp_core.instr_cycle; - } - } + if (save_cycles <= 0) + return; + + if (unlikely(bDspDebugging)) { + while (save_cycles > 0) + { + dsp56k_execute_instruction(); + save_cycles -= dsp_core.instr_cycle; + DebugDsp_Check(); + } + } else { + // fprintf(stderr, "--> %d\n", save_cycles); + while (save_cycles > 0) + { + dsp56k_execute_instruction(); + save_cycles -= dsp_core.instr_cycle; + } + } - /* Adjust cycles for next run */ - save_cycles = i - dsp_cycle; #endif -} +} /** * Enable/disable DSP debugging mode @@ -176,7 +199,7 @@ void DSP_SetDebugging(bool enabled) } /** - * Get DSP program counter (for disassembler) + * Get DSP program counter (for debugging) */ Uint16 DSP_GetPC(void) { @@ -188,31 +211,62 @@ Uint16 DSP_GetPC(void) return 0; } +/** + * Get next DSP PC without output (for debugging) + */ +Uint16 DSP_GetNextPC(Uint16 pc) +{ +#if ENABLE_DSP_EMU + /* code is reduced copy from dsp56k_execute_one_disasm_instruction() */ + dsp_core_t dsp_core_save; + Uint16 instruction_length; + + if (!bDspEnabled) + return 0; + + /* Save DSP context */ + memcpy(&dsp_core_save, &dsp_core, sizeof(dsp_core)); + + /* Disasm instruction */ + dsp_core.pc = pc; + /* why dsp56k_execute_one_disasm_instruction() does "-1" + * for this value, that doesn't seem right??? + */ + instruction_length = dsp56k_disasm(DSP_DISASM_MODE); + + /* Restore DSP context */ + memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core)); + + return pc + instruction_length; +#else + return 0; +#endif +} /** - * Disassemble DSP code between given addresses, return next PC address + * Get current DSP instruction cycles (for profiling) */ -Uint32 DSP_DisasmAddress(Uint16 lowerAdr, Uint16 UpperAdr) +Uint16 DSP_GetInstrCycles(void) { #if ENABLE_DSP_EMU - Uint32 dsp_pc; - dsp_core_t *ptr1, *ptr2; - - ptr1 = &dsp_core; - ptr2 = &dsp_core_save; - - for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { - /* Save DSP context before executing instruction */ - memcpy(ptr2, ptr1, sizeof(dsp_core)); + if (bDspEnabled) + return dsp_core.instr_cycle; + else +#endif + return 0; +} - /* execute and disasm instruction */ - dsp_core.pc = dsp_pc; - dsp_pc += dsp56k_disasm() - 1; - dsp56k_execute_instruction(); - fprintf(stderr, "%s", dsp56k_getInstructionText()); - /* Restore DSP context after executing instruction */ - memcpy(ptr1, ptr2, sizeof(dsp_core)); +/** + * Disassemble DSP code between given addresses, return next PC address + */ +Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr) +{ +#if ENABLE_DSP_EMU + Uint16 dsp_pc; + + for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { + dsp_pc += dsp56k_execute_one_disasm_instruction(out, dsp_pc); } return dsp_pc; #else @@ -319,7 +373,7 @@ Uint16 DSP_DisasmMemory(Uint16 dsp_memdu for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { /* special printing of host communication/transmit registers */ - if (space == 'X' && (mem == 0xffeb || mem == 0xffef)) { + if (space == 'X' && mem >= 0xffc0) { if (mem == 0xffeb) { fprintf(stderr,"X periph:%04x HTX : %06x RTX:%06x\n", mem, dsp_core.dsp_host_htx, dsp_core.dsp_host_rtx); @@ -328,6 +382,10 @@ Uint16 DSP_DisasmMemory(Uint16 dsp_memdu fprintf(stderr,"X periph:%04x SSI TX : %06x SSI RX:%06x\n", mem, dsp_core.ssi.transmit_value, dsp_core.ssi.received_value); } + else { + value = DSP_ReadMemory(mem, space, &mem_str); + fprintf(stderr,"%s:%04x %06x\t%s\n", mem_str, mem, value, x_ext_memory_addr_name[mem-0xffc0]); + } continue; } /* special printing of X & Y external RAM values */ @@ -348,7 +406,49 @@ Uint16 DSP_DisasmMemory(Uint16 dsp_memdu return dsp_memdump_upper+1; } +/** + * Show information on DSP core state which isn't + * shown by any of the other commands (dd, dm, dr). + */ +void DSP_Info(Uint32 dummy) +{ +#if ENABLE_DSP_EMU + int i, j; + const char *stackname[] = { "SSH", "SSL" }; + + fputs("DSP core information:\n", stderr); + + for (i = 0; i < ARRAYSIZE(stackname); i++) { + fprintf(stderr, "- %s stack:", stackname[i]); + for (j = 0; j < ARRAYSIZE(dsp_core.stack[0]); j++) { + fprintf(stderr, " %04hx", dsp_core.stack[i][j]); + } + fputs("\n", stderr); + } + + fprintf(stderr, "- Interrupt IPL:"); + for (i = 0; i < ARRAYSIZE(dsp_core.interrupt_ipl); i++) { + fprintf(stderr, " %04hx", dsp_core.interrupt_ipl[i]); + } + fputs("\n", stderr); + + fprintf(stderr, "- Pending ints: "); + for (i = 0; i < ARRAYSIZE(dsp_core.interrupt_isPending); i++) { + fprintf(stderr, " %04hx", dsp_core.interrupt_isPending[i]); + } + fputs("\n", stderr); + fprintf(stderr, "- Hostport:"); + for (i = 0; i < ARRAYSIZE(dsp_core.hostport); i++) { + fprintf(stderr, " %02x", dsp_core.hostport[i]); + } + fputs("\n", stderr); +#endif +} + +/** + * Show DSP register contents + */ void DSP_DisasmRegisters(void) { #if ENABLE_DSP_EMU @@ -482,7 +582,7 @@ int DSP_GetRegisterAddress(const char *r /* bisect */ l = 0; - r = sizeof (registers) / sizeof (*registers) - 1; + r = ARRAYSIZE(registers) - 1; do { m = (l+r) >> 1; for (i = 0; i < len; i++) { @@ -594,7 +694,7 @@ void DSP_SsiWriteRxValue(Uint32 value) void DSP_SsiReceive_SC0(void) { #if ENABLE_DSP_EMU - dsp_core_ssi_Receive_SC0(&dsp_core); + dsp_core_ssi_Receive_SC0(); #endif } @@ -607,7 +707,7 @@ void DSP_SsiTransmit_SC0(void) void DSP_SsiReceive_SC1(Uint32 FrameCounter) { #if ENABLE_DSP_EMU - dsp_core_ssi_Receive_SC1(&dsp_core, FrameCounter); + dsp_core_ssi_Receive_SC1(FrameCounter); #endif } @@ -621,7 +721,7 @@ void DSP_SsiTransmit_SC1(void) void DSP_SsiReceive_SC2(Uint32 FrameCounter) { #if ENABLE_DSP_EMU - dsp_core_ssi_Receive_SC2(&dsp_core, FrameCounter); + dsp_core_ssi_Receive_SC2(FrameCounter); #endif } @@ -635,7 +735,7 @@ void DSP_SsiTransmit_SC2(Uint32 frame) void DSP_SsiReceive_SCK(void) { #if ENABLE_DSP_EMU - dsp_core_ssi_Receive_SCK(&dsp_core); + dsp_core_ssi_Receive_SCK(); #endif } @@ -647,19 +747,26 @@ void DSP_SsiTransmit_SCK(void) /** * Read access wrapper for ioMemTabFalcon (DSP Host port) + * DSP Host interface port is accessed by the 68030 in Byte mode. + * A move.w value,$ffA206 results in 2 bus access for the 68030. */ void DSP_HandleReadAccess(void) { Uint32 addr; Uint8 value; + bool multi_access = false; + for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++) { #if ENABLE_DSP_EMU - value = dsp_core_read_host(&dsp_core, addr-DSP_HW_OFFSET); + value = dsp_core_read_host(addr-DSP_HW_OFFSET); #else /* this value prevents TOS from hanging in the DSP init code */ value = 0xff; #endif + if (multi_access == true) + M68000_AddCycles(4); + multi_access = true; Dprintf(("HWget_b(0x%08x)=0x%02x at 0x%08x\n", addr, value, m68k_getpc())); IoMem_WriteByte(addr, value); @@ -668,17 +775,23 @@ void DSP_HandleReadAccess(void) /** * Write access wrapper for ioMemTabFalcon (DSP Host port) + * DSP Host interface port is accessed by the 68030 in Byte mode. + * A move.w value,$ffA206 results in 2 bus access for the 68030. */ void DSP_HandleWriteAccess(void) { Uint32 addr; - Uint8 value; + bool multi_access = false; + for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++) { - value = IoMem_ReadByte(addr); - Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc())); #if ENABLE_DSP_EMU - dsp_core_write_host(&dsp_core, addr-DSP_HW_OFFSET, value); + Uint8 value = IoMem_ReadByte(addr); + Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc())); + dsp_core_write_host(addr-DSP_HW_OFFSET, value); #endif + if (multi_access == true) + M68000_AddCycles(4); + multi_access = true; } }