--- hatari/src/falcon/dsp.c 2019/04/01 07:13:46 1.1.1.1 +++ hatari/src/falcon/dsp.c 2019/04/09 08:55:48 1.1.1.11 @@ -1,586 +1,859 @@ /* - * dsp.c - Atari DSP56001 emulation code - * - * Copyright (c) 2001-2004 Petr Stehlik of ARAnyM dev team - * Adaption to Hatari (C) 2006 by Thomas Huth - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + DSP M56001 emulation + Dummy emulation, Hatari glue + + (C) 2001-2008 ARAnyM developer team + Adaption to Hatari (C) 2008 by Thomas Huth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include #include "main.h" #include "sysdeps.h" +#include "newcpu.h" +#include "memorySnapShot.h" #include "ioMem.h" #include "dsp.h" -#include "dsp_cpu.h" +#include "crossbar.h" +#include "configuration.h" +#include "cycInt.h" +#include "m68000.h" -#define DSP_EMULATION 1 -#define DEBUG 1 +#if ENABLE_DSP_EMU +#include "debugdsp.h" +#include "dsp_cpu.h" +#include "dsp_disasm.h" +#endif +#define DEBUG 0 #if DEBUG -#define D(x) x +#define Dprintf(a) printf a #else -#define D(x) +#define Dprintf(a) #endif -#include +#define DSP_HW_OFFSET 0xFFA200 -#include -#include -#ifndef M_PI -#define M_PI 3.141592653589793238462643383279502 -#endif - - -/* DSP state */ -uint8 dsp_state; +#if ENABLE_DSP_EMU +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" +}; -/* Registers */ -uint16 dsp_pc; -uint32 dsp_registers[64]; - -/* stack[0=ssh], stack[1=ssl] */ -uint16 dsp_stack[2][15]; +static Sint32 save_cycles; +#endif -/* ram[0] is x:, ram[1] is y:, ram[2] is p: */ -uint32 dsp_ram[3][DSP_RAMSIZE]; +static bool bDspDebugging; -/* rom[0] is x:, rom[1] is y: */ -uint32 dsp_rom[2][512]; +bool bDspEnabled = false; +bool bDspHostInterruptPending = false; -/* peripheral space, [x|y]:0xffc0-0xffff */ -uint32 dsp_periph[2][64]; -/* host port, CPU side */ -uint8 dsp_hostport[8]; +/** + * Trigger HREQ interrupt at the host CPU. + */ +#if ENABLE_DSP_EMU +static void DSP_TriggerHostInterrupt(int hreq) +{ +//fprintf ( stderr, "DSP_TriggerHostInterrupt %d %x %x\n" , hreq , regs.sr , regs.intmask ); + if ( hreq ) + { + M68000_SetSpecial(SPCFLAG_DSP); // TODO for old cpu core, remove, use level 6 instead and M68000_Update_intlev() + bDspHostInterruptPending = true; + M68000_Update_intlev (); + } + else + { + M68000_UnsetSpecial(SPCFLAG_DSP); // TODO for old cpu core, remove, use level 6 instead and M68000_Update_intlev() + bDspHostInterruptPending = false; + M68000_Update_intlev (); + } +} +#endif -/* Misc */ -uint32 dsp_loop_rep; /* executing rep ? */ -uint32 dsp_last_loop_inst; /* executing the last instruction in DO ? */ -uint32 dsp_first_host_write; /* first byte written to host port */ -SDL_sem *dsp56k_sem; +/** + * Return the state of HREQ + */ +Uint8 DSP_GetHREQ ( void ) +{ + if ( bDspHostInterruptPending ) + return 1; + else + return 0; +} -/* For bootstrap routine */ -static uint16 bootstrap_pos; -static uint32 bootstrap_accum; +/** + * Return the vector number associated to the HREQ interrupt. + * If this function is called when HREQ=0, then we return -1 to indicate + * a spurious interrupt. + */ +int DSP_ProcessIACK ( void ) +{ + int VecNr; -static SDL_Thread *dsp56k_thread; + if ( bDspHostInterruptPending ) + VecNr = IoMem_ReadByte ( 0xffa203 ); + else + VecNr = -1; + + return VecNr; +} +/** + * 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), M68000_EXC_SRC_INT_DSP); + bDspHostInterruptPending = false; // [NP] TODO : remove this line, should be cleared by DSP_TriggerHostInterrupt ? + M68000_UnsetSpecial(SPCFLAG_DSP); // [NP] TODO : remove this line, should be cleared by DSP_TriggerHostInterrupt ? + return true; + } -#if DSP_EMULATION + return false; +} +#endif -/* More disasm infos, if wanted */ -#define DSP_DISASM_HOSTREAD 0 /* Dsp->Host transfer */ -#define DSP_DISASM_HOSTWRITE 0 /* Host->Dsp transfer */ -#define DSP_DISASM_STATE 0 /* State changes */ -/* Execute DSP instructions till the DSP waits for a read/write */ -#define DSP_HOST_FORCEEXEC 0 +/** + * Initialize the DSP emulation (should be called only once at start) + */ +void DSP_Init(void) +{ +#if ENABLE_DSP_EMU + dsp_core_init(DSP_TriggerHostInterrupt); + dsp56k_init_cpu(); + save_cycles = 0; +#endif +} -static inline Uint32 getHWoffset(void) +/** + * Shut down the DSP emulation (should be called only once at exit) + */ +void DSP_UnInit(void) { - return 0xFFA200; +#if ENABLE_DSP_EMU + dsp_core_shutdown(); + bDspEnabled = false; +#endif } -/* Constructor and destructor for DSP class */ -void DSP_Init(void) +/** + * Reset the DSP emulation + */ +void DSP_Reset(void) { - int i; +#if ENABLE_DSP_EMU + dsp_core_reset(); + DSP_TriggerHostInterrupt ( 0 ); /* Clear HREQ */ + save_cycles = 0; +#endif +} - memset(dsp_ram, 0,sizeof(dsp_ram)); - /* Initialize Y:rom[0x0100-0x01ff] with a sin table */ - { - float src; - int32 dest; +/** + * Enable the DSP emulation + */ +void DSP_Enable(void) +{ +#if ENABLE_DSP_EMU + bDspEnabled = true; +#endif +} - for (i=0;i<256;i++) { - src = (((float) i)*M_PI)/128.0; - dest = (int32) (sin(src) * 8388608.0); /* 1<<23 */ - if (dest>8388607) { - dest = 8388607; - } else if (dest<-8388608) { - dest = -8388608; - } - dsp_rom[DSP_SPACE_Y][0x100+i]=dest & 0x00ffffff; - } - } - /* Initialize X:rom[0x0100-0x017f] with a mu-law table */ - { - const uint16 mulaw_base[8]={ - 0x7d7c, 0x3e7c, 0x1efc, 0x0f3c, 0x075c, 0x036c, 0x0174, 0x0078 - }; - - uint32 value, offset, position; - int j; - - position = 0x0100; - offset = 0x040000; - for(i=0;i<8;i++) { - value = mulaw_base[i]<<8; - - for (j=0;j<16;j++) { - dsp_rom[DSP_SPACE_X][position++]=value; - value -= offset; - } +/** + * Disable the DSP emulation + */ +void DSP_Disable(void) +{ +#if ENABLE_DSP_EMU + bDspEnabled = false; +#endif +} - offset >>= 1; - } - } - /* Initialize X:rom[0x0180-0x01ff] with a a-law table */ - { - const int32 multiply_base[8]={ - 0x1580, 0x0ac0, 0x5600, 0x2b00, - 0x1580, 0x0058, 0x0560, 0x02b0 - }; - const int32 multiply_col[4]={0x10, 0x01, 0x04, 0x02}; - const int32 multiply_line[4]={0x40, 0x04, 0x10, 0x08}; - const int32 base_values[4]={0, -1, 2, 1}; - uint32 pos=0x0180; - - for (i=0;i<8;i++) { - int32 alawbase, j; - - alawbase = multiply_base[i]<<8; - for (j=0;j<4;j++) { - int32 alawbase1, k; - - alawbase1 = alawbase + ((base_values[j]*multiply_line[i & 3])<<12); +/** + * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type) + */ +void DSP_MemorySnapShot_Capture(bool bSave) +{ +#if ENABLE_DSP_EMU + MemorySnapShot_Store(&bDspEnabled, sizeof(bDspEnabled)); + MemorySnapShot_Store(&dsp_core, sizeof(dsp_core)); + MemorySnapShot_Store(&save_cycles, sizeof(save_cycles)); - for (k=0;k<4;k++) { - int32 alawbase2; + if ( bDspEnabled ) + DSP_Enable(); + else + DSP_Disable(); +#endif +} - alawbase2 = alawbase1 + ((base_values[k]*multiply_col[i & 3])<<12); +/** + * Run DSP for certain cycles + */ +void DSP_Run(int nHostCycles) +{ +#if ENABLE_DSP_EMU + save_cycles += nHostCycles * 2; - dsp_rom[DSP_SPACE_X][pos++]=alawbase2; - } - } - } - } - - D(bug("Dsp: power-on done")); + if (dsp_core.running == 0) + return; - dsp56k_thread = NULL; - dsp56k_sem = NULL; + 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; + } + } - dsp_state = DSP_HALT; -#if DSP_DISASM_STATE - D(bug("Dsp: state = HALT")); #endif +} + +/** + * Enable/disable DSP debugging mode + */ +void DSP_SetDebugging(bool enabled) +{ + bDspDebugging = enabled; } -void DSP_UnInit(void) +/** + * Get DSP program counter (for debugging) + */ +Uint16 DSP_GetPC(void) { - DSP_shutdown(); +#if ENABLE_DSP_EMU + if (bDspEnabled) + return dsp_core.pc; + else +#endif + return 0; } -/* Other functions to init/shutdown dsp emulation */ -void DSP_Reset(void) +/** + * Get next DSP PC without output (for debugging) + */ +Uint16 DSP_GetNextPC(Uint16 pc) { - int i; +#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); - /* Kill existing thread and semaphore */ - DSP_shutdown(); + /* Restore DSP context */ + memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core)); - /* Pause thread */ - dsp_state = DSP_BOOTING; -#if DSP_DISASM_STATE - D(bug("Dsp: state = BOOTING")); + return pc + instruction_length; +#else + return 0; #endif +} - /* Memory */ - memset(dsp_periph, 0,sizeof(dsp_periph)); - memset(dsp_stack, 0,sizeof(dsp_stack)); - memset(dsp_registers, 0,sizeof(dsp_registers)); +/** + * Get current DSP instruction cycles (for profiling) + */ +Uint16 DSP_GetInstrCycles(void) +{ +#if ENABLE_DSP_EMU + if (bDspEnabled) + return dsp_core.instr_cycle; + else +#endif + return 0; +} - bootstrap_pos = bootstrap_accum = 0; - - /* Registers */ - dsp_pc = 0x0000; - dsp_registers[DSP_REG_OMR]=0x02; - for (i=0;i<8;i++) { - dsp_registers[DSP_REG_M0+i]=0x00ffff; - } - /* host port init, dsp side */ - dsp_periph[DSP_SPACE_X][DSP_HOST_HSR]=(1<= 0xffc0) { + *mem_str = spaces[idx][3]; + /* reading host/transmit regs has side-effects, + * so just give the memory value. + */ + return dsp_core.periph[space][address-0xffc0]; } - if (dsp56k_thread == NULL) { - dsp56k_thread = SDL_CreateThread(dsp56k_do_execute, NULL); + /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ + address &= (DSP_RAMSIZE>>1) - 1; + if (space == DSP_SPACE_X) { + address += DSP_RAMSIZE>>1; } + + /* Falcon: External RAM, finally map X,Y to P */ + *mem_str = spaces[idx][2]; + return dsp_core.ramext[address & (DSP_RAMSIZE-1)]; +#endif + return 0; } -void DSP_shutdown(void) -{ - if (dsp56k_thread != NULL) { - /* Stop thread */ - dsp_state = DSP_STOPTHREAD; -#if DSP_DISASM_STATE - D(bug("Dsp: state = STOPTHREAD")); +/** + * Output memory values between given addresses in given DSP address space. + * Return next DSP address value. + */ +Uint16 DSP_DisasmMemory(Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space) +{ +#if ENABLE_DSP_EMU + Uint32 mem, mem2, value; + const char *mem_str; + + for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { + /* special printing of host communication/transmit registers */ + 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); + } + else if (mem == 0xffef) { + 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 */ + if ((space == 'X' || space == 'Y') && + mem >= 0x200 && mem < 0xffc0) { + mem2 = mem & ((DSP_RAMSIZE>>1)-1); + if (space == 'X') { + mem2 += (DSP_RAMSIZE>>1); + } + fprintf(stderr,"%c:%04x (P:%04x): %06x\n", space, + mem, mem2, dsp_core.ramext[mem2 & (DSP_RAMSIZE-1)]); + continue; + } + value = DSP_ReadMemory(mem, space, &mem_str); + fprintf(stderr,"%s:%04x %06x\n", mem_str, mem, value); + } #endif + return dsp_memdump_upper+1; +} - /* Release semaphore, if thread waiting for it */ - if (SDL_SemValue(dsp56k_sem)==0) { - SDL_SemPost(dsp56k_sem); +/** + * Show information on DSP core state which isn't + * shown by any of the other commands (dd, dm, dr). + */ +void DSP_Info(FILE *fp, Uint32 dummy) +{ +#if ENABLE_DSP_EMU + int i, j; + const char *stackname[] = { "SSH", "SSL" }; + + fputs("DSP core information:\n", fp); + + for (i = 0; i < ARRAYSIZE(stackname); i++) { + fprintf(fp, "- %s stack:", stackname[i]); + for (j = 0; j < ARRAYSIZE(dsp_core.stack[0]); j++) { + fprintf(fp, " %04hx", dsp_core.stack[i][j]); } + fputs("\n", fp); + } - /* Wait for the thread to finish */ - while (dsp_state != DSP_STOPPEDTHREAD) { - SDL_Delay(1); - } + fprintf(fp, "- Interrupt IPL:"); + for (i = 0; i < ARRAYSIZE(dsp_core.interrupt_ipl); i++) { + fprintf(fp, " %04hx", dsp_core.interrupt_ipl[i]); + } + fputs("\n", fp); - dsp56k_thread = NULL; + fprintf(fp, "- Pending ints: "); + for (i = 0; i < ARRAYSIZE(dsp_core.interrupt_isPending); i++) { + fprintf(fp, " %04hx", dsp_core.interrupt_isPending[i]); } + fputs("\n", fp); - /* Destroy the semaphore */ - if (dsp56k_sem != NULL) { - SDL_DestroySemaphore(dsp56k_sem); - dsp56k_sem = NULL; - } -} - -/********************************** - * Force execution of DSP, till something - * to read from/write to host port - **********************************/ - -static inline void DSP_force_exec(void) -{ -#if DSP_HOST_FORCEEXEC - while (state == DSP_RUNNING) { - } -#endif -} - -#endif /* DSP_EMULATION */ - -/********************************** - * Hardware address read/write by CPU - **********************************/ - -static uint8 DSP_handleRead(Uint32 addr) -{ -#if DSP_EMULATION - uint8 value=0; - - addr -= getHWoffset(); - -/* D(bug("HWget_b(0x%08x)=0x%02x at 0x%08x", addr+HW_DSP, value, showPC()));*/ - - /* Whenever the host want to read something on host port, we test if a - transfer is needed */ - DSP_dsp2host(); - - switch(addr) { - case CPU_HOST_ICR: - value = dsp_hostport[CPU_HOST_ICR]; - break; - case CPU_HOST_CVR: - value = dsp_hostport[CPU_HOST_CVR]; - break; - case CPU_HOST_ISR: - value = dsp_hostport[CPU_HOST_ISR]; - break; - case CPU_HOST_IVR: - value = dsp_hostport[CPU_HOST_IVR]; - break; - case CPU_HOST_RX0: - DSP_force_exec(); - value = 0; - break; - case CPU_HOST_RXH: - DSP_force_exec(); - value = dsp_hostport[CPU_HOST_RXH]; - break; - case CPU_HOST_RXM: - DSP_force_exec(); - value = dsp_hostport[CPU_HOST_RXM]; - break; - case CPU_HOST_RXL: - DSP_force_exec(); - value = dsp_hostport[CPU_HOST_RXL]; - - if (dsp_state!=DSP_BOOTING) { - /* Clear RXDF bit to say that CPU has read */ - dsp_hostport[CPU_HOST_ISR] &= 0xff-(1<H): Host RXDF cleared")); + fprintf(fp, "- Hostport:"); + for (i = 0; i < ARRAYSIZE(dsp_core.hostport); i++) { + fprintf(fp, " %02x", dsp_core.hostport[i]); + } + fputs("\n", fp); #endif - } +} - /* Wake up DSP if it was waiting our read */ - if (dsp_state==DSP_WAITHOSTREAD) { -#if DSP_DISASM_STATE - D(bug("Dsp: state = DSP_RUNNING")); -#endif - dsp_state = DSP_RUNNING; +/** + * Show DSP register contents + */ +void DSP_DisasmRegisters(void) +{ +#if ENABLE_DSP_EMU + Uint32 i; - if (SDL_SemValue(dsp56k_sem)==0) { - SDL_SemPost(dsp56k_sem); - } - } + fprintf(stderr,"A: A2: %02x A1: %06x A0: %06x\n", + dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0]); + fprintf(stderr,"B: B2: %02x B1: %06x B0: %06x\n", + dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0]); + + fprintf(stderr,"X: X1: %06x X0: %06x\n", dsp_core.registers[DSP_REG_X1], dsp_core.registers[DSP_REG_X0]); + fprintf(stderr,"Y: Y1: %06x Y0: %06x\n", dsp_core.registers[DSP_REG_Y1], dsp_core.registers[DSP_REG_Y0]); - break; + for (i=0; i<8; i++) { + fprintf(stderr,"R%01x: %04x N%01x: %04x M%01x: %04x\n", + i, dsp_core.registers[DSP_REG_R0+i], + i, dsp_core.registers[DSP_REG_N0+i], + i, dsp_core.registers[DSP_REG_M0+i]); } - return value; -#else - return 0xff; // this value prevents TOS from hanging in the DSP init code */ -#endif /* DSP_EMULATION */ + fprintf(stderr,"LA: %04x LC: %04x PC: %04x\n", dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], dsp_core.pc); + fprintf(stderr,"SR: %04x OMR: %02x\n", dsp_core.registers[DSP_REG_SR], dsp_core.registers[DSP_REG_OMR]); + fprintf(stderr,"SP: %02x SSH: %04x SSL: %04x\n", + dsp_core.registers[DSP_REG_SP], dsp_core.registers[DSP_REG_SSH], dsp_core.registers[DSP_REG_SSL]); +#endif } -void DSP_HandleReadAccess(void) -{ - Uint32 a; - Uint8 v; - for (a = IoAccessBaseAddress; a < IoAccessBaseAddress+nIoMemAccessSize; a++) - { - v = DSP_handleRead(a); - IoMem_WriteByte(a, v); - } -} -static void DSP_handleWrite(Uint32 addr, uint8 value) +/** + * Get given DSP register address and required bit mask. + * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP, + * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers + * need special handling (in DSP*SetRegister()) when they are set. + * Return the register width in bits or zero for an error. + */ +int DSP_GetRegisterAddress(const char *regname, Uint32 **addr, Uint32 *mask) { -#if DSP_EMULATION - addr -= getHWoffset(); - -/* D(bug("HWput_b(0x%08x,0x%02x) at 0x%08x", addr+HW_DSP, value, showPC()));*/ - - switch(addr) { - case CPU_HOST_ICR: - dsp_hostport[CPU_HOST_ICR]=value & 0xfb; - /* Set HF1 and HF0 accordingly on the host side */ - dsp_periph[DSP_SPACE_X][DSP_HOST_HSR] &= - 0xff-((1<D): Host TXDE cleared")); + /* 56-bit A register */ + { "A0", &dsp_core.registers[DSP_REG_A0], 32, BITMASK(24) }, + { "A1", &dsp_core.registers[DSP_REG_A1], 32, BITMASK(24) }, + { "A2", &dsp_core.registers[DSP_REG_A2], 32, BITMASK(8) }, + + /* 56-bit B register */ + { "B0", &dsp_core.registers[DSP_REG_B0], 32, BITMASK(24) }, + { "B1", &dsp_core.registers[DSP_REG_B1], 32, BITMASK(24) }, + { "B2", &dsp_core.registers[DSP_REG_B2], 32, BITMASK(8) }, + + /* 16-bit LA & LC registers */ + { "LA", &dsp_core.registers[DSP_REG_LA], 32, BITMASK(16) }, + { "LC", &dsp_core.registers[DSP_REG_LC], 32, BITMASK(16) }, + + /* 16-bit M registers */ + { "M0", &dsp_core.registers[DSP_REG_M0], 32, BITMASK(16) }, + { "M1", &dsp_core.registers[DSP_REG_M1], 32, BITMASK(16) }, + { "M2", &dsp_core.registers[DSP_REG_M2], 32, BITMASK(16) }, + { "M3", &dsp_core.registers[DSP_REG_M3], 32, BITMASK(16) }, + { "M4", &dsp_core.registers[DSP_REG_M4], 32, BITMASK(16) }, + { "M5", &dsp_core.registers[DSP_REG_M5], 32, BITMASK(16) }, + { "M6", &dsp_core.registers[DSP_REG_M6], 32, BITMASK(16) }, + { "M7", &dsp_core.registers[DSP_REG_M7], 32, BITMASK(16) }, + + /* 16-bit N registers */ + { "N0", &dsp_core.registers[DSP_REG_N0], 32, BITMASK(16) }, + { "N1", &dsp_core.registers[DSP_REG_N1], 32, BITMASK(16) }, + { "N2", &dsp_core.registers[DSP_REG_N2], 32, BITMASK(16) }, + { "N3", &dsp_core.registers[DSP_REG_N3], 32, BITMASK(16) }, + { "N4", &dsp_core.registers[DSP_REG_N4], 32, BITMASK(16) }, + { "N5", &dsp_core.registers[DSP_REG_N5], 32, BITMASK(16) }, + { "N6", &dsp_core.registers[DSP_REG_N6], 32, BITMASK(16) }, + { "N7", &dsp_core.registers[DSP_REG_N7], 32, BITMASK(16) }, + + { "OMR", &dsp_core.registers[DSP_REG_OMR], 32, 0x5f }, + + /* 16-bit program counter */ + { "PC", (Uint32*)(&dsp_core.pc), 16, BITMASK(16) }, + + /* 16-bit DSP R (address) registers */ + { "R0", &dsp_core.registers[DSP_REG_R0], 32, BITMASK(16) }, + { "R1", &dsp_core.registers[DSP_REG_R1], 32, BITMASK(16) }, + { "R2", &dsp_core.registers[DSP_REG_R2], 32, BITMASK(16) }, + { "R3", &dsp_core.registers[DSP_REG_R3], 32, BITMASK(16) }, + { "R4", &dsp_core.registers[DSP_REG_R4], 32, BITMASK(16) }, + { "R5", &dsp_core.registers[DSP_REG_R5], 32, BITMASK(16) }, + { "R6", &dsp_core.registers[DSP_REG_R6], 32, BITMASK(16) }, + { "R7", &dsp_core.registers[DSP_REG_R7], 32, BITMASK(16) }, + + { "SSH", &dsp_core.registers[DSP_REG_SSH], 32, BITMASK(16) }, + { "SSL", &dsp_core.registers[DSP_REG_SSL], 32, BITMASK(16) }, + { "SP", &dsp_core.registers[DSP_REG_SP], 32, BITMASK(6) }, + + /* 16-bit status register */ + { "SR", &dsp_core.registers[DSP_REG_SR], 32, 0xefff }, + + /* 48-bit X register */ + { "X0", &dsp_core.registers[DSP_REG_X0], 32, BITMASK(24) }, + { "X1", &dsp_core.registers[DSP_REG_X1], 32, BITMASK(24) }, + + /* 48-bit Y register */ + { "Y0", &dsp_core.registers[DSP_REG_Y0], 32, BITMASK(24) }, + { "Y1", &dsp_core.registers[DSP_REG_Y1], 32, BITMASK(24) } + }; + /* left, right, middle, direction */ + int l, r, m, dir = 0; + unsigned int i, len; + char reg[MAX_REGNAME_LEN]; + + if (!bDspEnabled) { + return 0; + } + + for (i = 0; i < sizeof(reg) && regname[i]; i++) { + reg[i] = toupper((unsigned char)regname[i]); + } + if (i < 2 || regname[i]) { + /* too short or longer than any of the names */ + return 0; + } + len = i; + + /* bisect */ + l = 0; + r = ARRAYSIZE(registers) - 1; + do { + m = (l+r) >> 1; + for (i = 0; i < len; i++) { + dir = (int)reg[i] - registers[m].name[i]; + if (dir) { + break; + } + } + if (dir == 0) { + *addr = registers[m].addr; + *mask = registers[m].mask; + return registers[m].bits; + } + if (dir < 0) { + r = m-1; + } else { + l = m+1; + } + } while (l <= r); +#undef MAX_REGNAME_LEN #endif + return 0; +} - DSP_host2dsp(); - } - switch(dsp_state) { - case DSP_BOOTING: - dsp_ram[DSP_SPACE_P][bootstrap_pos] = bootstrap_accum; -/* D(bug("Dsp: bootstrap: p:0x%04x: 0x%06x written", bootstrap_pos, bootstrap_accum));*/ - bootstrap_pos++; - if (bootstrap_pos == 0x200) { -#if DSP_DISASM_STATE - D(bug("Dsp: bootstrap done")); -#endif - dsp_state = DSP_RUNNING; - - SDL_SemPost(dsp56k_sem); - } - bootstrap_accum = 0; - break; - case DSP_WAITHOSTWRITE: - /* Wake up DSP if it was waiting our write */ -#if DSP_DISASM_STATE - D(bug("Dsp: state = DSP_RUNNING")); -#endif - dsp_state = DSP_RUNNING; - - if (SDL_SemValue(dsp56k_sem)==0) { - SDL_SemPost(dsp56k_sem); - } - break; +/** + * Set given DSP register value, return false if unknown register given + */ +bool DSP_Disasm_SetRegister(const char *arg, Uint32 value) +{ +#if ENABLE_DSP_EMU + Uint32 *addr, mask, sp_value; + int bits; + + /* first check registers needing special handling... */ + if (arg[0]=='S' || arg[0]=='s') { + if (arg[1]=='P' || arg[1]=='p') { + dsp_core.registers[DSP_REG_SP] = value & BITMASK(6); + value &= BITMASK(4); + dsp_core.registers[DSP_REG_SSH] = dsp_core.stack[0][value]; + dsp_core.registers[DSP_REG_SSL] = dsp_core.stack[1][value]; + return true; + } + if (arg[1]=='S' || arg[1]=='s') { + sp_value = dsp_core.registers[DSP_REG_SP] & BITMASK(4); + if (arg[2]=='H' || arg[2]=='h') { + if (sp_value == 0) { + dsp_core.registers[DSP_REG_SSH] = 0; + dsp_core.stack[0][sp_value] = 0; + } else { + dsp_core.registers[DSP_REG_SSH] = value & BITMASK(16); + dsp_core.stack[0][sp_value] = value & BITMASK(16); + } + return true; } + if (arg[2]=='L' || arg[2]=='l') { + if (sp_value == 0) { + dsp_core.registers[DSP_REG_SSL] = 0; + dsp_core.stack[1][sp_value] = 0; + } else { + dsp_core.registers[DSP_REG_SSL] = value & BITMASK(16); + dsp_core.stack[1][sp_value] = value & BITMASK(16); + } + return true; + } + } + } - break; + /* ...then registers where address & mask are enough */ + bits = DSP_GetRegisterAddress(arg, &addr, &mask); + switch (bits) { + case 32: + *addr = value & mask; + return true; + case 16: + *(Uint16*)addr = value & mask; + return true; } -#endif /* DSP_EMULATION */ +#endif + return false; } -void DSP_HandleWriteAccess(void) +/** + * Read SSI transmit value + */ +Uint32 DSP_SsiReadTxValue(void) { - Uint32 a; - Uint8 v; - for (a = IoAccessBaseAddress; a < IoAccessBaseAddress+nIoMemAccessSize; a++) - { - v = IoMem_ReadByte(a); - DSP_handleWrite(a,v); - } +#if ENABLE_DSP_EMU + return dsp_core.ssi.transmit_value; +#else + return 0; +#endif } - -#if DSP_EMULATION - -/********************************** - * Host transfer - **********************************/ - -void DSP_host2dsp(void) +/** + * Write SSI receive value + */ +void DSP_SsiWriteRxValue(Uint32 value) { - int trdy; - - /* Host port transfer ? (host->dsp) */ - if ( - ((dsp_hostport[CPU_HOST_ISR] & (1<D): Transfer 0x%06x",dsp_periph[DSP_SPACE_X][DSP_HOST_HRX])); +void DSP_SsiReceive_SC0(void) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC0(); #endif +} - /* Set HRDF bit to say that DSP can read */ - dsp_periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<D): Dsp HRDF set")); +void DSP_SsiTransmit_SC0(void) +{ +#if ENABLE_DSP_EMU #endif +} - /* Set TXDE bit to say that host can write */ - dsp_hostport[CPU_HOST_ISR] |= 1<D): Host TXDE set")); +void DSP_SsiReceive_SC1(Uint32 FrameCounter) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC1(FrameCounter); #endif +} - /* Clear/set TRDY bit */ - dsp_hostport[CPU_HOST_ISR] &= 0xff-(1<>CPU_HOST_ISR_TXDE) & 1; - trdy &= !((dsp_periph[DSP_SPACE_X][DSP_HOST_HSR]>>DSP_HOST_HSR_HRDF) & 1); - dsp_hostport[CPU_HOST_ISR] |= (trdy & 1)<< CPU_HOST_ISR_TRDY; - } +void DSP_SsiTransmit_SC1(void) +{ +#if ENABLE_DSP_EMU + Crossbar_DmaPlayInHandShakeMode(); +#endif } -void DSP_dsp2host(void) +void DSP_SsiReceive_SC2(Uint32 FrameCounter) { - /* Host port transfer ? (dsp->host) */ - if ( - ((dsp_hostport[CPU_HOST_ISR] & (1<>8; - dsp_hostport[CPU_HOST_RXH] = dsp_periph[DSP_SPACE_X][DSP_HOST_HTX]>>16; +void DSP_SsiTransmit_SC2(Uint32 frame) +{ +#if ENABLE_DSP_EMU + Crossbar_DmaRecordInHandShakeMode_Frame(frame); +#endif +} -#if DSP_DISASM_HOSTWRITE - D(bug("Dsp: (D->H): Transfer 0x%06x",dsp_periph[DSP_SPACE_X][DSP_HOST_HTX])); +void DSP_SsiReceive_SCK(void) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SCK(); #endif +} - /* Set HTDE bit to say that DSP can write */ - dsp_periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<H): Dsp HTDE set")); +void DSP_SsiTransmit_SCK(void) +{ +#if ENABLE_DSP_EMU #endif +} - /* Set RXDF bit to say that host can read */ - dsp_hostport[CPU_HOST_ISR] |= 1<H): Host RXDF set")); +/** + * 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(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); } } -#endif /* DSP_EMULATION */ +/** + * 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; + bool multi_access = false; + for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++) + { +#if ENABLE_DSP_EMU + 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; + } +}