1
/***************************************************************************
4
Core implementation for the portable DSP32 emulator.
6
****************************************************************************
11
Redistribution and use in source and binary forms, with or without
12
modification, are permitted provided that the following conditions are
15
* Redistributions of source code must retain the above copyright
16
notice, this list of conditions and the following disclaimer.
17
* Redistributions in binary form must reproduce the above copyright
18
notice, this list of conditions and the following disclaimer in
19
the documentation and/or other materials provided with the
21
* Neither the name 'MAME' nor the names of its contributors may be
22
used to endorse or promote products derived from this software
23
without specific prior written permission.
25
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
26
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
29
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
POSSIBILITY OF SUCH DAMAGE.
37
****************************************************************************
41
At this time, the emulator is rather incomplete. However, it is
42
sufficiently complete to run both Race Drivin' and Hard Drivin's
43
Airborne, which is all I was after.
45
Things that still need to be implemented:
48
* carry-reverse add operations
50
* ieee/dsp conversions
51
* input/output conversion
54
In addition, there are several optimizations enabled which make
55
assumptions about the code which may not be valid for other
56
applications. Check dsp32ops.c for details.
58
***************************************************************************/
65
//**************************************************************************
67
//**************************************************************************
69
#define DETECT_MISALIGNED_MEMORY 0
73
//**************************************************************************
75
//**************************************************************************
77
// internal register numbering for PIO registers
86
#define PIO_RESERVED 8
88
#define UPPER (0x00ff << 8)
89
#define LOWER (0xff00 << 8)
91
// bits in the PCR register
92
#define PCR_RESET 0x001
93
#define PCR_REGMAP 0x002
96
#define PCR_AUTO 0x010
97
#define PCR_PDFs 0x020
98
#define PCR_PIFs 0x040
100
#define PCR_DMA32 0x100
101
#define PCR_PIO16 0x200
102
#define PCR_FLG 0x400
104
// internal flag bits
110
//**************************************************************************
112
//**************************************************************************
131
#define R0_ALT m_r[16]
153
#define zFLAG ((m_nzcflags & 0xffffff) == 0)
154
#define nFLAG ((m_nzcflags & 0x800000) != 0)
155
#define cFLAG ((m_nzcflags & 0x1000000) != 0)
156
#define vFLAG ((m_vflags & 0x800000) != 0)
157
#define ZFLAG (m_NZflags == 0)
158
#define NFLAG (m_NZflags < 0)
159
#define UFLAG (m_VUflags & UFLAGBIT)
160
#define VFLAG (m_VUflags & VFLAGBIT)
164
//**************************************************************************
166
//**************************************************************************
168
const device_type DSP32C = &device_creator<dsp32c_device>;
170
//-------------------------------------------------
171
// dsp32c_device - constructor
172
//-------------------------------------------------
174
dsp32c_device::dsp32c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
175
: cpu_device(mconfig, DSP32C, "DSP32C", tag, owner, clock),
176
m_program_config("program", ENDIANNESS_LITTLE, 32, 24),
208
m_output_pins_changed = NULL;
210
// set our instruction counter
211
m_icountptr = &m_icount;
215
//-------------------------------------------------
216
// static_set_config - set the configuration
218
//-------------------------------------------------
220
void dsp32c_device::static_set_config(device_t &device, const dsp32_config &config)
222
dsp32c_device &dsp = downcast<dsp32c_device &>(device);
223
static_cast<dsp32_config &>(dsp) = config;
227
//-------------------------------------------------
228
// device_start - start up the device
229
//-------------------------------------------------
231
void dsp32c_device::device_start()
233
// get our address spaces
234
m_program = space(AS_PROGRAM);
235
m_direct = &m_program->direct();
237
// register our state for the debugger
239
state_add(STATE_GENPC, "GENPC", m_r[15]).noshow();
240
state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
241
state_add(STATE_GENSP, "GENSP", m_r[21]).noshow();
242
state_add(STATE_GENFLAGS, "GENFLAGS", m_iotemp).callimport().callexport().formatstr("%6s").noshow();
243
state_add(DSP32_PC, "PC", m_r[15]).mask(0xffffff);
244
for (int regnum = 0; regnum <= 14; regnum++)
245
state_add(DSP32_R0 + regnum, tempstr.format("R%d", regnum), m_r[regnum]).mask(0xffffff);
246
state_add(DSP32_R15, "R15", m_r[17]).mask(0xffffff);
247
state_add(DSP32_R16, "R16", m_r[18]).mask(0xffffff);
248
state_add(DSP32_R17, "R17", m_r[19]).mask(0xffffff);
249
state_add(DSP32_R18, "R18", m_r[20]).mask(0xffffff);
250
state_add(DSP32_R19, "R19", m_r[21]).mask(0xffffff);
251
state_add(DSP32_R20, "R20", m_r[24]).mask(0xffffff);
252
state_add(DSP32_R21, "R21", m_r[25]).mask(0xffffff);
253
state_add(DSP32_R22, "R22", m_r[29]).mask(0xffffff);
254
state_add(DSP32_PIN, "PIN", m_pin).mask(0xffffff);
255
state_add(DSP32_POUT, "POUT", m_pout).mask(0xffffff);
256
state_add(DSP32_IVTP, "IVTP", m_ivtp).mask(0xffffff);
257
state_add(DSP32_A0, "A0", m_a[0]).formatstr("%8s");
258
state_add(DSP32_A1, "A1", m_a[1]).formatstr("%8s");
259
state_add(DSP32_A2, "A2", m_a[2]).formatstr("%8s");
260
state_add(DSP32_A3, "A3", m_a[3]).formatstr("%8s");
261
state_add(DSP32_DAUC, "DAUC", m_r[26]).mask(0xff);
262
state_add(DSP32_PAR, "PAR", m_par);
263
state_add(DSP32_PDR, "PDR", m_pdr);
264
state_add(DSP32_PIR, "PIR", m_pir);
265
state_add(DSP32_PCR, "PCR", m_iotemp).mask(0x3ff).callimport();
266
state_add(DSP32_EMR, "EMR", m_emr);
267
state_add(DSP32_ESR, "ESR", m_esr);
268
state_add(DSP32_PCW, "PCW", m_pcw);
269
state_add(DSP32_PIOP, "PIOP", m_piop);
270
state_add(DSP32_IBUF, "IBUF", m_ibuf);
271
state_add(DSP32_ISR, "ISR", m_isr);
272
state_add(DSP32_OBUF, "OBUF", m_obuf);
273
state_add(DSP32_OSR, "OSR" , m_osr);
274
state_add(DSP32_IOC, "IOC", m_r[27]).mask(0xfffff);
276
// register our state for saving
277
save_item(NAME(m_r));
278
save_item(NAME(m_pin));
279
save_item(NAME(m_pout));
280
save_item(NAME(m_ivtp));
281
save_item(NAME(m_nzcflags));
282
save_item(NAME(m_vflags));
283
save_item(NAME(m_a));
284
save_item(NAME(m_NZflags));
285
save_item(NAME(m_VUflags));
286
save_item(NAME(m_abuf));
287
save_item(NAME(m_abufreg));
288
save_item(NAME(m_abufVUflags));
289
save_item(NAME(m_abufNZflags));
290
save_item(NAME(m_abufcycle));
291
save_item(NAME(m_abuf_index));
292
save_item(NAME(m_mbufaddr));
293
save_item(NAME(m_mbufdata));
294
save_item(NAME(m_par));
295
save_item(NAME(m_pare));
296
save_item(NAME(m_pdr));
297
save_item(NAME(m_pdr2));
298
save_item(NAME(m_pir));
299
save_item(NAME(m_pcr));
300
save_item(NAME(m_emr));
301
save_item(NAME(m_esr));
302
save_item(NAME(m_pcw));
303
save_item(NAME(m_piop));
304
save_item(NAME(m_ibuf));
305
save_item(NAME(m_isr));
306
save_item(NAME(m_obuf));
307
save_item(NAME(m_osr));
308
save_item(NAME(m_lastpins));
309
save_item(NAME(m_ppc));
313
//-------------------------------------------------
314
// device_reset - reset the device
315
//-------------------------------------------------
317
void dsp32c_device::device_reset()
322
// clear some registers
324
update_pcr(m_pcr & PCR_RESET);
328
// initialize fixed registers
335
// init internal stuff
336
m_abufcycle[0] = m_abufcycle[1] = m_abufcycle[2] = m_abufcycle[3] = 12345678;
337
m_mbufaddr[0] = m_mbufaddr[1] = m_mbufaddr[2] = m_mbufaddr[3] = 1;
341
//-------------------------------------------------
342
// memory_space_config - return the configuration
343
// of the specified address space, or NULL if
344
// the space doesn't exist
345
//-------------------------------------------------
347
const address_space_config *dsp32c_device::memory_space_config(address_spacenum spacenum) const
349
return (spacenum == AS_PROGRAM) ? &m_program_config : NULL;
353
//-------------------------------------------------
354
// state_import - import state into the device,
355
// after it has been set
356
//-------------------------------------------------
358
void dsp32c_device::state_import(const device_state_entry &entry)
360
switch (entry.index())
366
update_pcr(m_iotemp);
370
fatalerror("dsp32c_device::state_import called for unexpected value\n");
376
//-------------------------------------------------
377
// state_export - export state out of the device
378
//-------------------------------------------------
380
void dsp32c_device::state_export(const device_state_entry &entry)
382
switch (entry.index())
385
// no actual flags register, so just make something up
386
m_iotemp = ((zFLAG != 0) << 0) |
387
((nFLAG != 0) << 1) |
388
((cFLAG != 0) << 2) |
389
((vFLAG != 0) << 3) |
390
((ZFLAG != 0) << 4) |
391
((NFLAG != 0) << 5) |
392
((UFLAG != 0) << 6) |
401
fatalerror("dsp32c_device::state_export called for unexpected value\n");
407
//-------------------------------------------------
408
// state_string_export - export state as a string
410
//-------------------------------------------------
412
void dsp32c_device::state_string_export(const device_state_entry &entry, astring &string)
414
switch (entry.index())
417
string.printf("%c%c%c%c%c%c%c%c",
432
string.printf("%8g", *(double *)entry.dataptr());
438
//-------------------------------------------------
439
// disasm_min_opcode_bytes - return the length
440
// of the shortest instruction, in bytes
441
//-------------------------------------------------
443
UINT32 dsp32c_device::disasm_min_opcode_bytes() const
449
//-------------------------------------------------
450
// disasm_max_opcode_bytes - return the length
451
// of the longest instruction, in bytes
452
//-------------------------------------------------
454
UINT32 dsp32c_device::disasm_max_opcode_bytes() const
460
//-------------------------------------------------
461
// disasm_disassemble - call the disassembly
463
//-------------------------------------------------
465
offs_t dsp32c_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
467
extern CPU_DISASSEMBLE( dsp32c );
468
return CPU_DISASSEMBLE_NAME(dsp32c)(NULL, buffer, pc, oprom, opram, 0);
474
//**************************************************************************
476
//**************************************************************************
478
inline UINT32 dsp32c_device::ROPCODE(offs_t pc)
480
return m_direct->read_decrypted_dword(pc);
483
inline UINT8 dsp32c_device::RBYTE(offs_t addr)
485
return m_program->read_byte(addr);
488
inline void dsp32c_device::WBYTE(offs_t addr, UINT8 data)
490
m_program->write_byte(addr, data);
493
inline UINT16 dsp32c_device::RWORD(offs_t addr)
495
#if DETECT_MISALIGNED_MEMORY
496
if (addr & 1) fprintf(stderr, "Unaligned word read @ %06X, PC=%06X\n", addr, PC);
498
return m_program->read_word(addr);
501
inline UINT32 dsp32c_device::RLONG(offs_t addr)
503
#if DETECT_MISALIGNED_MEMORY
504
if (addr & 3) fprintf(stderr, "Unaligned long read @ %06X, PC=%06X\n", addr, PC);
506
return m_program->read_dword(addr);
509
inline void dsp32c_device::WWORD(offs_t addr, UINT16 data)
511
#if DETECT_MISALIGNED_MEMORY
512
if (addr & 1) fprintf(stderr, "Unaligned word write @ %06X, PC=%06X\n", addr, PC);
514
m_program->write_word(addr, data);
517
inline void dsp32c_device::WLONG(offs_t addr, UINT32 data)
519
#if DETECT_MISALIGNED_MEMORY
520
if (addr & 3) fprintf(stderr, "Unaligned long write @ %06X, PC=%06X\n", addr, PC);
522
m_program->write_dword(addr, data);
527
//**************************************************************************
529
//**************************************************************************
531
void dsp32c_device::check_irqs()
537
void dsp32c_device::set_irq_line(int irqline, int state)
544
//**************************************************************************
546
//**************************************************************************
548
void dsp32c_device::update_pcr(UINT16 newval)
550
UINT16 oldval = m_pcr;
553
// reset the chip if we get a reset
554
if ((oldval & PCR_RESET) == 0 && (newval & PCR_RESET) != 0)
557
// track the state of the output pins
558
if (m_output_pins_changed != NULL)
560
UINT16 newoutput = ((newval & (PCR_PIFs | PCR_ENI)) == (PCR_PIFs | PCR_ENI)) ? DSP32_OUTPUT_PIF : 0;
561
if (newoutput != m_lastpins)
563
m_lastpins = newoutput;
564
(*m_output_pins_changed)(*this, newoutput);
571
//**************************************************************************
573
//**************************************************************************
575
#include "dsp32ops.c"
579
//**************************************************************************
580
// CORE EXECUTION LOOP
581
//**************************************************************************
583
//-------------------------------------------------
584
// execute_min_cycles - return minimum number of
585
// cycles it takes for one instruction to execute
586
//-------------------------------------------------
588
UINT32 dsp32c_device::execute_min_cycles() const
594
//-------------------------------------------------
595
// execute_max_cycles - return maximum number of
596
// cycles it takes for one instruction to execute
597
//-------------------------------------------------
599
UINT32 dsp32c_device::execute_max_cycles() const
605
//-------------------------------------------------
606
// execute_input_lines - return the number of
607
// input/interrupt lines
608
//-------------------------------------------------
610
UINT32 dsp32c_device::execute_input_lines() const
616
void dsp32c_device::execute_set_input(int inputnum, int state)
621
void dsp32c_device::execute_run()
624
if ((m_pcr & PCR_RESET) == 0)
630
// update buffered accumulator values
631
m_abufcycle[0] += m_icount;
632
m_abufcycle[1] += m_icount;
633
m_abufcycle[2] += m_icount;
634
m_abufcycle[3] += m_icount;
642
// normalize buffered accumulator values
643
m_abufcycle[0] -= m_icount;
644
m_abufcycle[1] -= m_icount;
645
m_abufcycle[2] -= m_icount;
646
m_abufcycle[3] -= m_icount;
651
//**************************************************************************
652
// PARALLEL INTERFACE WRITES
653
//**************************************************************************
655
const UINT32 dsp32c_device::s_regmap[4][16] =
657
{ // DSP32 compatible mode
658
PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
659
PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
660
PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER,
661
PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER
663
{ // DSP32C 8-bit mode
664
PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
665
PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
666
PIO_PIR|LOWER, PIO_PIR|UPPER, PIO_PCR|UPPER, PIO_PARE|LOWER,
667
PIO_PDR2|LOWER,PIO_PDR2|UPPER,PIO_RESERVED, PIO_RESERVED
669
{ // DSP32C illegal mode
670
PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
671
PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
672
PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
673
PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED
675
{ // DSP32C 16-bit mode
676
PIO_PAR, PIO_RESERVED, PIO_PDR, PIO_RESERVED,
677
PIO_EMR, PIO_RESERVED, PIO_ESR|LOWER, PIO_PCR,
678
PIO_PIR, PIO_RESERVED, PIO_RESERVED, PIO_PARE|LOWER,
679
PIO_PDR2, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED
685
//**************************************************************************
686
// PARALLEL INTERFACE WRITES
687
//**************************************************************************
689
void dsp32c_device::dma_increment()
691
if (m_pcr & PCR_AUTO)
693
int amount = (m_pcr & PCR_DMA32) ? 4 : 2;
701
void dsp32c_device::dma_load()
703
// only process if DMA is enabled
706
UINT32 addr = m_par | (m_pare << 16);
709
if (!(m_pcr & PCR_DMA32))
710
m_pdr = RWORD(addr & 0xfffffe);
715
UINT32 temp = RLONG(addr & 0xfffffc);
717
m_pdr2 = temp & 0xffff;
720
// set the PDF flag to indicate we have data ready
721
update_pcr(m_pcr | PCR_PDFs);
726
void dsp32c_device::dma_store()
728
// only process if DMA is enabled
731
UINT32 addr = m_par | (m_pare << 16);
734
if (!(m_pcr & PCR_DMA32))
735
WWORD(addr & 0xfffffe, m_pdr);
739
WLONG(addr & 0xfffffc, (m_pdr << 16) | m_pdr2);
741
// clear the PDF flag to indicate we have taken the data
742
update_pcr(m_pcr & ~PCR_PDFs);
747
void dsp32c_device::pio_w(int reg, int data)
752
// look up register and mask
753
mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
754
reg = s_regmap[mode][reg];
756
if (mask == 0x00ff) data <<= 8;
760
// switch off the register
764
m_par = (m_par & mask) | data;
766
// trigger a load on the upper half
767
if (!(mask & 0xff00))
772
m_pare = (m_pare & mask) | data;
776
m_pdr = (m_pdr & mask) | data;
778
// trigger a write and PDF setting on the upper half
779
if (!(mask & 0xff00))
787
m_pdr2 = (m_pdr2 & mask) | data;
791
m_emr = (m_emr & mask) | data;
795
m_esr = (m_esr & mask) | data;
801
update_pcr((m_pcr & mask) | data);
805
m_pir = (m_pir & mask) | data;
807
// set PIF on upper half
808
if (!(mask & 0xff00))
809
update_pcr(m_pcr | PCR_PIFs);
814
logerror("dsp32_pio_w called on invalid register %d\n", reg);
821
//**************************************************************************
822
// PARALLEL INTERFACE READS
823
//**************************************************************************
825
int dsp32c_device::pio_r(int reg)
827
UINT16 mask, result = 0xffff;
828
UINT8 mode, shift = 0;
830
// look up register and mask
831
mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
832
reg = s_regmap[mode][reg];
834
if (mask == 0x00ff) mask = 0xff00, shift = 8;
837
// switch off the register
851
// trigger an increment on the lower half
855
// trigger a fetch on the upper half
856
if (!(mask & 0xff00))
877
if (!(mask & 0xff00))
878
update_pcr(m_pcr & ~PCR_PIFs); // clear PIFs
884
logerror("dsp32_pio_w called on invalid register %d\n", reg);
888
return (result >> shift) & ~mask;