/*************************************************************************** dsp56k.c Core implementation for the portable DSP56k emulator. Written by Andrew Gardner **************************************************************************** Note: This CPU emulator is very much a work-in-progress. Thus far, it appears to be complete enough to run the memory tests for Polygonet Commanders. Some particularly WIP-like features of this core are as follows : * I ask many questions about my code throughout the core * The BITS(bits,op) macro is fine for a disassembler, but VERY slow for the inner loops of an executing core. This will go away someday ***************************************************************************/ #include "debugger.h" #include "dsp56k.h" // #define PC_E000 /*************************************************************************** MACROS ***************************************************************************/ // ??? Are there namespace collision issues with just defining something "PC" ??? // ...doesn't seem like it, but one never knows... // Register macros #define PC dsp56k.pcuProgramCounter #define SR dsp56k.pcuStatus #define OMR dsp56k.pcuOperatingModeReg #define SP dsp56k.pcuStackPointer #define LA dsp56k.pcuLoopAddressReg #define LC dsp56k.pcuLoopCounter #define SSH dsp56k.pcuSystemStack[SP].w.h #define SSL dsp56k.pcuSystemStack[SP].w.l #define X dsp56k.aluDataRegs[0].d #define X1 dsp56k.aluDataRegs[0].w.h #define X0 dsp56k.aluDataRegs[0].w.l #define Y dsp56k.aluDataRegs[1].d #define Y1 dsp56k.aluDataRegs[1].w.h #define Y0 dsp56k.aluDataRegs[1].w.l #define A dsp56k.aluAccumRegs[0].lw #define A2 dsp56k.aluAccumRegs[0].b.h4 #define A1 dsp56k.aluAccumRegs[0].w.h #define A0 dsp56k.aluAccumRegs[0].w.l #define B dsp56k.aluAccumRegs[1].lw #define B2 dsp56k.aluAccumRegs[1].b.h4 #define B1 dsp56k.aluAccumRegs[1].w.h #define B0 dsp56k.aluAccumRegs[1].w.l #define R0 dsp56k.aguAddressRegs[0] #define R1 dsp56k.aguAddressRegs[1] #define R2 dsp56k.aguAddressRegs[2] #define R3 dsp56k.aguAddressRegs[3] #define N0 dsp56k.aguOffsetRegs[0] #define N1 dsp56k.aguOffsetRegs[1] #define N2 dsp56k.aguOffsetRegs[2] #define N3 dsp56k.aguOffsetRegs[3] #define M0 dsp56k.aguModifierRegs[0] #define M1 dsp56k.aguModifierRegs[1] #define M2 dsp56k.aguModifierRegs[2] #define M3 dsp56k.aguModifierRegs[3] #define TEMP dsp56k.aguTempReg #define STATUS dsp56k.aguStatusReg // The CPU Stack #define ST0 dsp56k.pcuSystemStack[0].d #define ST1 dsp56k.pcuSystemStack[1].d #define ST2 dsp56k.pcuSystemStack[2].d #define ST3 dsp56k.pcuSystemStack[3].d #define ST4 dsp56k.pcuSystemStack[4].d #define ST5 dsp56k.pcuSystemStack[5].d #define ST6 dsp56k.pcuSystemStack[6].d #define ST7 dsp56k.pcuSystemStack[7].d #define ST8 dsp56k.pcuSystemStack[8].d #define ST9 dsp56k.pcuSystemStack[9].d #define ST10 dsp56k.pcuSystemStack[10].d #define ST11 dsp56k.pcuSystemStack[11].d #define ST12 dsp56k.pcuSystemStack[12].d #define ST13 dsp56k.pcuSystemStack[13].d #define ST14 dsp56k.pcuSystemStack[14].d #define ST15 dsp56k.pcuSystemStack[15].d // !!! Is there really only 15 of them, or is there 16 ??? // Other #define OP dsp56k.op // Peripheral RAM id's and addresses #define PBCa (0xffc0-0xffc0) #define PCCa (0xffc1-0xffc0) #define PBDDRa (0xffc2-0xffc0) #define PCDDRa (0xffc3-0xffc0) #define PBC (dsp56k_peripheral_ram[PBCa]) #define PCC (dsp56k_peripheral_ram[PCCa]) #define PBDDR (dsp56k_peripheral_ram[PBDDRa]) #define PCDDR (dsp56k_peripheral_ram[PCDDRa]) #define HCRa (0xffc4-0xffc0) #define HCR (dsp56k_peripheral_ram[HCRa]) #define COCRa (0xffc8-0xffc0) #define COCR (dsp56k_peripheral_ram[COCR]) #define CRASSI0a (0xffd0-0xffc0) #define CRBSSI0a (0xffd1-0xffc0) #define CRASSI0 (dsp56k_peripheral_ram[CRASSI0a]) #define CRBSSI0 (dsp56k_peripheral_ram[CRBSSI0a]) #define CRASSI1a (0xffd8-0xffc0) #define CRBSSI1a (0xffd9-0xffc0) #define CRASSI1 (dsp56k_peripheral_ram[CRASSI1a]) #define CRBSSI1 (dsp56k_peripheral_ram[CRBSSI1a]) #define PLCRa (0xffdc-0xffc0) #define PLCR (dsp56k_peripheral_ram[PLCRa]) #define BCRa (0xffde-0xffc0) #define IPRa (0xffdf-0xffc0) #define BCR (dsp56k_peripheral_ram[BCRa]) #define IPR (dsp56k_peripheral_ram[IPRa]) #define PBDa (0xffe2-0xffc0) #define PCDa (0xffe3-0xffc0) #define HSRa (0xffe4-0xffc0) #define PBD (dsp56k_peripheral_ram[PBDa]) #define PCD (dsp56k_peripheral_ram[PCDa]) #define HSR (dsp56k_peripheral_ram[HSRa]) #define HTXHRXa (0xffe5-0xffc0) #define HTXHRX (dsp56k_peripheral_ram[HTXHRXa]) #define COSRa (0xffe8-0xffc0) #define CRXCTXa (0xffe9-0xffc0) #define COSR (dsp56k_peripheral_ram[COSRa]) #define CRXCTX (dsp56k_peripheral_ram[CRXCTXa]) #define TCRa (0xffec-0xffc0) #define TCTRa (0xffed-0xffc0) #define TCPRa (0xffee-0xffc0) #define TPRa (0xffef-0xffc0) #define TCR (dsp56k_peripheral_ram[TCRa]) #define TCTR (dsp56k_peripheral_ram[TCTRa]) #define TCPR (dsp56k_peripheral_ram[TCPRa]) #define TPR (dsp56k_peripheral_ram[TPRa]) #define TSRSSI0a (0xfff0-0xffc0) #define TRXSSI0a (0xfff1-0xffc0) #define RSMA0a (0xfff2-0xffc0) #define RSMB0a (0xfff3-0xffc0) #define TSMA0a (0xfff4-0xffc0) #define TSMB0a (0xfff5-0xffc0) #define TSRSSI0 (dsp56k_peripheral_ram[TSRSSI0a]) #define TRXSSI0 (dsp56k_peripheral_ram[TRXSSI0a]) #define RSMA0 (dsp56k_peripheral_ram[RSMA0a]) #define RSMB0 (dsp56k_peripheral_ram[RSMB0a]) #define TSMA0 (dsp56k_peripheral_ram[TSMA0a]) #define TSMB0 (dsp56k_peripheral_ram[TSMB0a]) #define TSRSSI1a (0xfff8-0xffc0) #define TRXSSI1a (0xfff9-0xffc0) #define RSMA1a (0xfffa-0xffc0) #define RSMB1a (0xfffb-0xffc0) #define TSMA1a (0xfffc-0xffc0) #define TSMB1a (0xfffd-0xffc0) #define TSRSSI1 (dsp56k_peripheral_ram[TSRSSI1a]) #define TRXSSI1 (dsp56k_peripheral_ram[TRXSSI1a]) #define RSMA1 (dsp56k_peripheral_ram[RSMA1a]) #define RSMB1 (dsp56k_peripheral_ram[RSMB1a]) #define TSMA1 (dsp56k_peripheral_ram[TSMA1a]) #define TSMB1 (dsp56k_peripheral_ram[TSMB1a]) // Status Register Bits #define lfBIT ((SR & 0x8000) != 0) #define fvBIT ((SR & 0x4000) != 0) #define s1BIT ((SR & 0x0800) != 0) #define s0BIT ((SR & 0x0400) != 0) #define i1BIT ((SR & 0x0200) != 0) #define i0BIT ((SR & 0x0100) != 0) #define sBIT ((SR & 0x0080) != 0) #define lBIT ((SR & 0x0040) != 0) #define eBIT ((SR & 0x0020) != 0) #define uBIT ((SR & 0x0010) != 0) #define nBIT ((SR & 0x0008) != 0) #define zBIT ((SR & 0x0004) != 0) #define vBIT ((SR & 0x0002) != 0) #define cBIT ((SR & 0x0001) != 0) #define CLEAR_lfBIT() (SR &= (~0x8000)) #define CLEAR_fvBIT() (SR &= (~0x4000)) #define CLEAR_s1BIT() (SR &= (~0x0800)) #define CLEAR_s0BIT() (SR &= (~0x0400)) #define CLEAR_i1BIT() (SR &= (~0x0200)) #define CLEAR_i0BIT() (SR &= (~0x0100)) #define CLEAR_sBIT() (SR &= (~0x0080)) #define CLEAR_lBIT() (SR &= (~0x0040)) #define CLEAR_eBIT() (SR &= (~0x0020)) #define CLEAR_uBIT() (SR &= (~0x0010)) #define CLEAR_nBIT() (SR &= (~0x0008)) #define CLEAR_zBIT() (SR &= (~0x0004)) #define CLEAR_vBIT() (SR &= (~0x0002)) #define CLEAR_cBIT() (SR &= (~0x0001)) #define SET_lfBIT() (SR |= 0x8000) #define SET_fvBIT() (SR |= 0x4000) #define SET_s1BIT() (SR |= 0x0800) #define SET_s0BIT() (SR |= 0x0400) #define SET_i1BIT() (SR |= 0x0200) #define SET_i0BIT() (SR |= 0x0100) #define SET_sBIT() (SR |= 0x0080) #define SET_lBIT() (SR |= 0x0040) #define SET_eBIT() (SR |= 0x0020) #define SET_uBIT() (SR |= 0x0010) #define SET_nBIT() (SR |= 0x0008) #define SET_zBIT() (SR |= 0x0004) #define SET_vBIT() (SR |= 0x0002) #define SET_cBIT() (SR |= 0x0001) // Stack Pointer Bits #define ufBIT ((SP & 0x20) != 0) #define seBIT ((SP & 0x10) != 0) #define CLEAR_ufBIT() (SP &= (~0x20)) #define CLEAR_seBIT() (SP &= (~0x10)) #define SET_ufBIT() (SP |= 0x20) #define SET_seBIT() (SP |= 0x10) // Operating Mode Register Bits #define cdBIT ((OMR & 0x80) != 0) #define sdBIT ((OMR & 0x40) != 0) #define rBIT ((OMR & 0x20) != 0) #define saBIT ((OMR & 0x10) != 0) #define mcBIT ((OMR & 0x04) != 0) #define mbBIT ((OMR & 0x02) != 0) #define maBIT ((OMR & 0x01) != 0) #define CLEAR_cdBIT() (OMR &= (~0x80)) #define CLEAR_sdBIT() (OMR &= (~0x40)) #define CLEAR_rBIT() (OMR &= (~0x20)) #define CLEAR_saBIT() (OMR &= (~0x10)) #define CLEAR_mcBIT() (OMR &= (~0x04)) #define CLEAR_mbBIT() (OMR &= (~0x02)) #define CLEAR_maBIT() (OMR &= (~0x01)) #define SET_cdBIT() (OMR |= 0x80) #define SET_sdBIT() (OMR |= 0x40) #define SET_rBIT() (OMR |= 0x20) #define SET_saBIT() (OMR |= 0x10) #define SET_mcBIT() (OMR |= 0x04) #define SET_mbBIT() (OMR |= 0x02) #define SET_maBIT() (OMR |= 0x01) // Interrupt Priority Register Bits #define tl1BIT ((IPR & 0x8000) != 0) #define tl0BIT ((IPR & 0x4000) != 0) #define s1l1BIT ((IPR & 0x2000) != 0) #define s1l0BIT ((IPR & 0x1000) != 0) #define s0l1BIT ((IPR & 0x0800) != 0) #define s0l0BIT ((IPR & 0x0400) != 0) #define hl1BIT ((IPR & 0x0200) != 0) #define hl0BIT ((IPR & 0x0100) != 0) #define cl1BIT ((IPR & 0x0080) != 0) #define cl0BIT ((IPR & 0x0040) != 0) #define ibl2BIT ((IPR & 0x0020) != 0) #define ibl1BIT ((IPR & 0x0010) != 0) #define ibl0BIT ((IPR & 0x0008) != 0) #define ial2BIT ((IPR & 0x0004) != 0) #define ial1BIT ((IPR & 0x0002) != 0) #define ial0BIT ((IPR & 0x0001) != 0) #define CLEAR_tl1BIT() (IPR &= (~0x8000)) #define CLEAR_tl0BIT() (IPR &= (~0x4000)) #define CLEAR_s1l1BIT() (IPR &= (~0x2000)) #define CLEAR_s1l0BIT() (IPR &= (~0x1000)) #define CLEAR_s0l1BIT() (IPR &= (~0x0800)) #define CLEAR_s0l0BIT() (IPR &= (~0x0400)) #define CLEAR_hl1BIT() (IPR &= (~0x0200)) #define CLEAR_hl0BIT() (IPR &= (~0x0100)) #define CLEAR_cl1BIT() (IPR &= (~0x0080)) #define CLEAR_cl0BIT() (IPR &= (~0x0040)) #define CLEAR_ibl2BIT() (IPR &= (~0x0020)) #define CLEAR_ibl1BIT() (IPR &= (~0x0010)) #define CLEAR_ibl0BIT() (IPR &= (~0x0008)) #define CLEAR_ial2BIT() (IPR &= (~0x0004)) #define CLEAR_ial1BIT() (IPR &= (~0x0002)) #define CLEAR_ial0BIT() (IPR &= (~0x0001)) #define SET_tl1BIT() (IPR |= 0x8000) #define SET_tl0BIT() (IPR |= 0x4000) #define SET_s1l1BIT() (IPR |= 0x2000) #define SET_s1l0BIT() (IPR |= 0x1000) #define SET_s0l1BIT() (IPR |= 0x0800) #define SET_s0l0BIT() (IPR |= 0x0400) #define SET_hl1BIT() (IPR |= 0x0200) #define SET_hl0BIT() (IPR |= 0x0100) #define SET_cl1BIT() (IPR |= 0x0080) #define SET_cl0BIT() (IPR |= 0x0040) #define SET_ibl2BIT() (IPR |= 0x0020) #define SET_ibl1BIT() (IPR |= 0x0010) #define SET_ibl0BIT() (IPR |= 0x0008) #define SET_ial2BIT() (IPR |= 0x0004) #define SET_ial1BIT() (IPR |= 0x0002) #define SET_ial0BIT() (IPR |= 0x0001) // Bus Control Register Bits #define rhBIT ((BCR & 0x8000) != 0) #define bsBIT ((BCR & 0x4000) != 0) #define CLEAR_rhBIT() (BCR &= (~0x8000)) #define CLEAR_bsBIT() (BCR &= (~0x4000)) #define SET_rhBIT() (BCR |= 0x8000) #define SET_bsBIT() (BCR |= 0x4000) // Port B Control Register Bits #define bcBIT ((PBC & 0x0001) != 0) #define CLEAR_bcBIT() (PBC &= (~0x0001)) #define SET_bcBIT() (PBC |= 0x0001) // HOST INTERFACE (dsp56k side) // Read/Write Host Control Register Bits #define hf3BIT ((HCR & 0x0010) != 0) #define hf2BIT ((HCR & 0x0008) != 0) #define hcieBIT ((HCR & 0x0004) != 0) #define htieBIT ((HCR & 0x0002) != 0) #define hrieBIT ((HCR & 0x0001) != 0) #define CLEAR_hf3BIT() (HCR &= (~0x0010)) #define CLEAR_hf2BIT() (HCR &= (~0x0008)) #define CLEAR_hcieBIT() (HCR &= (~0x0004)) #define CLEAR_htieBIT() (HCR &= (~0x0002)) #define CLEAR_hrieBIT() (HCR &= (~0x0001)) #define SET_hf3BIT() (HCR |= 0x0010) #define SET_hf2BIT() (HCR |= 0x0008) #define SET_hcieBIT() (HCR |= 0x0004) #define SET_htieBIT() (HCR |= 0x0002) #define SET_hrieBIT() (HCR |= 0x0001) // Read-only Host Status Register Bits #define dmaBIT ((HSR & 0x0080) != 0) #define hf1BIT ((HSR & 0x0010) != 0) #define hf0BIT ((HSR & 0x0008) != 0) #define hcpBIT ((HSR & 0x0004) != 0) #define htdeBIT ((HSR & 0x0002) != 0) #define hrdfBIT ((HSR & 0x0001) != 0) #define CLEAR_dmaBIT() (HSR &= (~0x0080)) #define CLEAR_hf1BIT() (HSR &= (~0x0010)) #define CLEAR_hf0BIT() (HSR &= (~0x0008)) #define CLEAR_hcpBIT() (HSR &= (~0x0004)) #define CLEAR_htdeBIT() (HSR &= (~0x0002)) #define CLEAR_hrdfBIT() (HSR &= (~0x0001)) #define SET_dmaBIT() (HSR |= 0x0080) #define SET_hf1BIT() (HSR |= 0x0010) #define SET_hf0BIT() (HSR |= 0x0008) #define SET_hcpBIT() (HSR |= 0x0004) #define SET_htdeBIT() (HSR |= 0x0002) #define SET_hrdfBIT() (HSR |= 0x0001) // HOST INTERFACE (host side) // Interrupt Control Register Bits #define x_initBIT ((dsp56k.HI.ICR & 0x0080) != 0) #define x_hm1BIT ((dsp56k.HI.ICR & 0x0040) != 0) #define x_hm0BIT ((dsp56k.HI.ICR & 0x0020) != 0) #define x_hf1BIT ((dsp56k.HI.ICR & 0x0010) != 0) #define x_hf0BIT ((dsp56k.HI.ICR & 0x0008) != 0) #define x_treqBIT ((dsp56k.HI.ICR & 0x0002) != 0) #define x_rreqBIT ((dsp56k.HI.ICR & 0x0001) != 0) #define CLEAR_x_initBIT() (dsp56k.HI.ICR &= (~0x0080)) #define CLEAR_x_hm1BIT() (dsp56k.HI.ICR &= (~0x0040)) #define CLEAR_x_hm0BIT() (dsp56k.HI.ICR &= (~0x0020)) #define CLEAR_x_hf1BIT() (dsp56k.HI.ICR &= (~0x0010)) #define CLEAR_x_hf0BIT() (dsp56k.HI.ICR &= (~0x0008)) #define CLEAR_x_treqBIT() (dsp56k.HI.ICR &= (~0x0002)) #define CLEAR_x_rreqBIT() (dsp56k.HI.ICR &= (~0x0001)) #define SET_x_initBIT() (dsp56k.HI.ICR |= 0x0080) #define SET_x_hm1BIT() (dsp56k.HI.ICR |= 0x0040) #define SET_x_hm0BIT() (dsp56k.HI.ICR |= 0x0020) #define SET_x_hf1BIT() (dsp56k.HI.ICR |= 0x0010) #define SET_x_hf0BIT() (dsp56k.HI.ICR |= 0x0008) #define SET_x_treqBIT() (dsp56k.HI.ICR |= 0x0002) #define SET_x_rreqBIT() (dsp56k.HI.ICR |= 0x0001) // Command Vector Register Bit #define x_hcBIT ((dsp56k.HI.CVR & 0x0080) != 0) #define CLEAR_x_hcBIT() (dsp56k.HI.CVR &= (~0x0080)) #define SET_x_hcBIT() (dsp56k.HI.CVR |= 0x0080) // Interrupt Status Register Bits #define x_hreqBIT ((dsp56k.HI.ISR & 0x0080) != 0) #define x_dmaBIT ((dsp56k.HI.ISR & 0x0040) != 0) #define x_hf3BIT ((dsp56k.HI.ISR & 0x0010) != 0) #define x_hf2BIT ((dsp56k.HI.ISR & 0x0008) != 0) #define x_trdyBIT ((dsp56k.HI.ISR & 0x0004) != 0) #define x_txdeBIT ((dsp56k.HI.ISR & 0x0002) != 0) #define x_rxdfBIT ((dsp56k.HI.ISR & 0x0001) != 0) #define CLEAR_x_hreqBIT() (dsp56k.HI.ISR &= (~0x0080)) #define CLEAR_x_dmaBIT() (dsp56k.HI.ISR &= (~0x0040)) #define CLEAR_x_hf3BIT() (dsp56k.HI.ISR &= (~0x0010)) #define CLEAR_x_hf2BIT() (dsp56k.HI.ISR &= (~0x0008)) #define CLEAR_x_trdyBIT() (dsp56k.HI.ISR &= (~0x0004)) #define CLEAR_x_txdeBIT() (dsp56k.HI.ISR &= (~0x0002)) #define CLEAR_x_rxdfBIT() (dsp56k.HI.ISR &= (~0x0001)) #define SET_x_hreqBIT() (dsp56k.HI.ISR |= 0x0080) #define SET_x_dmaBIT() (dsp56k.HI.ISR |= 0x0040) #define SET_x_hf3BIT() (dsp56k.HI.ISR |= 0x0010) #define SET_x_hf2BIT() (dsp56k.HI.ISR |= 0x0008) #define SET_x_trdyBIT() (dsp56k.HI.ISR |= 0x0004) #define SET_x_txdeBIT() (dsp56k.HI.ISR |= 0x0002) #define SET_x_rxdfBIT() (dsp56k.HI.ISR |= 0x0001) // Interrupt Vector Register Bits #define x_iv7BIT ((dsp56k.HI.IVR & 0x0080) != 0) #define x_iv6BIT ((dsp56k.HI.IVR & 0x0040) != 0) #define x_iv5BIT ((dsp56k.HI.IVR & 0x0020) != 0) #define x_iv4BIT ((dsp56k.HI.IVR & 0x0010) != 0) #define x_iv3BIT ((dsp56k.HI.IVR & 0x0008) != 0) #define x_iv2BIT ((dsp56k.HI.IVR & 0x0004) != 0) #define x_iv1BIT ((dsp56k.HI.IVR & 0x0002) != 0) #define x_iv0BIT ((dsp56k.HI.IVR & 0x0001) != 0) #define CLEAR_x_iv7BIT() (dsp56k.HI.IVR &= (~0x0080)) #define CLEAR_x_iv6BIT() (dsp56k.HI.IVR &= (~0x0040)) #define CLEAR_x_iv5BIT() (dsp56k.HI.IVR &= (~0x0020)) #define CLEAR_x_iv4BIT() (dsp56k.HI.IVR &= (~0x0010)) #define CLEAR_x_iv3BIT() (dsp56k.HI.IVR &= (~0x0008)) #define CLEAR_x_iv2BIT() (dsp56k.HI.IVR &= (~0x0004)) #define CLEAR_x_iv1BIT() (dsp56k.HI.IVR &= (~0x0002)) #define CLEAR_x_iv0BIT() (dsp56k.HI.IVR &= (~0x0001)) #define SET_x_iv7BIT() (dsp56k.HI.IVR | 0x0080) #define SET_x_iv6BIT() (dsp56k.HI.IVR | 0x0040) #define SET_x_iv5BIT() (dsp56k.HI.IVR | 0x0020) #define SET_x_iv4BIT() (dsp56k.HI.IVR | 0x0010) #define SET_x_iv3BIT() (dsp56k.HI.IVR | 0x0008) #define SET_x_iv2BIT() (dsp56k.HI.IVR | 0x0004) #define SET_x_iv1BIT() (dsp56k.HI.IVR | 0x0002) #define SET_x_iv0BIT() (dsp56k.HI.IVR | 0x0001) // IRQ Interfaces #define LINE_MODA (dsp56k.irq_modA) #define LINE_MODB (dsp56k.irq_modB) #define LINE_MODC (dsp56k.irq_modC) #define LINE_RESET (dsp56k.irq_reset) /*************************************************************************** STRUCTURES & TYPEDEFS ***************************************************************************/ // DSP56156 Host Interface - page 94 of DSP56156UM typedef struct { // DSP56156 SIDE // Three words in the DSP processor?s address space // UINT8 HCR $FFC4 // UINT8 HSR $FFE4 // UINT16 HTX $FFE5 - same as below // UINT16 HRX $FFE5 - same as above // HOST SIDE // The HI appears as a memory mapped peripheral, occupying 8 bytes in the host processor?s address space UINT8 TXHRXH, TXLRXL; UINT8 ICR; UINT8 CVR; UINT8 ISR; UINT8 IVR; // control lines available to the host UINT8 HA0, HA1, HA2; UINT8 hatHRW; UINT8 hatHEN; UINT8 hatHREQ; UINT8 hatHACK; } dsp56k_host_interface; // DSP56156 Registers - sizes specific to chip typedef struct { // See section 1-22 in DSP56156UM.pdf for scrutinization... // PCU Registers UINT16 pcuProgramCounter; // PC UINT16 pcuStatus; // MR,CCR / SR UINT16 pcuLoopCounter; // LC UINT16 pcuLoopAddressReg; // LA UINT8 pcuStackPointer; // SP UINT8 pcuOperatingModeReg; // OMR PAIR pcuSystemStack[16]; // SSH,SSL (*15) // ALU Registers PAIR aluDataRegs[2]; // X1,X0 & Y1,Y0 PAIR64 aluAccumRegs[2]; // A2,A1,A0 & B2,B1,B0 // AGU Registers UINT16 aguAddressRegs[4]; // R0,R1,R2,R3 UINT16 aguOffsetRegs[4]; // N0,N1,N2,N3 UINT16 aguModifierRegs[4]; // M0,M1,M2,M3 UINT16 aguTempReg; // TEMP UINT8 aguStatusReg; // Status // IRQ lines UINT8 irq_modA; // aka IRQA - can be defined edge or level sensitive (though i'm not sure how) UINT8 irq_modB; // aka IRQA - can be defined edge or level sensitive (though i'm not sure how) UINT8 irq_modC; // just modC :) UINT8 irq_reset; // Always level-sensitive int (*irq_callback)(int irqline); // Internal Stuff UINT32 ppc; // Previous PC - for debugger UINT16 op; // Current opcode int interrupt_cycles; int repFlag; // Knowing if we're in a 'repeat' state (dunno how the processor does this) UINT32 repAddr; // The address of the instruction to repeat... // Interfaces - ports B and C *can* be these if everything's setup right. dsp56k_host_interface HI; const void * config; } dsp56k_regs; /*************************************************************************** FUNCTION PROTOTYPES ***************************************************************************/ static void dsp56k_reset(void); /*************************************************************************** PRIVATE GLOBAL VARIABLES ***************************************************************************/ static dsp56k_regs dsp56k; static int dsp56k_icount; static UINT16 hack_memory_offset = 0; static UINT16 *dsp56k_peripheral_ram; static UINT16 *dsp56k_program_ram; /*************************************************************************** IRQ HANDLING ***************************************************************************/ static void check_irqs(void) { } static void set_irq_line(int irqline, int state) { if (irqline == 3) { LINE_RESET = state; if(LINE_RESET != CLEAR_LINE) { int irq_vector = (*dsp56k.irq_callback)(3); PC = irq_vector; LINE_RESET = CLEAR_LINE; } } } /*************************************************************************** CONTEXT SWITCHING ***************************************************************************/ static void dsp56k_get_context(void *dst) { /* copy the context */ if (dst) *(dsp56k_regs *)dst = dsp56k; } static void dsp56k_set_context(void *src) { /* copy the context */ if (src) dsp56k = *(dsp56k_regs *)src; memory_set_opbase(PC); /* check for IRQs */ check_irqs(); } /*************************************************************************** INITIALIZATION AND SHUTDOWN ***************************************************************************/ static void dsp56k_init(int index, int clock, const void *_config, int (*irqcallback)(int)) { dsp56k.config = _config; dsp56k.irq_callback = irqcallback; } static void dsp56k_reset_HI(void) { dsp56k.HI.CVR = 0x16; // clears HC and sets HL } // Page 101 (7-25) in the Family Manual static void dsp56k_reset(void) { if (dsp56k.config == NULL) { memory_set_opbase(PC); // Handle internal stuff dsp56k.interrupt_cycles = 0; // Internal peripheral devices are reset, and pins revert to general I/O pins // Modifier registers are set M0 = M1 = M2 = M3 = 0xffff; // BCR is set - the really slow bootup mode & the Bus State status bit high (0x4xxx) //BCR = 0x43ff; // Stack pointer is cleared SP = 0x00; // The docs say nothing about ufBIT & seBIT, but this should be right // Documentation says 'MR' is setup, but it really means 'SR' is setup SR = 0x0300; // Only the Interrupt mask bits of the Status Register are set upon reset // !!! GO THROUGH AND GET ALL THESE RIGHT SOMEDAY !!! HSR = 0x0000; SET_htdeBIT(); dsp56k_reset_HI(); OMR = 0x00; // All is cleared, except for the IRQ lines below IPR = 0x00; dsp56k.repFlag = 0; // Certainly not repeating to start dsp56k.repAddr = 0x0000; // Reset the address too... // Manipulate everything you need to for the ports (!! maybe these will be callbacks someday !!)... data_write_word_16le(0xffc0, 0x0000); // Sets Port B Control Register to general I/O data_write_word_16le(0xffc2, 0x0000); // Sets Port B Data Direction Register as input data_write_word_16le(0xffc1, 0x0000); // Sets Port C Control Register to general I/O data_write_word_16le(0xffc3, 0x0000); // Sets Port C Data Direction Register as input // Now that we're leaving, set ma, mb, and mc from MODA, MODB, and MODC lines // I believe polygonet sets everyone to mode 0... The following reflects this... CLEAR_maBIT(); CLEAR_mbBIT(); // switch bootup sequence based on chip operating mode switch((mbBIT << 1) | maBIT) { // [Special Bootstrap 1] Bootstrap from an external byte-wide memory located at P:$c000 case 0x0: PC = 0x0000; // 0x0030; // 0x0032; // 0x002e; // 0x0000; // 0x002c; break; // [Special Bootstrap 2] Bootstrap from the Host port or SSI0 case 0x1: PC = 0x0000; break; // [Normal Expanded] Internal PRAM enabled; External reset at P:$e000 case 0x2: PC = 0xe000; break; // [Development Expanded] Int. program memory disabled; Ext. reset at P:$0000 case 0x3: PC = 0x0000; break; } } else { PC = *((UINT16*)dsp56k.config); } } static void dsp56k_exit(void) { } /*************************************************************************** CORE INCLUDE ***************************************************************************/ #define ROPCODE(pc) cpu_readop16(pc) #include "dsp56ops.c" /*************************************************************************** CORE EXECUTION LOOP ***************************************************************************/ static int dsp56k_execute(int cycles) { /* skip if halted */ if (LINE_RESET) return cycles; dsp56k_icount = cycles; dsp56k_icount -= dsp56k.interrupt_cycles; dsp56k.interrupt_cycles = 0; while(dsp56k_icount > 0) execute_one(); dsp56k_icount -= dsp56k.interrupt_cycles; dsp56k.interrupt_cycles = 0; return cycles - dsp56k_icount; } /*************************************************************************** DISASSEMBLY HOOK ***************************************************************************/ extern offs_t dsp56k_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); /**************************************************************************** * Internal Memory Handlers ****************************************************************************/ static READ16_HANDLER( peripheral_register_r ) { // logerror("peripheral_register_r 0x%x\n", offset+0xffc0); switch (offset) { case HCRa: //ffc4 return HCR; break; case HSRa: //ffe4 return HSR; break; case HTXHRXa: //ffe5 // The HRX register contains valid data when the HRDF bit is set. // if (hrdfBIT) return HTXHRX; // Reading HRX clears HRDF. CLEAR_hrdfBIT(); // The DSP may program the HRIE bit to cause a Host Receive Data interrupt when HRDF is set. return 0x0000; break; } return dsp56k_peripheral_ram[offset]; } static WRITE16_HANDLER( peripheral_register_w ) { COMBINE_DATA(&dsp56k_peripheral_ram[offset]); logerror("peripheral_register_w 0x%x 0x%x (@%x)\n", offset+0xffc0, data, PC); switch (offset) { case HCRa: //ffc4 // The HCR register occupies the low order byte of the internal data bus - // the high order portion is zero-filled. // Changing HF2 will change the Host Flag 2 (HF2) bit of the Interrupt Status // Register ISR on the host processor side of the host interface. if (hf2BIT) SET_x_hf2BIT(); else CLEAR_x_hf2BIT(); // Changing HF3 will change the Host Flag 3 (HF3) bit of the Interrupt Status // Register ISR on the host processor side of the host interface. if (hf3BIT) { SET_x_hf3BIT(); } else CLEAR_x_hf3BIT(); break; case HSRa: //ffe4 /* READ ONLY */ break; case HTXHRXa: //ffe5 // ??? Can you write here even if you don't have the requirements? // Writing the HTX register clears HTDE (HSR bit 1) CLEAR_htdeBIT(); // The DSP may program the HTIE (HCR bit 1) bit to cause a Host Transmit Data // interrupt when HTDE is set // The HTX register is transferred as 16-bit data to the Receive Byte Registers // RXH:RXL if both the HTDE (HSR bit 1) bit and the Receive Data Full, // RXDF (ISR bit 0), status bit are cleared // printf("%d %d %x\n", htdeBIT, x_rxdfBIT, dsp56k_peripheral_ram[offset]); if ( !htdeBIT && !x_rxdfBIT ) { dsp56k.HI.TXHRXH = (HTXHRX & 0xff00) >> 8; dsp56k.HI.TXLRXL = (HTXHRX & 0x00ff); // This transfer operation sets RXDF (ISR bit 0) and HTDE (HSR bit 1). SET_x_rxdfBIT(); } break; } } UINT16 dsp56k_get_peripheral_memory(UINT16 addr) { if (addr >= 0xffc0) // && addr <= 0xffff { return dsp56k_peripheral_ram[addr-0xffc0]; } else { logerror("DSP56k - Peripheral memory requested does not exist\n"); return 0x00; } } /**************************************************************************** * Internal Memory Maps ****************************************************************************/ static ADDRESS_MAP_START( dsp56156_program_memory, ADDRESS_SPACE_PROGRAM, 16 ) AM_RANGE(0x0000, 0x07ff) AM_RAM AM_BASE(&dsp56k_program_ram) ADDRESS_MAP_END static ADDRESS_MAP_START( dsp56156_x_data_memory, ADDRESS_SPACE_DATA, 16 ) AM_RANGE(0x0000, 0x07ff) AM_RAM AM_RANGE(0xffc0, 0xffff) AM_READWRITE(peripheral_register_r, peripheral_register_w) AM_BASE(&dsp56k_peripheral_ram) ADDRESS_MAP_END /************************************************************************** * Host Interface (HI) functionality. **************************************************************************/ void dsp56k_host_interface_write(UINT8 addr, UINT8 data) { switch (addr) { case 0x0: // ICR dsp56k.HI.ICR = data; // Changing HF0 also changes the Host Flag bit 0 (HF0) of the Host Status register HSR on the DSP side of the HI. if (x_hf0BIT) SET_hf0BIT(); if (x_hf1BIT) SET_hf1BIT(); break; case 0x1: // CVR dsp56k.HI.CVR = data; // Normally the host processor sets HC=1 to request the host command // exception from the DSP. if (dsp56k.HI.CVR & 0x80) { // Setting HC (bit 0x80) causes HCP (Host Command Pending) to be set in the HSR register. The host // can write HC and HV in the same write cycle if desired. HC is cleared by DSP reset. SET_hcpBIT(); // reset the pc to the proper address logerror("RESET (%04x) sent\n", (dsp56k.HI.CVR & 0x1f) << 1); PC = (dsp56k.HI.CVR & 0x1f) << 1; // When the host command exception is taken by the DSP, the HC // bit is cleared by the HI hardware. CLEAR_x_hcBIT(); } break; case 0x2: break; // ISR - read only case 0x3: // IVR // 68000 series communication break; case 0x4: break; // Unused case 0x5: break; // Unused case 0x6: // TXH/RXH // Data may be written into the Transmit Byte Registers when the // Transmit Data Register Empty TXDE bit is set. if (!x_txdeBIT) { dsp56k.HI.TXHRXH = data; } break; case 0x7: // TXL/RXL // Data may be written into the Transmit Byte Registers when the // Transmit Data Register Empty TXDE bit is set. if (!x_txdeBIT) dsp56k.HI.TXLRXL = data; // writing the Transmit Low register TXL clears the TXDE bit CLEAR_x_txdeBIT(); // The Transmit Byte Registers TXH:TXL are transferred as 16-bit data to the Host Receive // Data Register HRX when both TXDE bit and the Host Receive Data Full, HRDF, bit are // cleared. if (!x_txdeBIT && !hrdfBIT) { HTXHRX = ( ((UINT16)dsp56k.HI.TXHRXH) << 8 ) | (UINT16)dsp56k.HI.TXLRXL; // !!! Hack !!! Move it straight to program memory... dsp56k_program_ram[hack_memory_offset] = HTXHRX; logerror("Wrote memoryOffset[%d] : %04x\n", hack_memory_offset, dsp56k_program_ram[hack_memory_offset]); hack_memory_offset++; // This transfer operation sets TXDE and HRDF. // SET_x_txdeBIT(); // SET_hrdfBIT(); } break; } } static int memtest3_hack=0; UINT8 dsp56k_host_interface_read(UINT8 addr) { UINT8 retVal = 0x00; switch(addr) { case 0x00: // ICR retVal = dsp56k.HI.ICR; break; case 0x01: // CVR retVal = dsp56k.HI.CVR; break; case 0x02: // ISR retVal = dsp56k.HI.ISR; /* We may need some *VERY* tight synchro at the end of the 3rd memory test in order to get this going right */ if ( (PC <= 0x125) && (PC >= 0x123) ) { /* Maybe this isn't needed? */ if (!memtest3_hack) { cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(100)); memtest3_hack++; } } break; case 0x03: // IVR retVal = dsp56k.HI.IVR; break; case 0x04: break; // Unused case 0x05: break; // Unused case 0x06: // RXH/TXH retVal = dsp56k.HI.TXHRXH; break; case 0x07: // RXL/TXL retVal = dsp56k.HI.TXLRXL; // RXDF is cleared when the Receive Data Low (RXL) register is read by the host processor. CLEAR_x_rxdfBIT(); SET_htdeBIT(); // !!! seems right ??? break; } return retVal; } /* HACK ! (maybe ;) */ void dsp56k_reset_dma_offset(void) { hack_memory_offset = 0; } /************************************************************************** * Generic set_info/get_info **************************************************************************/ static void dsp56k_set_info(UINT32 state, cpuinfo *info) { switch (state) { case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODA: set_irq_line(DSP56K_IRQ_MODA, info->i); break; case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODB: set_irq_line(DSP56K_IRQ_MODB, info->i); break; case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODC: set_irq_line(DSP56K_IRQ_MODC, info->i); break; case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_RESET: set_irq_line(DSP56K_IRQ_RESET, info->i); break; // !! It might be interesting to use this section as something which masks out the unecessary bits in each register !! 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: // !!! I think this is correct !!! 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; } } void dsp56k_get_info(UINT32 state, cpuinfo *info) { switch (state) { // --- the following bits of info are returned as 64-bit signed integers --- case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(dsp56k); break; case CPUINFO_INT_INPUT_LINES: info->i = 4; break; case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break; case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; 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; // ? case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -1; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 16; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 16; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = -1; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; // I think this is the ffc0-fff0 part of data memory? case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; // case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; // case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODA: info->i = LINE_MODA; break; case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODB: info->i = LINE_MODB; break; case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODC: info->i = LINE_MODC; break; case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_RESET: info->i = LINE_RESET; break; // Is reset a special case? case CPUINFO_INT_PREVIOUSPC: info->i = dsp56k.ppc; break; case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + DSP56K_PC: info->i = PC; break; 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: // !!! I think this is correct !!! case CPUINFO_INT_REGISTER + DSP56K_SP: info->i = SP; break; case CPUINFO_INT_REGISTER + DSP56K_OMR: info->i = OMR; break; case CPUINFO_INT_REGISTER + DSP56K_X: info->i = X; break; case CPUINFO_INT_REGISTER + DSP56K_Y: info->i = Y; break; case CPUINFO_INT_REGISTER + DSP56K_A: info->i = A; break; case CPUINFO_INT_REGISTER + DSP56K_B: info->i = B; 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 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; 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; case CPUINFO_INT_REGISTER + DSP56K_TEMP: info->i = TEMP; break; case CPUINFO_INT_REGISTER + DSP56K_STATUS: info->i = STATUS; break; // 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; // --- the following bits of info are returned as pointers to data or functions --- case CPUINFO_PTR_SET_INFO: info->setinfo = dsp56k_set_info; break; case CPUINFO_PTR_GET_CONTEXT: info->getcontext = dsp56k_get_context; break; case CPUINFO_PTR_SET_CONTEXT: info->setcontext = dsp56k_set_context; break; case CPUINFO_PTR_INIT: info->init = dsp56k_init; break; case CPUINFO_PTR_RESET: info->reset = dsp56k_reset; break; case CPUINFO_PTR_EXIT: info->exit = dsp56k_exit; break; case CPUINFO_PTR_EXECUTE: info->execute = dsp56k_execute; break; case CPUINFO_PTR_BURN: info->burn = NULL; break; #ifdef MAME_DEBUG case CPUINFO_PTR_DISASSEMBLE: info->disassemble = dsp56k_dasm; break; #endif /* MAME_DEBUG */ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &dsp56k_icount; break; case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map = construct_map_dsp56156_x_data_memory; break; case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_dsp56156_program_memory; break; case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map = 0; break; // --- the following bits of info are returned as NULL-terminated strings --- case CPUINFO_STR_NAME: strcpy(info->s, "DSP56156"); break; case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Motorola DSP56156"); break; case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.1"); break; case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Andrew Gardner"); break; case CPUINFO_STR_FLAGS: sprintf(info->s, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s %s%s %s%s%s%s%s%s%s", lfBIT ? "L":".", fvBIT ? "F":".", s1BIT ? "S":".", s0BIT ? "S":".", i1BIT ? "I":".", i0BIT ? "I":".", sBIT ? "S":".", lBIT ? "L":".", eBIT ? "E":".", uBIT ? "U":".", nBIT ? "N":".", zBIT ? "Z":".", vBIT ? "V":".", cBIT ? "C":".", ufBIT ? "U":".", seBIT ? "S":".", cdBIT ? "C":".", sdBIT ? "S":".", rBIT ? "R":".", saBIT ? "S":".", mcBIT ? "M":".", mbBIT ? "M":".", maBIT ? "M":"."); 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 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; // !! This is silly - it gives me a warning if I try to print an unsigned long with %08x // (and thus won't compile) - any suggestions? Maybe we change it to a series of UINT16's or something? 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 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; } }