1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     dsp32.c
6     Core implementation for the portable DSP32 emulator.
7 
8 ****************************************************************************
9 
10     Important note:
11 
12     At this time, the emulator is rather incomplete. However, it is
13     sufficiently complete to run both Race Drivin' and Hard Drivin's
14     Airborne, which is all I was after.
15 
16     Things that still need to be implemented:
17 
18         * interrupts
19         * carry-reverse add operations
20         * do loops
21         * ieee/dsp conversions
22         * input/output conversion
23         * serial I/O
24 
25     In addition, there are several optimizations enabled which make
26     assumptions about the code which may not be valid for other
27     applications. Check dsp32ops.inc for details.
28 
29 ***************************************************************************/
30 
31 #include "emu.h"
32 #include "dsp32.h"
33 #include "dsp32dis.h"
34 #include "debugger.h"
35 
36 
37 //**************************************************************************
38 //  DEBUGGING
39 //**************************************************************************
40 
41 #define DETECT_MISALIGNED_MEMORY    0
42 
43 
44 
45 //**************************************************************************
46 //  CONSTANTS
47 //**************************************************************************
48 
49 // internal register numbering for PIO registers
50 #define PIO_PAR         0
51 #define PIO_PDR         1
52 #define PIO_EMR         2
53 #define PIO_ESR         3
54 #define PIO_PCR         4
55 #define PIO_PIR         5
56 #define PIO_PARE        6
57 #define PIO_PDR2        7
58 #define PIO_RESERVED    8
59 
60 #define UPPER           (0x00ff << 8)
61 #define LOWER           (0xff00 << 8)
62 
63 // bits in the PCR register
64 #define PCR_RESET       0x001
65 #define PCR_REGMAP      0x002
66 #define PCR_ENI         0x004
67 #define PCR_DMA         0x008
68 #define PCR_AUTO        0x010
69 #define PCR_PDFs        0x020
70 #define PCR_PIFs        0x040
71 #define PCR_RES         0x080
72 #define PCR_DMA32       0x100
73 #define PCR_PIO16       0x200
74 #define PCR_FLG         0x400
75 
76 // internal flag bits
77 #define UFLAGBIT        1
78 #define VFLAGBIT        2
79 
80 
81 
82 //**************************************************************************
83 //  MACROS
84 //**************************************************************************
85 
86 // register mapping
87 #define R0              m_r[0]
88 #define R1              m_r[1]
89 #define R2              m_r[2]
90 #define R3              m_r[3]
91 #define R4              m_r[4]
92 #define R5              m_r[5]
93 #define R6              m_r[6]
94 #define R7              m_r[7]
95 #define R8              m_r[8]
96 #define R9              m_r[9]
97 #define R10             m_r[10]
98 #define R11             m_r[11]
99 #define R12             m_r[12]
100 #define R13             m_r[13]
101 #define R14             m_r[14]
102 #define PC              m_r[15]
103 #define R0_ALT          m_r[16]
104 #define R15             m_r[17]
105 #define R16             m_r[18]
106 #define R17             m_r[19]
107 #define R18             m_r[20]
108 #define R19             m_r[21]
109 #define RMM             m_r[22]
110 #define RPP             m_r[23]
111 #define R20             m_r[24]
112 #define R21             m_r[25]
113 #define DAUC            m_r[26]
114 #define IOC             m_r[27]
115 #define R22             m_r[29]
116 #define PCSH            m_r[30]
117 
118 #define A0              m_a[0]
119 #define A1              m_a[1]
120 #define A2              m_a[2]
121 #define A3              m_a[3]
122 #define A_0             m_a[4]
123 #define A_1             m_a[5]
124 
125 #define zFLAG           ((m_nzcflags & 0xffffff) == 0)
126 #define nFLAG           ((m_nzcflags & 0x800000) != 0)
127 #define cFLAG           ((m_nzcflags & 0x1000000) != 0)
128 #define vFLAG           ((m_vflags & 0x800000) != 0)
129 #define ZFLAG           (m_NZflags == 0)
130 #define NFLAG           (m_NZflags < 0)
131 #define UFLAG           (m_VUflags & UFLAGBIT)
132 #define VFLAG           (m_VUflags & VFLAGBIT)
133 
134 
135 
136 //**************************************************************************
137 //  DEVICE INTERFACE
138 //**************************************************************************
139 
140 DEFINE_DEVICE_TYPE(DSP32C, dsp32c_device, "dsp32c", "AT&T DSP32C")
141 
142 //-------------------------------------------------
143 //  dsp32c_device - constructor
144 //-------------------------------------------------
145 
dsp32c_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)146 dsp32c_device::dsp32c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
147 	: cpu_device(mconfig, DSP32C, tag, owner, clock),
148 		m_program_config("program", ENDIANNESS_LITTLE, 32, 24),
149 		m_pin(0),
150 		m_pout(0),
151 		m_ivtp(0),
152 		m_nzcflags(0),
153 		m_vflags(0),
154 		m_NZflags(0),
155 		m_VUflags(0),
156 		m_abuf_index(0),
157 		m_mbuf_index(0),
158 		m_par(0),
159 		m_pare(0),
160 		m_pdr(0),
161 		m_pdr2(0),
162 		m_pir(0),
163 		m_pcr(0),
164 		m_emr(0),
165 		m_esr(0),
166 		m_pcw(0),
167 		m_piop(0),
168 		m_ibuf(0),
169 		m_isr(0),
170 		m_obuf(0),
171 		m_osr(0),
172 		m_iotemp(0),
173 		m_lastp(0),
174 		m_icount(0),
175 		m_lastpins(0),
176 		m_ppc(0),
177 		m_output_pins_changed(*this)
178 {
179 	// set our instruction counter
180 	set_icountptr(m_icount);
181 }
182 
183 //-------------------------------------------------
184 //  device_start - start up the device
185 //-------------------------------------------------
186 
device_start()187 void dsp32c_device::device_start()
188 {
189 	m_output_pins_changed.resolve_safe();
190 
191 	// get our address spaces
192 	space(AS_PROGRAM).cache(m_cache);
193 	space(AS_PROGRAM).specific(m_program);
194 
195 	// register our state for the debugger
196 	state_add(STATE_GENPC,     "GENPC",     m_r[15]).noshow();
197 	state_add(STATE_GENPCBASE, "CURPC",     m_ppc).noshow();
198 	state_add(STATE_GENSP,     "GENSP",     m_r[21]).noshow();
199 	state_add(STATE_GENFLAGS,  "GENFLAGS",  m_iotemp).callimport().callexport().formatstr("%6s").noshow();
200 	state_add(DSP32_PC,        "PC",        m_r[15]).mask(0xffffff);
201 	for (int regnum = 0; regnum <= 14; regnum++)
202 		state_add(DSP32_R0 + regnum, string_format("R%d", regnum).c_str(), m_r[regnum]).mask(0xffffff);
203 	state_add(DSP32_R15,       "R15",       m_r[17]).mask(0xffffff);
204 	state_add(DSP32_R16,       "R16",       m_r[18]).mask(0xffffff);
205 	state_add(DSP32_R17,       "R17",       m_r[19]).mask(0xffffff);
206 	state_add(DSP32_R18,       "R18",       m_r[20]).mask(0xffffff);
207 	state_add(DSP32_R19,       "R19",       m_r[21]).mask(0xffffff);
208 	state_add(DSP32_R20,       "R20",       m_r[24]).mask(0xffffff);
209 	state_add(DSP32_R21,       "R21",       m_r[25]).mask(0xffffff);
210 	state_add(DSP32_R22,       "R22",       m_r[29]).mask(0xffffff);
211 	state_add(DSP32_PIN,       "PIN",       m_pin).mask(0xffffff);
212 	state_add(DSP32_POUT,      "POUT",      m_pout).mask(0xffffff);
213 	state_add(DSP32_IVTP,      "IVTP",      m_ivtp).mask(0xffffff);
214 	state_add(DSP32_A0,        "A0",        m_a[0]).formatstr("%8s");
215 	state_add(DSP32_A1,        "A1",        m_a[1]).formatstr("%8s");
216 	state_add(DSP32_A2,        "A2",        m_a[2]).formatstr("%8s");
217 	state_add(DSP32_A3,        "A3",        m_a[3]).formatstr("%8s");
218 	state_add(DSP32_DAUC,      "DAUC",      m_r[26]).mask(0xff);
219 	state_add(DSP32_PAR,       "PAR",       m_par);
220 	state_add(DSP32_PDR,       "PDR",       m_pdr);
221 	state_add(DSP32_PIR,       "PIR",       m_pir);
222 	state_add(DSP32_PCR,       "PCR",       m_iotemp).mask(0x3ff).callimport();
223 	state_add(DSP32_EMR,       "EMR",       m_emr);
224 	state_add(DSP32_ESR,       "ESR",       m_esr);
225 	state_add(DSP32_PCW,       "PCW",       m_pcw);
226 	state_add(DSP32_PIOP,      "PIOP",      m_piop);
227 	state_add(DSP32_IBUF,      "IBUF",      m_ibuf);
228 	state_add(DSP32_ISR,       "ISR",       m_isr);
229 	state_add(DSP32_OBUF,      "OBUF",      m_obuf);
230 	state_add(DSP32_OSR,       "OSR" ,      m_osr);
231 	state_add(DSP32_IOC,       "IOC",       m_r[27]).mask(0xfffff);
232 
233 	// register our state for saving
234 	save_item(NAME(m_r));
235 	save_item(NAME(m_pin));
236 	save_item(NAME(m_pout));
237 	save_item(NAME(m_ivtp));
238 	save_item(NAME(m_nzcflags));
239 	save_item(NAME(m_vflags));
240 	save_item(NAME(m_a));
241 	save_item(NAME(m_NZflags));
242 	save_item(NAME(m_VUflags));
243 	save_item(NAME(m_abuf));
244 	save_item(NAME(m_abufreg));
245 	save_item(NAME(m_abufVUflags));
246 	save_item(NAME(m_abufNZflags));
247 	save_item(NAME(m_abufcycle));
248 	save_item(NAME(m_abuf_index));
249 	save_item(NAME(m_mbufaddr));
250 	save_item(NAME(m_mbufdata));
251 	save_item(NAME(m_par));
252 	save_item(NAME(m_pare));
253 	save_item(NAME(m_pdr));
254 	save_item(NAME(m_pdr2));
255 	save_item(NAME(m_pir));
256 	save_item(NAME(m_pcr));
257 	save_item(NAME(m_emr));
258 	save_item(NAME(m_esr));
259 	save_item(NAME(m_pcw));
260 	save_item(NAME(m_piop));
261 	save_item(NAME(m_ibuf));
262 	save_item(NAME(m_isr));
263 	save_item(NAME(m_obuf));
264 	save_item(NAME(m_osr));
265 	save_item(NAME(m_lastpins));
266 	save_item(NAME(m_ppc));
267 }
268 
269 
270 //-------------------------------------------------
271 //  device_reset - reset the device
272 //-------------------------------------------------
273 
device_reset()274 void dsp32c_device::device_reset()
275 {
276 	// reset goes to 0
277 	PC = 0;
278 
279 	// clear some registers
280 	m_pcw &= 0x03ff;
281 	m_pcr = PCR_RESET;
282 	m_esr = 0;
283 	m_emr = 0xffff;
284 
285 	// clear the output pins
286 	m_output_pins_changed(0);
287 
288 	// initialize fixed registers
289 	R0 = R0_ALT = 0;
290 	RMM = -1;
291 	RPP = 1;
292 	A_0 = 0.0;
293 	A_1 = 1.0;
294 
295 	// init internal stuff
296 	m_abufcycle[0] = m_abufcycle[1] = m_abufcycle[2] = m_abufcycle[3] = 12345678;
297 	m_mbufaddr[0] = m_mbufaddr[1] = m_mbufaddr[2] = m_mbufaddr[3] = 1;
298 }
299 
300 
301 //-------------------------------------------------
302 //  memory_space_config - return the configuration
303 //  of the specified address space, or nullptr if
304 //  the space doesn't exist
305 //-------------------------------------------------
306 
memory_space_config() const307 device_memory_interface::space_config_vector dsp32c_device::memory_space_config() const
308 {
309 	return space_config_vector {
310 		std::make_pair(AS_PROGRAM, &m_program_config)
311 	};
312 }
313 
314 
315 //-------------------------------------------------
316 //  state_import - import state into the device,
317 //  after it has been set
318 //-------------------------------------------------
319 
state_import(const device_state_entry & entry)320 void dsp32c_device::state_import(const device_state_entry &entry)
321 {
322 	switch (entry.index())
323 	{
324 		case STATE_GENFLAGS:
325 			break;
326 
327 		case DSP32_PCR:
328 			update_pcr(m_iotemp);
329 			break;
330 
331 		default:
332 			fatalerror("dsp32c_device::state_import called for unexpected value\n");
333 	}
334 }
335 
336 
337 //-------------------------------------------------
338 //  state_export - export state out of the device
339 //-------------------------------------------------
340 
state_export(const device_state_entry & entry)341 void dsp32c_device::state_export(const device_state_entry &entry)
342 {
343 	switch (entry.index())
344 	{
345 		case STATE_GENFLAGS:
346 			// no actual flags register, so just make something up
347 			m_iotemp =  (zFLAG ? 0x01 : 0) |
348 						(nFLAG ? 0x02 : 0) |
349 						(cFLAG ? 0x04 : 0) |
350 						(vFLAG ? 0x08 : 0) |
351 						(ZFLAG ? 0x10 : 0) |
352 						(NFLAG ? 0x20 : 0) |
353 						(UFLAG ? 0x40 : 0) |
354 						(VFLAG ? 0x80 : 0);
355 			break;
356 
357 		case DSP32_PCR:
358 			m_iotemp = m_pcr;
359 			break;
360 
361 		default:
362 			fatalerror("dsp32c_device::state_export called for unexpected value\n");
363 	}
364 }
365 
366 
367 //-------------------------------------------------
368 //  state_string_export - export state as a string
369 //  for the debugger
370 //-------------------------------------------------
371 
state_string_export(const device_state_entry & entry,std::string & str) const372 void dsp32c_device::state_string_export(const device_state_entry &entry, std::string &str) const
373 {
374 	switch (entry.index())
375 	{
376 		case STATE_GENFLAGS:
377 			str = string_format("%c%c%c%c%c%c%c%c",
378 				NFLAG ? 'N':'.',
379 				ZFLAG ? 'Z':'.',
380 				UFLAG ? 'U':'.',
381 				VFLAG ? 'V':'.',
382 				nFLAG ? 'n':'.',
383 				zFLAG ? 'z':'.',
384 				cFLAG ? 'c':'.',
385 				vFLAG ? 'v':'.');
386 			break;
387 
388 		case DSP32_A0:
389 		case DSP32_A1:
390 		case DSP32_A2:
391 		case DSP32_A3:
392 			str = string_format("%8g", *(double *)entry.dataptr());
393 			break;
394 	}
395 }
396 
397 
398 //-------------------------------------------------
399 //  disassemble - call the disassembly
400 //  helper function
401 //-------------------------------------------------
402 
create_disassembler()403 std::unique_ptr<util::disasm_interface> dsp32c_device::create_disassembler()
404 {
405 	return std::make_unique<dsp32c_disassembler>();
406 }
407 
408 
409 
410 //**************************************************************************
411 //  MEMORY ACCESSORS
412 //**************************************************************************
413 
ROPCODE(offs_t pc)414 inline uint32_t dsp32c_device::ROPCODE(offs_t pc)
415 {
416 	return m_cache.read_dword(pc);
417 }
418 
RBYTE(offs_t addr)419 inline uint8_t dsp32c_device::RBYTE(offs_t addr)
420 {
421 	return m_program.read_byte(addr);
422 }
423 
WBYTE(offs_t addr,uint8_t data)424 inline void dsp32c_device::WBYTE(offs_t addr, uint8_t data)
425 {
426 	m_program.write_byte(addr, data);
427 }
428 
RWORD(offs_t addr)429 inline uint16_t dsp32c_device::RWORD(offs_t addr)
430 {
431 #if DETECT_MISALIGNED_MEMORY
432 	if (!WORD_ALIGNED(addr))
433 		osd_printf_error("Unaligned word read @ %06X, PC=%06X\n", addr, PC);
434 #endif
435 	return m_program.read_word(addr);
436 }
437 
RLONG(offs_t addr)438 inline uint32_t dsp32c_device::RLONG(offs_t addr)
439 {
440 #if DETECT_MISALIGNED_MEMORY
441 	if (!DWORD_ALIGNED(addr))
442 		osd_printf_error("Unaligned long read @ %06X, PC=%06X\n", addr, PC);
443 #endif
444 	return m_program.read_dword(addr);
445 }
446 
WWORD(offs_t addr,uint16_t data)447 inline void dsp32c_device::WWORD(offs_t addr, uint16_t data)
448 {
449 #if DETECT_MISALIGNED_MEMORY
450 	if (!WORD_ALIGNED(addr))
451 		osd_printf_error("Unaligned word write @ %06X, PC=%06X\n", addr, PC);
452 #endif
453 	m_program.write_word(addr, data);
454 }
455 
WLONG(offs_t addr,uint32_t data)456 inline void dsp32c_device::WLONG(offs_t addr, uint32_t data)
457 {
458 #if DETECT_MISALIGNED_MEMORY
459 	if (!DWORD_ALIGNED(addr))
460 		osd_printf_error("Unaligned long write @ %06X, PC=%06X\n", addr, PC);
461 #endif
462 	m_program.write_dword(addr, data);
463 }
464 
465 
466 
467 //**************************************************************************
468 //  IRQ HANDLING
469 //**************************************************************************
470 
check_irqs()471 void dsp32c_device::check_irqs()
472 {
473 	// finish me!
474 }
475 
476 
set_irq_line(int irqline,int state)477 void dsp32c_device::set_irq_line(int irqline, int state)
478 {
479 	// finish me!
480 }
481 
482 
483 
484 //**************************************************************************
485 //  REGISTER HANDLING
486 //**************************************************************************
487 
update_pcr(uint16_t newval)488 void dsp32c_device::update_pcr(uint16_t newval)
489 {
490 	uint16_t oldval = m_pcr;
491 	m_pcr = newval;
492 
493 	// reset the chip if we get a reset
494 	if ((oldval & PCR_RESET) == 0 && (newval & PCR_RESET) != 0)
495 		reset();
496 }
497 
498 
499 
500 //**************************************************************************
501 //  OUTPUT HANDLING
502 //**************************************************************************
503 
update_pins(void)504 void dsp32c_device::update_pins(void)
505 {
506 	if (m_pcr & PCR_ENI)
507 	{
508 		uint16_t newoutput = 0;
509 
510 		if (m_pcr & PCR_PIFs)
511 			newoutput |= DSP32_OUTPUT_PIF;
512 
513 		if (m_pcr & PCR_PDFs)
514 			newoutput |= DSP32_OUTPUT_PDF;
515 
516 		if (newoutput != m_lastpins)
517 		{
518 			m_lastpins = newoutput;
519 			m_output_pins_changed(newoutput);
520 		}
521 	}
522 }
523 
524 
525 
526 //**************************************************************************
527 //  CORE INCLUDE
528 //**************************************************************************
529 
530 #include "dsp32ops.hxx"
531 
532 
533 
534 //**************************************************************************
535 //  CORE EXECUTION LOOP
536 //**************************************************************************
537 
538 //-------------------------------------------------
539 //  execute_min_cycles - return minimum number of
540 //  cycles it takes for one instruction to execute
541 //-------------------------------------------------
542 
execute_min_cycles() const543 uint32_t dsp32c_device::execute_min_cycles() const noexcept
544 {
545 	return 4;
546 }
547 
548 
549 //-------------------------------------------------
550 //  execute_max_cycles - return maximum number of
551 //  cycles it takes for one instruction to execute
552 //-------------------------------------------------
553 
execute_max_cycles() const554 uint32_t dsp32c_device::execute_max_cycles() const noexcept
555 {
556 	return 4;
557 }
558 
559 
560 //-------------------------------------------------
561 //  execute_input_lines - return the number of
562 //  input/interrupt lines
563 //-------------------------------------------------
564 
execute_input_lines() const565 uint32_t dsp32c_device::execute_input_lines() const noexcept
566 {
567 	return 2;
568 }
569 
570 
execute_set_input(int inputnum,int state)571 void dsp32c_device::execute_set_input(int inputnum, int state)
572 {
573 }
574 
575 
execute_run()576 void dsp32c_device::execute_run()
577 {
578 	// skip if halted
579 	if ((m_pcr & PCR_RESET) == 0)
580 	{
581 		m_icount = 0;
582 		return;
583 	}
584 
585 	// update buffered accumulator values
586 	m_abufcycle[0] += m_icount;
587 	m_abufcycle[1] += m_icount;
588 	m_abufcycle[2] += m_icount;
589 	m_abufcycle[3] += m_icount;
590 
591 	// handle interrupts
592 	check_irqs();
593 
594 	while (m_icount > 0)
595 		execute_one();
596 
597 	// normalize buffered accumulator values
598 	m_abufcycle[0] -= m_icount;
599 	m_abufcycle[1] -= m_icount;
600 	m_abufcycle[2] -= m_icount;
601 	m_abufcycle[3] -= m_icount;
602 }
603 
604 
605 
606 //**************************************************************************
607 //  PARALLEL INTERFACE WRITES
608 //**************************************************************************
609 
610 const uint32_t dsp32c_device::s_regmap[4][16] =
611 {
612 	{   // DSP32 compatible mode
613 		PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
614 		PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
615 		PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER,
616 		PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER
617 	},
618 	{   // DSP32C 8-bit mode
619 		PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
620 		PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
621 		PIO_PIR|LOWER, PIO_PIR|UPPER, PIO_PCR|UPPER, PIO_PARE|LOWER,
622 		PIO_PDR2|LOWER,PIO_PDR2|UPPER,PIO_RESERVED,  PIO_RESERVED
623 	},
624 	{   // DSP32C illegal mode
625 		PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,
626 		PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,
627 		PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,
628 		PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED
629 	},
630 	{   // DSP32C 16-bit mode
631 		PIO_PAR,       PIO_RESERVED,  PIO_PDR,       PIO_RESERVED,
632 		PIO_EMR,       PIO_RESERVED,  PIO_ESR|LOWER, PIO_PCR,
633 		PIO_PIR,       PIO_RESERVED,  PIO_RESERVED,  PIO_PARE|LOWER,
634 		PIO_PDR2,      PIO_RESERVED,  PIO_RESERVED,  PIO_RESERVED
635 	}
636 };
637 
638 
639 
640 //**************************************************************************
641 //  PARALLEL INTERFACE WRITES
642 //**************************************************************************
643 
dma_increment()644 void dsp32c_device::dma_increment()
645 {
646 	if (m_pcr & PCR_AUTO)
647 	{
648 		int amount = (m_pcr & PCR_DMA32) ? 4 : 2;
649 		m_par += amount;
650 		if (m_par < amount)
651 			m_pare++;
652 	}
653 }
654 
655 
dma_load()656 void dsp32c_device::dma_load()
657 {
658 	// only process if DMA is enabled
659 	if (m_pcr & PCR_DMA)
660 	{
661 		uint32_t addr = m_par | (m_pare << 16);
662 
663 		// 16-bit case
664 		if (!(m_pcr & PCR_DMA32))
665 			m_pdr = RWORD(addr & 0xfffffe);
666 
667 		// 32-bit case
668 		else
669 		{
670 			uint32_t temp = RLONG(addr & 0xfffffc);
671 			m_pdr = temp >> 16;
672 			m_pdr2 = temp & 0xffff;
673 		}
674 
675 		// set the PDF flag to indicate we have data ready
676 		update_pcr(m_pcr | PCR_PDFs);
677 	}
678 }
679 
680 
dma_store()681 void dsp32c_device::dma_store()
682 {
683 	// only process if DMA is enabled
684 	if (m_pcr & PCR_DMA)
685 	{
686 		uint32_t addr = m_par | (m_pare << 16);
687 
688 		// 16-bit case
689 		if (!(m_pcr & PCR_DMA32))
690 			WWORD(addr & 0xfffffe, m_pdr);
691 
692 		// 32-bit case
693 		else
694 			WLONG(addr & 0xfffffc, (m_pdr << 16) | m_pdr2);
695 
696 		// clear the PDF flag to indicate we have taken the data
697 		update_pcr(m_pcr & ~PCR_PDFs);
698 	}
699 }
700 
701 
pio_w(int reg,int data)702 void dsp32c_device::pio_w(int reg, int data)
703 {
704 	uint16_t mask;
705 	uint8_t mode;
706 
707 	// look up register and mask
708 	mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
709 	reg = s_regmap[mode][reg];
710 	mask = reg >> 8;
711 	if (mask == 0x00ff) data <<= 8;
712 	data &= ~mask;
713 	reg &= 0xff;
714 
715 	// switch off the register
716 	switch (reg)
717 	{
718 		case PIO_PAR:
719 			m_par = (m_par & mask) | data;
720 
721 			// trigger a load on the upper half
722 			if (!(mask & 0xff00))
723 				dma_load();
724 			break;
725 
726 		case PIO_PARE:
727 			m_pare = (m_pare & mask) | data;
728 			break;
729 
730 		case PIO_PDR:
731 			m_pdr = (m_pdr & mask) | data;
732 
733 			// trigger a write and PDF setting on the upper half
734 			if (!(mask & 0xff00))
735 			{
736 				dma_store();
737 				dma_increment();
738 				update_pins();
739 			}
740 			break;
741 
742 		case PIO_PDR2:
743 			m_pdr2 = (m_pdr2 & mask) | data;
744 			break;
745 
746 		case PIO_EMR:
747 			m_emr = (m_emr & mask) | data;
748 			break;
749 
750 		case PIO_ESR:
751 			m_esr = (m_esr & mask) | data;
752 			break;
753 
754 		case PIO_PCR:
755 			mask |= 0x0060;
756 			data &= ~mask;
757 			update_pcr((m_pcr & mask) | data);
758 			break;
759 
760 		case PIO_PIR:
761 			m_pir = (m_pir & mask) | data;
762 
763 			// set PIF on upper half
764 			if (!(mask & 0xff00))
765 			{
766 				update_pcr(m_pcr | PCR_PIFs);
767 				update_pins();
768 			}
769 			break;
770 
771 		// error case
772 		default:
773 			logerror("dsp32_pio_w called on invalid register %d\n", reg);
774 			break;
775 	}
776 }
777 
778 
779 
780 //**************************************************************************
781 //  PARALLEL INTERFACE READS
782 //**************************************************************************
783 
pio_r(int reg)784 int dsp32c_device::pio_r(int reg)
785 {
786 	uint16_t mask, result = 0xffff;
787 	uint8_t mode, shift = 0;
788 
789 	// look up register and mask
790 	mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
791 	reg = s_regmap[mode][reg];
792 	mask = reg >> 8;
793 	if (mask == 0x00ff) mask = 0xff00, shift = 8;
794 	reg &= 0xff;
795 
796 	// switch off the register
797 	switch (reg)
798 	{
799 		case PIO_PAR:
800 			result = m_par | 1;
801 			break;
802 
803 		case PIO_PARE:
804 			result = m_pare;
805 			break;
806 
807 		case PIO_PDR:
808 			result = m_pdr;
809 
810 			// trigger an increment on the lower half
811 			if (shift != 8)
812 				dma_increment();
813 
814 			// trigger a fetch on the upper half
815 			if (!(mask & 0xff00))
816 			{
817 				dma_load();
818 				update_pins();
819 			}
820 			break;
821 
822 		case PIO_PDR2:
823 			result = m_pdr2;
824 			break;
825 
826 		case PIO_EMR:
827 			result = m_emr;
828 			break;
829 
830 		case PIO_ESR:
831 			result = m_esr;
832 			break;
833 
834 		case PIO_PCR:
835 			result = m_pcr;
836 			break;
837 
838 		case PIO_PIR:
839 			if (!(mask & 0xff00))
840 			{
841 				update_pcr(m_pcr & ~PCR_PIFs);  // clear PIFs
842 				update_pins();
843 			}
844 			result = m_pir;
845 			break;
846 
847 		// error case
848 		default:
849 			logerror("dsp32_pio_w called on invalid register %d\n", reg);
850 			break;
851 	}
852 
853 	return (result >> shift) & ~mask;
854 }
855