summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/dsp32/dsp32.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/dsp32/dsp32.c')
-rw-r--r--trunk/src/emu/cpu/dsp32/dsp32.c889
1 files changed, 889 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/dsp32/dsp32.c b/trunk/src/emu/cpu/dsp32/dsp32.c
new file mode 100644
index 00000000000..5bd0cd810fb
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp32/dsp32.c
@@ -0,0 +1,889 @@
+/***************************************************************************
+
+ dsp32.c
+ Core implementation for the portable DSP32 emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Important note:
+
+ At this time, the emulator is rather incomplete. However, it is
+ sufficiently complete to run both Race Drivin' and Hard Drivin's
+ Airborne, which is all I was after.
+
+ Things that still need to be implemented:
+
+ * interrupts
+ * carry-reverse add operations
+ * do loops
+ * ieee/dsp conversions
+ * input/output conversion
+ * serial I/O
+
+ In addition, there are several optimizations enabled which make
+ assumptions about the code which may not be valid for other
+ applications. Check dsp32ops.c for details.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "dsp32.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define DETECT_MISALIGNED_MEMORY 0
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// internal register numbering for PIO registers
+#define PIO_PAR 0
+#define PIO_PDR 1
+#define PIO_EMR 2
+#define PIO_ESR 3
+#define PIO_PCR 4
+#define PIO_PIR 5
+#define PIO_PARE 6
+#define PIO_PDR2 7
+#define PIO_RESERVED 8
+
+#define UPPER (0x00ff << 8)
+#define LOWER (0xff00 << 8)
+
+// bits in the PCR register
+#define PCR_RESET 0x001
+#define PCR_REGMAP 0x002
+#define PCR_ENI 0x004
+#define PCR_DMA 0x008
+#define PCR_AUTO 0x010
+#define PCR_PDFs 0x020
+#define PCR_PIFs 0x040
+#define PCR_RES 0x080
+#define PCR_DMA32 0x100
+#define PCR_PIO16 0x200
+#define PCR_FLG 0x400
+
+// internal flag bits
+#define UFLAGBIT 1
+#define VFLAGBIT 2
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// register mapping
+#define R0 m_r[0]
+#define R1 m_r[1]
+#define R2 m_r[2]
+#define R3 m_r[3]
+#define R4 m_r[4]
+#define R5 m_r[5]
+#define R6 m_r[6]
+#define R7 m_r[7]
+#define R8 m_r[8]
+#define R9 m_r[9]
+#define R10 m_r[10]
+#define R11 m_r[11]
+#define R12 m_r[12]
+#define R13 m_r[13]
+#define R14 m_r[14]
+#define PC m_r[15]
+#define R0_ALT m_r[16]
+#define R15 m_r[17]
+#define R16 m_r[18]
+#define R17 m_r[19]
+#define R18 m_r[20]
+#define R19 m_r[21]
+#define RMM m_r[22]
+#define RPP m_r[23]
+#define R20 m_r[24]
+#define R21 m_r[25]
+#define DAUC m_r[26]
+#define IOC m_r[27]
+#define R22 m_r[29]
+#define PCSH m_r[30]
+
+#define A0 m_a[0]
+#define A1 m_a[1]
+#define A2 m_a[2]
+#define A3 m_a[3]
+#define A_0 m_a[4]
+#define A_1 m_a[5]
+
+#define zFLAG ((m_nzcflags & 0xffffff) == 0)
+#define nFLAG ((m_nzcflags & 0x800000) != 0)
+#define cFLAG ((m_nzcflags & 0x1000000) != 0)
+#define vFLAG ((m_vflags & 0x800000) != 0)
+#define ZFLAG (m_NZflags == 0)
+#define NFLAG (m_NZflags < 0)
+#define UFLAG (m_VUflags & UFLAGBIT)
+#define VFLAG (m_VUflags & VFLAGBIT)
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+const device_type DSP32C = &device_creator<dsp32c_device>;
+
+//-------------------------------------------------
+// dsp32c_device - constructor
+//-------------------------------------------------
+
+dsp32c_device::dsp32c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, DSP32C, "DSP32C", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 32, 24),
+ m_pin(0),
+ m_pout(0),
+ m_ivtp(0),
+ m_nzcflags(0),
+ m_vflags(0),
+ m_NZflags(0),
+ m_VUflags(0),
+ m_abuf_index(0),
+ m_mbuf_index(0),
+ m_par(0),
+ m_pare(0),
+ m_pdr(0),
+ m_pdr2(0),
+ m_pir(0),
+ m_pcr(0),
+ m_emr(0),
+ m_esr(0),
+ m_pcw(0),
+ m_piop(0),
+ m_ibuf(0),
+ m_isr(0),
+ m_obuf(0),
+ m_osr(0),
+ m_iotemp(0),
+ m_lastp(0),
+ m_icount(0),
+ m_lastpins(0),
+ m_ppc(0),
+ m_program(NULL),
+ m_direct(NULL)
+{
+ m_output_pins_changed = NULL;
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// static_set_config - set the configuration
+// structure
+//-------------------------------------------------
+
+void dsp32c_device::static_set_config(device_t &device, const dsp32_config &config)
+{
+ dsp32c_device &dsp = downcast<dsp32c_device &>(device);
+ static_cast<dsp32_config &>(dsp) = config;
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void dsp32c_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ // register our state for the debugger
+ astring tempstr;
+ state_add(STATE_GENPC, "GENPC", m_r[15]).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_r[21]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_iotemp).callimport().callexport().formatstr("%6s").noshow();
+ state_add(DSP32_PC, "PC", m_r[15]).mask(0xffffff);
+ for (int regnum = 0; regnum <= 14; regnum++)
+ state_add(DSP32_R0 + regnum, tempstr.format("R%d", regnum), m_r[regnum]).mask(0xffffff);
+ state_add(DSP32_R15, "R15", m_r[17]).mask(0xffffff);
+ state_add(DSP32_R16, "R16", m_r[18]).mask(0xffffff);
+ state_add(DSP32_R17, "R17", m_r[19]).mask(0xffffff);
+ state_add(DSP32_R18, "R18", m_r[20]).mask(0xffffff);
+ state_add(DSP32_R19, "R19", m_r[21]).mask(0xffffff);
+ state_add(DSP32_R20, "R20", m_r[24]).mask(0xffffff);
+ state_add(DSP32_R21, "R21", m_r[25]).mask(0xffffff);
+ state_add(DSP32_R22, "R22", m_r[29]).mask(0xffffff);
+ state_add(DSP32_PIN, "PIN", m_pin).mask(0xffffff);
+ state_add(DSP32_POUT, "POUT", m_pout).mask(0xffffff);
+ state_add(DSP32_IVTP, "IVTP", m_ivtp).mask(0xffffff);
+ state_add(DSP32_A0, "A0", m_a[0]).formatstr("%8s");
+ state_add(DSP32_A1, "A1", m_a[1]).formatstr("%8s");
+ state_add(DSP32_A2, "A2", m_a[2]).formatstr("%8s");
+ state_add(DSP32_A3, "A3", m_a[3]).formatstr("%8s");
+ state_add(DSP32_DAUC, "DAUC", m_r[26]).mask(0xff);
+ state_add(DSP32_PAR, "PAR", m_par);
+ state_add(DSP32_PDR, "PDR", m_pdr);
+ state_add(DSP32_PIR, "PIR", m_pir);
+ state_add(DSP32_PCR, "PCR", m_iotemp).mask(0x3ff).callimport();
+ state_add(DSP32_EMR, "EMR", m_emr);
+ state_add(DSP32_ESR, "ESR", m_esr);
+ state_add(DSP32_PCW, "PCW", m_pcw);
+ state_add(DSP32_PIOP, "PIOP", m_piop);
+ state_add(DSP32_IBUF, "IBUF", m_ibuf);
+ state_add(DSP32_ISR, "ISR", m_isr);
+ state_add(DSP32_OBUF, "OBUF", m_obuf);
+ state_add(DSP32_OSR, "OSR" , m_osr);
+ state_add(DSP32_IOC, "IOC", m_r[27]).mask(0xfffff);
+
+ // register our state for saving
+ save_item(NAME(m_r));
+ save_item(NAME(m_pin));
+ save_item(NAME(m_pout));
+ save_item(NAME(m_ivtp));
+ save_item(NAME(m_nzcflags));
+ save_item(NAME(m_vflags));
+ save_item(NAME(m_a));
+ save_item(NAME(m_NZflags));
+ save_item(NAME(m_VUflags));
+ save_item(NAME(m_abuf));
+ save_item(NAME(m_abufreg));
+ save_item(NAME(m_abufVUflags));
+ save_item(NAME(m_abufNZflags));
+ save_item(NAME(m_abufcycle));
+ save_item(NAME(m_abuf_index));
+ save_item(NAME(m_mbufaddr));
+ save_item(NAME(m_mbufdata));
+ save_item(NAME(m_par));
+ save_item(NAME(m_pare));
+ save_item(NAME(m_pdr));
+ save_item(NAME(m_pdr2));
+ save_item(NAME(m_pir));
+ save_item(NAME(m_pcr));
+ save_item(NAME(m_emr));
+ save_item(NAME(m_esr));
+ save_item(NAME(m_pcw));
+ save_item(NAME(m_piop));
+ save_item(NAME(m_ibuf));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_obuf));
+ save_item(NAME(m_osr));
+ save_item(NAME(m_lastpins));
+ save_item(NAME(m_ppc));
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void dsp32c_device::device_reset()
+{
+ // reset goes to 0
+ PC = 0;
+
+ // clear some registers
+ m_pcw &= 0x03ff;
+ update_pcr(m_pcr & PCR_RESET);
+ m_esr = 0;
+ m_emr = 0xffff;
+
+ // initialize fixed registers
+ R0 = R0_ALT = 0;
+ RMM = -1;
+ RPP = 1;
+ A_0 = 0.0;
+ A_1 = 1.0;
+
+ // init internal stuff
+ m_abufcycle[0] = m_abufcycle[1] = m_abufcycle[2] = m_abufcycle[3] = 12345678;
+ m_mbufaddr[0] = m_mbufaddr[1] = m_mbufaddr[2] = m_mbufaddr[3] = 1;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *dsp32c_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config : NULL;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void dsp32c_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ break;
+
+ case DSP32_PCR:
+ update_pcr(m_iotemp);
+ break;
+
+ default:
+ fatalerror("dsp32c_device::state_import called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_export - export state out of the device
+//-------------------------------------------------
+
+void dsp32c_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ // no actual flags register, so just make something up
+ m_iotemp = ((zFLAG != 0) << 0) |
+ ((nFLAG != 0) << 1) |
+ ((cFLAG != 0) << 2) |
+ ((vFLAG != 0) << 3) |
+ ((ZFLAG != 0) << 4) |
+ ((NFLAG != 0) << 5) |
+ ((UFLAG != 0) << 6) |
+ ((VFLAG != 0) << 7);
+ break;
+
+ case DSP32_PCR:
+ m_iotemp = m_pcr;
+ break;
+
+ default:
+ fatalerror("dsp32c_device::state_export called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void dsp32c_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ NFLAG ? 'N':'.',
+ ZFLAG ? 'Z':'.',
+ UFLAG ? 'U':'.',
+ VFLAG ? 'V':'.',
+ nFLAG ? 'n':'.',
+ zFLAG ? 'z':'.',
+ cFLAG ? 'c':'.',
+ vFLAG ? 'v':'.');
+ break;
+
+ case DSP32_A0:
+ case DSP32_A1:
+ case DSP32_A2:
+ case DSP32_A3:
+ string.printf("%8g", *(double *)entry.dataptr());
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp32c_device::disasm_min_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp32c_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t dsp32c_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( dsp32c );
+ return CPU_DISASSEMBLE_NAME(dsp32c)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+
+//**************************************************************************
+// MEMORY ACCESSORS
+//**************************************************************************
+
+inline UINT32 dsp32c_device::ROPCODE(offs_t pc)
+{
+ return m_direct->read_decrypted_dword(pc);
+}
+
+inline UINT8 dsp32c_device::RBYTE(offs_t addr)
+{
+ return m_program->read_byte(addr);
+}
+
+inline void dsp32c_device::WBYTE(offs_t addr, UINT8 data)
+{
+ m_program->write_byte(addr, data);
+}
+
+inline UINT16 dsp32c_device::RWORD(offs_t addr)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 1) fprintf(stderr, "Unaligned word read @ %06X, PC=%06X\n", addr, PC);
+#endif
+ return m_program->read_word(addr);
+}
+
+inline UINT32 dsp32c_device::RLONG(offs_t addr)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 3) fprintf(stderr, "Unaligned long read @ %06X, PC=%06X\n", addr, PC);
+#endif
+ return m_program->read_dword(addr);
+}
+
+inline void dsp32c_device::WWORD(offs_t addr, UINT16 data)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 1) fprintf(stderr, "Unaligned word write @ %06X, PC=%06X\n", addr, PC);
+#endif
+ m_program->write_word(addr, data);
+}
+
+inline void dsp32c_device::WLONG(offs_t addr, UINT32 data)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 3) fprintf(stderr, "Unaligned long write @ %06X, PC=%06X\n", addr, PC);
+#endif
+ m_program->write_dword(addr, data);
+}
+
+
+
+//**************************************************************************
+// IRQ HANDLING
+//**************************************************************************
+
+void dsp32c_device::check_irqs()
+{
+ // finish me!
+}
+
+
+void dsp32c_device::set_irq_line(int irqline, int state)
+{
+ // finish me!
+}
+
+
+
+//**************************************************************************
+// REGISTER HANDLING
+//**************************************************************************
+
+void dsp32c_device::update_pcr(UINT16 newval)
+{
+ UINT16 oldval = m_pcr;
+ m_pcr = newval;
+
+ // reset the chip if we get a reset
+ if ((oldval & PCR_RESET) == 0 && (newval & PCR_RESET) != 0)
+ reset();
+
+ // track the state of the output pins
+ if (m_output_pins_changed != NULL)
+ {
+ UINT16 newoutput = ((newval & (PCR_PIFs | PCR_ENI)) == (PCR_PIFs | PCR_ENI)) ? DSP32_OUTPUT_PIF : 0;
+ if (newoutput != m_lastpins)
+ {
+ m_lastpins = newoutput;
+ (*m_output_pins_changed)(*this, newoutput);
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// CORE INCLUDE
+//**************************************************************************
+
+#include "dsp32ops.c"
+
+
+
+//**************************************************************************
+// CORE EXECUTION LOOP
+//**************************************************************************
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp32c_device::execute_min_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp32c_device::execute_max_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 dsp32c_device::execute_input_lines() const
+{
+ return 2;
+}
+
+
+void dsp32c_device::execute_set_input(int inputnum, int state)
+{
+}
+
+
+void dsp32c_device::execute_run()
+{
+ // skip if halted
+ if ((m_pcr & PCR_RESET) == 0)
+ {
+ m_icount = 0;
+ return;
+ }
+
+ // update buffered accumulator values
+ m_abufcycle[0] += m_icount;
+ m_abufcycle[1] += m_icount;
+ m_abufcycle[2] += m_icount;
+ m_abufcycle[3] += m_icount;
+
+ // handle interrupts
+ check_irqs();
+
+ while (m_icount > 0)
+ execute_one();
+
+ // normalize buffered accumulator values
+ m_abufcycle[0] -= m_icount;
+ m_abufcycle[1] -= m_icount;
+ m_abufcycle[2] -= m_icount;
+ m_abufcycle[3] -= m_icount;
+}
+
+
+
+//**************************************************************************
+// PARALLEL INTERFACE WRITES
+//**************************************************************************
+
+const UINT32 dsp32c_device::s_regmap[4][16] =
+{
+ { // DSP32 compatible mode
+ PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
+ PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
+ PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER,
+ PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER
+ },
+ { // DSP32C 8-bit mode
+ PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
+ PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
+ PIO_PIR|LOWER, PIO_PIR|UPPER, PIO_PCR|UPPER, PIO_PARE|LOWER,
+ PIO_PDR2|LOWER,PIO_PDR2|UPPER,PIO_RESERVED, PIO_RESERVED
+ },
+ { // DSP32C illegal mode
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED
+ },
+ { // DSP32C 16-bit mode
+ PIO_PAR, PIO_RESERVED, PIO_PDR, PIO_RESERVED,
+ PIO_EMR, PIO_RESERVED, PIO_ESR|LOWER, PIO_PCR,
+ PIO_PIR, PIO_RESERVED, PIO_RESERVED, PIO_PARE|LOWER,
+ PIO_PDR2, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED
+ }
+};
+
+
+
+//**************************************************************************
+// PARALLEL INTERFACE WRITES
+//**************************************************************************
+
+void dsp32c_device::dma_increment()
+{
+ if (m_pcr & PCR_AUTO)
+ {
+ int amount = (m_pcr & PCR_DMA32) ? 4 : 2;
+ m_par += amount;
+ if (m_par < amount)
+ m_pare++;
+ }
+}
+
+
+void dsp32c_device::dma_load()
+{
+ // only process if DMA is enabled
+ if (m_pcr & PCR_DMA)
+ {
+ UINT32 addr = m_par | (m_pare << 16);
+
+ // 16-bit case
+ if (!(m_pcr & PCR_DMA32))
+ m_pdr = RWORD(addr & 0xfffffe);
+
+ // 32-bit case
+ else
+ {
+ UINT32 temp = RLONG(addr & 0xfffffc);
+ m_pdr = temp >> 16;
+ m_pdr2 = temp & 0xffff;
+ }
+
+ // set the PDF flag to indicate we have data ready
+ update_pcr(m_pcr | PCR_PDFs);
+ }
+}
+
+
+void dsp32c_device::dma_store()
+{
+ // only process if DMA is enabled
+ if (m_pcr & PCR_DMA)
+ {
+ UINT32 addr = m_par | (m_pare << 16);
+
+ // 16-bit case
+ if (!(m_pcr & PCR_DMA32))
+ WWORD(addr & 0xfffffe, m_pdr);
+
+ // 32-bit case
+ else
+ WLONG(addr & 0xfffffc, (m_pdr << 16) | m_pdr2);
+
+ // clear the PDF flag to indicate we have taken the data
+ update_pcr(m_pcr & ~PCR_PDFs);
+ }
+}
+
+
+void dsp32c_device::pio_w(int reg, int data)
+{
+ UINT16 mask;
+ UINT8 mode;
+
+ // look up register and mask
+ mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
+ reg = s_regmap[mode][reg];
+ mask = reg >> 8;
+ if (mask == 0x00ff) data <<= 8;
+ data &= ~mask;
+ reg &= 0xff;
+
+ // switch off the register
+ switch (reg)
+ {
+ case PIO_PAR:
+ m_par = (m_par & mask) | data;
+
+ // trigger a load on the upper half
+ if (!(mask & 0xff00))
+ dma_load();
+ break;
+
+ case PIO_PARE:
+ m_pare = (m_pare & mask) | data;
+ break;
+
+ case PIO_PDR:
+ m_pdr = (m_pdr & mask) | data;
+
+ // trigger a write and PDF setting on the upper half
+ if (!(mask & 0xff00))
+ {
+ dma_store();
+ dma_increment();
+ }
+ break;
+
+ case PIO_PDR2:
+ m_pdr2 = (m_pdr2 & mask) | data;
+ break;
+
+ case PIO_EMR:
+ m_emr = (m_emr & mask) | data;
+ break;
+
+ case PIO_ESR:
+ m_esr = (m_esr & mask) | data;
+ break;
+
+ case PIO_PCR:
+ mask |= 0x0060;
+ data &= ~mask;
+ update_pcr((m_pcr & mask) | data);
+ break;
+
+ case PIO_PIR:
+ m_pir = (m_pir & mask) | data;
+
+ // set PIF on upper half
+ if (!(mask & 0xff00))
+ update_pcr(m_pcr | PCR_PIFs);
+ break;
+
+ // error case
+ default:
+ logerror("dsp32_pio_w called on invalid register %d\n", reg);
+ break;
+ }
+}
+
+
+
+//**************************************************************************
+// PARALLEL INTERFACE READS
+//**************************************************************************
+
+int dsp32c_device::pio_r(int reg)
+{
+ UINT16 mask, result = 0xffff;
+ UINT8 mode, shift = 0;
+
+ // look up register and mask
+ mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
+ reg = s_regmap[mode][reg];
+ mask = reg >> 8;
+ if (mask == 0x00ff) mask = 0xff00, shift = 8;
+ reg &= 0xff;
+
+ // switch off the register
+ switch (reg)
+ {
+ case PIO_PAR:
+ result = m_par | 1;
+ break;
+
+ case PIO_PARE:
+ result = m_pare;
+ break;
+
+ case PIO_PDR:
+ result = m_pdr;
+
+ // trigger an increment on the lower half
+ if (shift != 8)
+ dma_increment();
+
+ // trigger a fetch on the upper half
+ if (!(mask & 0xff00))
+ dma_load();
+ break;
+
+ case PIO_PDR2:
+ result = m_pdr2;
+ break;
+
+ case PIO_EMR:
+ result = m_emr;
+ break;
+
+ case PIO_ESR:
+ result = m_esr;
+ break;
+
+ case PIO_PCR:
+ result = m_pcr;
+ break;
+
+ case PIO_PIR:
+ if (!(mask & 0xff00))
+ update_pcr(m_pcr & ~PCR_PIFs); // clear PIFs
+ result = m_pir;
+ break;
+
+ // error case
+ default:
+ logerror("dsp32_pio_w called on invalid register %d\n", reg);
+ break;
+ }
+
+ return (result >> shift) & ~mask;
+}