--- hatari/src/falcon/dsp.c 2019/04/01 07:13:46 1.1 +++ hatari/src/falcon/dsp.c 2019/04/09 08:48:46 1.1.1.4 @@ -1,586 +1,684 @@ /* - * 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 "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" -#define DSP_EMULATION 1 -#define DEBUG 1 +#if ENABLE_DSP_EMU +#include "m68000.h" +#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 - -#include -#include - -#ifndef M_PI -#define M_PI 3.141592653589793238462643383279502 -#endif - - -/* DSP state */ -uint8 dsp_state; - -/* Registers */ -uint16 dsp_pc; -uint32 dsp_registers[64]; +#define BITMASK(x) ((1<<(x))-1) -/* stack[0=ssh], stack[1=ssl] */ -uint16 dsp_stack[2][15]; +#define DSP_HW_OFFSET 0xFFA200 -/* ram[0] is x:, ram[1] is y:, ram[2] is p: */ -uint32 dsp_ram[3][DSP_RAMSIZE]; -/* rom[0] is x:, rom[1] is y: */ -uint32 dsp_rom[2][512]; - -/* peripheral space, [x|y]:0xffc0-0xffff */ -uint32 dsp_periph[2][64]; - -/* host port, CPU side */ -uint8 dsp_hostport[8]; - -/* 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; - - -/* For bootstrap routine */ -static uint16 bootstrap_pos; -static uint32 bootstrap_accum; +#if ENABLE_DSP_EMU +static dsp_core_t dsp_core; +static dsp_core_t dsp_core_save; +static Sint32 save_cycles; +#endif +static bool bDspDebugging; -static SDL_Thread *dsp56k_thread; +bool bDspEnabled = false; +bool bDspHostInterruptPending = false; +/** + * Trigger HREQ interrupt at the host CPU. + */ +#if ENABLE_DSP_EMU +static void DSP_TriggerHostInterrupt(void) +{ + bDspHostInterruptPending = true; -#if DSP_EMULATION + /* 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); +} +#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 + */ +void DSP_Init(void) +{ +#if ENABLE_DSP_EMU + if (ConfigureParams.System.nDSPType != DSP_TYPE_EMU) + return; + dsp_core_init(&dsp_core, DSP_TriggerHostInterrupt); + dsp56k_init_cpu(&dsp_core); + bDspEnabled = true; + save_cycles = 0; +#endif +} -static inline Uint32 getHWoffset(void) +/** + * Shut down the DSP emulation + */ +void DSP_UnInit(void) { - return 0xFFA200; +#if ENABLE_DSP_EMU + if (ConfigureParams.System.nDSPType != DSP_TYPE_EMU) + return; + dsp_core_shutdown(&dsp_core); + bDspEnabled = false; +#endif } -/* Constructor and destructor for DSP class */ -void DSP_Init(void) +/** + * Reset the DSP emulation + */ +void DSP_Reset(void) { - int i; - - memset(dsp_ram, 0,sizeof(dsp_ram)); +#if ENABLE_DSP_EMU + dsp_core_reset(&dsp_core); + bDspHostInterruptPending = false; + save_cycles = 0; +#endif +} - /* Initialize Y:rom[0x0100-0x01ff] with a sin table */ - { - float src; - int32 dest; - 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; - } - } +/** + * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type) + */ +void DSP_MemorySnapShot_Capture(bool bSave) +{ +#if ENABLE_DSP_EMU + if (!bSave) + DSP_Reset(); - /* 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; - } + MemorySnapShot_Store(&bDspEnabled, sizeof(bDspEnabled)); + MemorySnapShot_Store(&dsp_core, sizeof(dsp_core)); + MemorySnapShot_Store(&save_cycles, sizeof(save_cycles)); +#endif +} - offset >>= 1; +/** + * Run DSP for certain cycles + */ +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; + + if (dsp_core.running == 0) + return; + + if (unlikely(bDspDebugging)) { + while (i > dsp_cycle) + { + DebugDsp_Check(); + dsp56k_execute_instruction(); + dsp_cycle += dsp_core.instr_cycle; } - } - - /* 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); - - for (k=0;k<4;k++) { - int32 alawbase2; - - alawbase2 = alawbase1 + ((base_values[k]*multiply_col[i & 3])<<12); - - dsp_rom[DSP_SPACE_X][pos++]=alawbase2; - } - } + } else { + while (i > dsp_cycle) + { + dsp56k_execute_instruction(); + dsp_cycle += dsp_core.instr_cycle; } } - - D(bug("Dsp: power-on done")); - - dsp56k_thread = NULL; - dsp56k_sem = NULL; - dsp_state = DSP_HALT; -#if DSP_DISASM_STATE - D(bug("Dsp: state = HALT")); + /* Adjust cycles for next run */ + save_cycles = i - dsp_cycle; #endif } -void DSP_UnInit(void) +/** + * Enable/disable DSP debugging mode + */ +void DSP_SetDebugging(bool enabled) { - DSP_shutdown(); + bDspDebugging = enabled; } -/* Other functions to init/shutdown dsp emulation */ -void DSP_Reset(void) +/** + * Get DSP program counter (for disassembler) + */ +Uint16 DSP_GetPC(void) { - int i; - - /* Kill existing thread and semaphore */ - DSP_shutdown(); - - /* Pause thread */ - dsp_state = DSP_BOOTING; -#if DSP_DISASM_STATE - D(bug("Dsp: state = BOOTING")); +#if ENABLE_DSP_EMU + if (bDspEnabled) + return dsp_core.pc; + else #endif + return 0; +} - /* Memory */ - memset(dsp_periph, 0,sizeof(dsp_periph)); - memset(dsp_stack, 0,sizeof(dsp_stack)); - memset(dsp_registers, 0,sizeof(dsp_registers)); - bootstrap_pos = bootstrap_accum = 0; +/** + * Disassemble DSP code between given addresses, return next PC address + */ +Uint32 DSP_DisasmAddress(Uint16 lowerAdr, Uint16 UpperAdr) +{ +#if ENABLE_DSP_EMU + Uint32 dsp_pc; + dsp_core_t *ptr1, *ptr2; - /* 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]; } - /* Destroy the semaphore */ - if (dsp56k_sem != NULL) { - SDL_DestroySemaphore(dsp56k_sem); - dsp56k_sem = 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; } -/********************************** - * Force execution of DSP, till something - * to read from/write to host port - **********************************/ -static inline void DSP_force_exec(void) +/** + * 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 DSP_HOST_FORCEEXEC - while (state == DSP_RUNNING) { +#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 == 0xffeb || mem == 0xffef)) { + 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); + } + 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; } -#endif /* DSP_EMULATION */ - -/********************************** - * Hardware address read/write by CPU - **********************************/ -static uint8 DSP_handleRead(Uint32 addr) +void DSP_DisasmRegisters(void) { -#if DSP_EMULATION - uint8 value=0; +#if ENABLE_DSP_EMU + Uint32 i; - addr -= getHWoffset(); + 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]); -/* D(bug("HWget_b(0x%08x)=0x%02x at 0x%08x", addr+HW_DSP, value, showPC()));*/ + 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]); + } - /* Whenever the host want to read something on host port, we test if a - transfer is needed */ - DSP_dsp2host(); + 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 +} - 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")); -#endif - } +/** + * 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 ENABLE_DSP_EMU +#define MAX_REGNAME_LEN 4 + typedef struct { + const char name[MAX_REGNAME_LEN]; + Uint32 *addr; + size_t bits; + Uint32 mask; + } reg_addr_t; + + /* sorted by name so that this can be bisected */ + static const reg_addr_t registers[] = { - /* Wake up DSP if it was waiting our read */ - if (dsp_state==DSP_WAITHOSTREAD) { -#if DSP_DISASM_STATE - D(bug("Dsp: state = DSP_RUNNING")); + /* 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(regname[i]); + } + if (i < 2 || regname[i]) { + /* too short or longer than any of the names */ + return 0; + } + len = i; + + /* bisect */ + l = 0; + r = sizeof (registers) / sizeof (*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 - dsp_state = DSP_RUNNING; + return 0; +} + - if (SDL_SemValue(dsp56k_sem)==0) { - SDL_SemPost(dsp56k_sem); +/** + * 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; } - - break; + 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; + } + } } - return value; -#else - return 0xff; // this value prevents TOS from hanging in the DSP init code */ -#endif /* DSP_EMULATION */ + /* ...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 + return false; } -void DSP_HandleReadAccess(void) +/** + * Read SSI transmit value + */ +Uint32 DSP_SsiReadTxValue(void) { - Uint32 a; - Uint8 v; - for (a = IoAccessBaseAddress; a < IoAccessBaseAddress+nIoMemAccessSize; a++) - { - v = DSP_handleRead(a); - IoMem_WriteByte(a, v); - } +#if ENABLE_DSP_EMU + return dsp_core.ssi.transmit_value; +#else + return 0; +#endif } -static void DSP_handleWrite(Uint32 addr, uint8 value) +/** + * Write SSI receive value + */ +void DSP_SsiWriteRxValue(Uint32 value) { -#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")); +#if ENABLE_DSP_EMU + dsp_core.ssi.received_value = value & 0xffffff; #endif +} - 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; - } +/** + * Signal SSI clock tick to DSP + */ - break; - } -#endif /* DSP_EMULATION */ +void DSP_SsiReceive_SC0(void) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC0(&dsp_core); +#endif } -void DSP_HandleWriteAccess(void) +void DSP_SsiTransmit_SC0(void) { - Uint32 a; - Uint8 v; - for (a = IoAccessBaseAddress; a < IoAccessBaseAddress+nIoMemAccessSize; a++) - { - v = IoMem_ReadByte(a); - DSP_handleWrite(a,v); - } +#if ENABLE_DSP_EMU +#endif } - -#if DSP_EMULATION - -/********************************** - * Host transfer - **********************************/ - -void DSP_host2dsp(void) +void DSP_SsiReceive_SC1(Uint32 FrameCounter) { - 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])); +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC1(&dsp_core, FrameCounter); #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_SC1(void) +{ +#if ENABLE_DSP_EMU + Crossbar_DmaPlayInHandShakeMode(); #endif +} - /* Set TXDE bit to say that host can write */ - dsp_hostport[CPU_HOST_ISR] |= 1<D): Host TXDE set")); +void DSP_SsiReceive_SC2(Uint32 FrameCounter) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC2(&dsp_core, 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_dsp2host(void) +void DSP_SsiTransmit_SC2(Uint32 frame) { - /* 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; +#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(&dsp_core); #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) + */ +void DSP_HandleReadAccess(void) +{ + Uint32 addr; + Uint8 value; + for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++) + { +#if ENABLE_DSP_EMU + value = dsp_core_read_host(&dsp_core, addr-DSP_HW_OFFSET); +#else + /* this value prevents TOS from hanging in the DSP init code */ + value = 0xff; #endif + + 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) + */ +void DSP_HandleWriteAccess(void) +{ + Uint32 addr; + Uint8 value; + 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); +#endif + } +}