1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     tms32031.cpp
6 
7     TMS320C3x family 32-bit floating point DSP emulator
8 
9     TMS320C30/1/2 difference table:
10 
11     |-------------------|-------------------|-------------------|-------------------|
12     | Feature           | 'C30              | 'C31              | 'C32              |
13     |-------------------|-------------------|-------------------|-------------------|
14     | External Bus      | Two buses:        | One bus:          | One bus:          |
15     |                   | Primary bus:      | 32-bit data       | 32-bit data       |
16     |                   | 32-bit data       | 24-bit address    | 24-bit address    |
17     |                   | 24-bit address    | STRB active for   | STRB active for   |
18     |                   | STRB active for   | 000000-7FFFFFh    | 000000-7FFFFFh    |
19     |                   | 000000-7FFFFFh    | and               | and               |
20     |                   | and               | 80A000-FFFFFFh    | 880000-8FFFFFh    |
21     |                   | 80A000-FFFFFFh    |                   | 8-, 16-, 32-bit   |
22     |                   | Expansion bus:    |                   | data in           |
23     |                   | 32-bit data       |                   | 8-, 16-, 32-bit   |
24     |                   | 13-bit address    |                   | wide memory       |
25     |                   | MSTRB active for  |                   | STRB1 active for  |
26     |                   | 800000-801FFFh    |                   | 900000-FFFFFFh    |
27     |                   | IOSTRB active for |                   | 8-, 16-, 32-bit   |
28     |                   | 804000-805FFFh    |                   | data in           |
29     |                   |                   |                   | 8-, 16-, 32-bit   |
30     |                   |                   |                   | wide memory       |
31     |                   |                   |                   | IOSTRB active for |
32     |                   |                   |                   | 810000-82FFFFh    |
33     |-------------------|-------------------|-------------------|-------------------|
34     | ROM (Words)       | 4K                | No                | No                |
35     |-------------------|-------------------|-------------------|-------------------|
36     | Boot Loader       | No                | Yes               | Yes               |
37     |-------------------|-------------------|-------------------|-------------------|
38     | On-Chip RAM       | 2k                | 2k                | 512               |
39     | (Words)           | Address:          | Address:          | Address:          |
40     |                   | 809800-809fff     | 809800-809fff     | 87fe00-87ffff     |
41     |-------------------|-------------------|-------------------|-------------------|
42     | DMA               | 1 Channel         | 1 Channel         | 2 Channels        |
43     |                   | CPU greater       | CPU greater       | Configurable      |
44     |                   | priority then DMA | priority then DMA | priorities        |
45     |-------------------|-------------------|-------------------|-------------------|
46     | Serial Ports      | 2                 | 1                 | 1                 |
47     |-------------------|-------------------|-------------------|-------------------|
48     | Timers            | 2                 | 2                 | 2                 |
49     |-------------------|-------------------|-------------------|-------------------|
50     | Interrupts        | Level-Triggered   | Level-Triggered   | Level-Triggered   |
51     |                   |                   |                   | or combination of |
52     |                   |                   |                   | edge- and         |
53     |                   |                   |                   | level-triggered   |
54     |-------------------|-------------------|-------------------|-------------------|
55     | Interrupt vector  | Fixed 0-3Fh       | Microprocessor:   | Relocatable       |
56     | table             |                   | 0-3Fh fixed       |                   |
57     |                   |                   | Boot loader:      |                   |
58     |                   |                   | 809FC1-809FFF     |                   |
59     |                   |                   | fixed             |                   |
60     |-------------------|-------------------|-------------------|-------------------|
61 
62     TODO:
63     - merge and implement internal peripheral emulations
64     - implement chip family difference
65 
66 ***************************************************************************/
67 
68 #include "emu.h"
69 #include "tms32031.h"
70 #include "dis32031.h"
71 #include "debugger.h"
72 
73 
74 //**************************************************************************
75 //  CONSTANTS
76 //**************************************************************************
77 
78 // indexes into the register file
79 enum
80 {
81 	TMR_R0 = 0,
82 	TMR_R1,
83 	TMR_R2,
84 	TMR_R3,
85 	TMR_R4,
86 	TMR_R5,
87 	TMR_R6,
88 	TMR_R7,
89 	TMR_AR0,
90 	TMR_AR1,
91 	TMR_AR2,
92 	TMR_AR3,
93 	TMR_AR4,
94 	TMR_AR5,
95 	TMR_AR6,
96 	TMR_AR7,
97 	TMR_DP,
98 	TMR_IR0,
99 	TMR_IR1,
100 	TMR_BK,
101 	TMR_SP,
102 	TMR_ST,
103 	TMR_IE,
104 	TMR_IF,
105 	TMR_IOF,
106 	TMR_RS,
107 	TMR_RE,
108 	TMR_RC,
109 	TMR_R8,     // 3204x only
110 	TMR_R9,     // 3204x only
111 	TMR_R10,    // 3204x only
112 	TMR_R11,    // 3204x only
113 	TMR_TEMP1,  // used by the interpreter
114 	TMR_TEMP2,  // used by the interpreter
115 	TMR_TEMP3   // used by the interpreter
116 };
117 
118 // flags
119 const int CFLAG     = 0x0001;
120 const int VFLAG     = 0x0002;
121 const int ZFLAG     = 0x0004;
122 const int NFLAG     = 0x0008;
123 const int UFFLAG    = 0x0010;
124 const int LVFLAG    = 0x0020;
125 const int LUFFLAG   = 0x0040;
126 const int OVMFLAG   = 0x0080;
127 const int RMFLAG    = 0x0100;
128 //const int CFFLAG    = 0x0400;
129 //const int CEFLAG    = 0x0800;
130 //const int CCFLAG    = 0x1000;
131 const int GIEFLAG   = 0x2000;
132 
133 
134 
135 //**************************************************************************
136 //  MACROS
137 //**************************************************************************
138 
139 #define IREG(rnum)  (m_r[rnum].i32[0])
140 
141 
142 
143 //**************************************************************************
144 //  GLOBAL VARIABLES
145 //**************************************************************************
146 
147 // device type definition
148 DEFINE_DEVICE_TYPE(TMS32030, tms32030_device, "tms32030", "Texas Instruments TMS320C30")
149 DEFINE_DEVICE_TYPE(TMS32031, tms32031_device, "tms32031", "Texas Instruments TMS320C31")
150 DEFINE_DEVICE_TYPE(TMS32032, tms32032_device, "tms32032", "Texas Instruments TMS320C32")
151 
152 // memory map common to all 'C30 devices
153 // TODO: expand to cover all the standard internal peripherals
common_3203x(address_map & map)154 void tms3203x_device::common_3203x(address_map &map)
155 {
156 	//map(0x808000, 0x808000) DMA (0) Global control
157 	//map(0x808004, 0x808004) DMA (0) Source address
158 	//map(0x808006, 0x808006) DMA (0) Destination address
159 	//map(0x808008, 0x808008) DMA (0) Transfer Counter
160 	//map(0x808020, 0x808020) Timer 0 Global Control
161 	//map(0x808024, 0x808024) Timer 0 Counter
162 	//map(0x808028, 0x808028) Timer 0 Period Register
163 	//map(0x808030, 0x808030) Timer 1 Global Control
164 	//map(0x808034, 0x808034) Timer 1 Counter
165 	//map(0x808038, 0x808038) Timer 1 Period Register
166 	//map(0x808040, 0x808040) Serial Port (0) Global Control
167 	//map(0x808042, 0x808042) FSX/DX/CLKX Serial Port (0) Control
168 	//map(0x808043, 0x808043) FSR/DR/CLKR Serial Port (0) Control
169 	//map(0x808044, 0x808044) Serial Port (0) R/X Timer Control
170 	//map(0x808045, 0x808045) Serial Port (0) R/X Timer Counter
171 	//map(0x808046, 0x808046) Serial Port (0) R/X Timer Period Register
172 	//map(0x808048, 0x808048) Serial Port (0) Data-Transmit
173 	//map(0x80804c, 0x80804c) Serial Port (0) Data-Receive
174 	map(0x808064, 0x808064).rw(FUNC(tms3203x_device::primary_bus_control_r), FUNC(tms3203x_device::primary_bus_control_w));
175 }
176 
177 // internal memory maps
internal_32030(address_map & map)178 void tms32030_device::internal_32030(address_map &map)
179 {
180 	common_3203x(map);
181 
182 	//map(0x000000, 0x7fffff) STRB
183 	//map(0x800000, 0x801fff) MSTRB
184 	//map(0x804000, 0x805fff) IOSTRB
185 	//map(0x808050, 0x808050) Serial Port 1 Global Control
186 	//map(0x808052, 0x808052) FSX/DX/CLKX Serial Port 1 Control
187 	//map(0x808053, 0x808053) FSR/DR/CLKR Serial Port 1 Control
188 	//map(0x808054, 0x808054) Serial Port 1 R/X Timer Control
189 	//map(0x808055, 0x808055) Serial Port 1 R/X Timer Counter
190 	//map(0x808056, 0x808056) Serial Port 1 R/X Timer Period Register
191 	//map(0x808058, 0x808058) Serial Port 1 Data-Transmit
192 	//map(0x80805c, 0x80805c) Serial Port 1 Data-Receive
193 	//map(0x808060, 0x808060) Expansion-Bus Control
194 	//map(0x808064, 0x808064) Primary-Bus Control
195 	map(0x809800, 0x809fff).ram();
196 	//map(0x80a000, 0xffffff) STRB
197 }
198 
internal_32031(address_map & map)199 void tms32031_device::internal_32031(address_map &map)
200 {
201 	common_3203x(map);
202 
203 	//map(0x000000, 0x7fffff) STRB
204 	//map(0x808064, 0x808064) Primary-Bus Control
205 	map(0x809800, 0x809fff).ram();
206 	//map(0x80a000, 0xffffff) STRB
207 }
208 
internal_32032(address_map & map)209 void tms32032_device::internal_32032(address_map &map)
210 {
211 	common_3203x(map);
212 
213 	//map(0x000000, 0x7fffff) STRB0
214 	//map(0x808010, 0x808010) DMA 1 Global control
215 	//map(0x808014, 0x808014) DMA 1 Source address
216 	//map(0x808016, 0x808016) DMA 1 Destination address
217 	//map(0x808018, 0x808018) DMA 1 Transfer Counter
218 	//map(0x808060, 0x808060) IOSTRB Bus Control
219 	//map(0x808064, 0x808064) STRB0 Bus Control
220 	//map(0x808068, 0x808068) STRB1 Bus Control
221 	//map(0x810000, 0x82ffff) IOSTRB
222 	map(0x87fe00, 0x87ffff).ram();
223 	//map(0x880000, 0x8fffff) STRB0
224 	//map(0x900000, 0xffffff) STRB1
225 }
226 
227 
228 // ROM definitions for the internal boot loader programs
229 // (Using assembled versions until the code ROMs are extracted from both DSPs)
230 ROM_START( tms32030 )
231 	ROM_REGION(0x4000, "internal_rom", 0)
232 	ROM_LOAD( "c30boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(bddc2763) SHA1(96b2170ecee5bec5abaa1741bb2d3b6096ecc262)) // TODO: programmable?
233 ROM_END
234 
ROM_START(tms32031)235 ROM_START( tms32031 )
236 	ROM_REGION(0x4000, "internal_rom", 0)
237 	ROM_LOAD( "c31boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(bddc2763) SHA1(96b2170ecee5bec5abaa1741bb2d3b6096ecc262) ) // Assembled from c31boot.asm (02-07-92)
238 ROM_END
239 
240 ROM_START( tms32032 )
241 	ROM_REGION(0x4000, "internal_rom", 0)
242 	ROM_LOAD( "c32boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(ecf84729) SHA1(4d32ead450f921f563514b061ea561a222283616) ) // Assembled from c32boot.asm (03-04-96)
243 ROM_END
244 
245 
246 
247 //**************************************************************************
248 //  TMSREG REGISTER
249 //**************************************************************************
250 
251 //-------------------------------------------------
252 //  as_float - interpret the contents of a tmsreg
253 //  as a DSP-encoded floating-point value, and
254 //  extract a 32-bit IEEE float from it
255 //-------------------------------------------------
256 
257 float tms3203x_device::tmsreg::as_float() const
258 {
259 	int_double id;
260 
261 	// map 0 to 0
262 	if (mantissa() == 0 && exponent() == -128)
263 		return 0;
264 
265 	// handle positive numbers
266 	else if (mantissa() >= 0)
267 	{
268 		int exp = (exponent() + 127) << 23;
269 		id.i[0] = exp + (mantissa() >> 8);
270 	}
271 
272 	// handle negative numbers
273 	else
274 	{
275 		int exp = (exponent() + 127) << 23;
276 		int32_t man = -mantissa();
277 		id.i[0] = 0x80000000 + exp + ((man >> 8) & 0x00ffffff);
278 	}
279 
280 	// return the converted float
281 	return id.f[0];
282 }
283 
284 
285 //-------------------------------------------------
286 //  as_double - interpret the contents of a tmsreg
287 //  as a DSP-encoded floating-point value, and
288 //  extract a 64-bit IEEE double from it
289 //-------------------------------------------------
290 
as_double() const291 double tms3203x_device::tmsreg::as_double() const
292 {
293 	int_double id;
294 
295 	// map 0 to 0
296 	if (mantissa() == 0 && exponent() == -128)
297 		return 0;
298 
299 	// handle positive numbers
300 	else if (mantissa() >= 0)
301 	{
302 		int exp = (exponent() + 1023) << 20;
303 		id.i[BYTE_XOR_BE(0)] = exp + (mantissa() >> 11);
304 		id.i[BYTE_XOR_BE(1)] = (mantissa() << 21) & 0xffe00000;
305 	}
306 
307 	// handle negative numbers
308 	else
309 	{
310 		int exp = (exponent() + 1023) << 20;
311 		int32_t man = -mantissa();
312 		id.i[BYTE_XOR_BE(0)] = 0x80000000 + exp + ((man >> 11) & 0x001fffff);
313 		id.i[BYTE_XOR_BE(1)] = (man << 21) & 0xffe00000;
314 	}
315 
316 	// return the converted double
317 	return id.d;
318 }
319 
320 
321 //-------------------------------------------------
322 //  from_double - import a 64-bit IEEE double into
323 //  the DSP's internal floating point format
324 //-------------------------------------------------
325 
from_double(double val)326 void tms3203x_device::tmsreg::from_double(double val)
327 {
328 	// extract mantissa and exponent from the IEEE input
329 	int_double id;
330 	id.d = val;
331 	int32_t mantissa = ((id.i[BYTE_XOR_BE(0)] & 0x000fffff) << 11) | ((id.i[BYTE_XOR_BE(1)] & 0xffe00000) >> 21);
332 	int32_t exponent = ((id.i[BYTE_XOR_BE(0)] & 0x7ff00000) >> 20) - 1023;
333 
334 	// if we're too small, map to 0
335 	if (exponent < -128)
336 	{
337 		set_mantissa(0);
338 		set_exponent(-128);
339 	}
340 
341 	// if we're too large, map to the maximum value
342 	else if (exponent > 127)
343 	{
344 		if ((int32_t)id.i[BYTE_XOR_BE(0)] >= 0)
345 			set_mantissa(0x7fffffff);
346 		else
347 			set_mantissa(0x80000001);
348 		set_exponent(127);
349 	}
350 
351 	// if we're positive, map directly
352 	else if ((int32_t)id.i[BYTE_XOR_BE(0)] >= 0)
353 	{
354 		set_mantissa(mantissa);
355 		set_exponent(exponent);
356 	}
357 
358 	// if we're negative with a non-zero mantissa, remove the leading sign bit
359 	else if (mantissa != 0)
360 	{
361 		set_mantissa(0x80000000 | -mantissa);
362 		set_exponent(exponent);
363 	}
364 
365 	// if we're negative with a zero mantissa, normalize
366 	else
367 	{
368 		set_mantissa(0x80000000);
369 		set_exponent(exponent - 1);
370 	}
371 }
372 
373 
374 
375 //**************************************************************************
376 //  DEVICE INTERFACE
377 //**************************************************************************
378 
379 //-------------------------------------------------
380 //  tms3203x_device - constructor
381 //-------------------------------------------------
382 
tms3203x_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t chiptype,address_map_constructor internal_map)383 tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t chiptype, address_map_constructor internal_map)
384 	: cpu_device(mconfig, type, tag, owner, clock),
385 		m_program_config("program", ENDIANNESS_LITTLE, 32, 24, -2, internal_map),
386 		m_chip_type(chiptype),
387 		m_pc(0),
388 		m_bkmask(0),
389 		m_primary_bus_control(0),
390 		m_irq_state(0),
391 		m_delayed(false),
392 		m_irq_pending(false),
393 		m_is_idling(false),
394 		m_icount(0),
395 		m_internal_rom(*this, "internal_rom"),
396 		m_mcbl_mode(false),
397 		m_xf0_cb(*this),
398 		m_xf1_cb(*this),
399 		m_iack_cb(*this),
400 		m_holda_cb(*this)
401 {
402 	// initialize remaining state
403 	memset(&m_r, 0, sizeof(m_r));
404 
405 	// set our instruction counter
406 	set_icountptr(m_icount);
407 
408 #if (TMS_3203X_LOG_OPCODE_USAGE)
409 	memset(m_hits, 0, sizeof(m_hits));
410 #endif
411 }
412 
tms32030_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)413 tms32030_device::tms32030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
414 	: tms3203x_device(mconfig, TMS32030, tag, owner, clock, CHIP_TYPE_TMS32030, address_map_constructor(FUNC(tms32030_device::internal_32030), this))
415 {
416 }
417 
tms32031_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)418 tms32031_device::tms32031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
419 	: tms3203x_device(mconfig, TMS32031, tag, owner, clock, CHIP_TYPE_TMS32031, address_map_constructor(FUNC(tms32031_device::internal_32031), this))
420 {
421 }
422 
tms32032_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)423 tms32032_device::tms32032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
424 	: tms3203x_device(mconfig, TMS32032, tag, owner, clock, CHIP_TYPE_TMS32032, address_map_constructor(FUNC(tms32032_device::internal_32032), this))
425 {
426 }
427 
428 //-------------------------------------------------
429 //  ~tms3203x_device - destructor
430 //-------------------------------------------------
431 
~tms3203x_device()432 tms3203x_device::~tms3203x_device()
433 {
434 #if (TMS_3203X_LOG_OPCODE_USAGE)
435 	for (int i = 0; i < ARRAY_LENGTH(m_hits); i++)
436 		if (m_hits[i] != 0)
437 			printf("%10d - %03X.%X\n", m_hits[i], i / 4, i % 4);
438 #endif
439 }
440 
441 
442 //-------------------------------------------------
443 //  rom_region - return a pointer to the device's
444 //  internal ROM region
445 //-------------------------------------------------
446 
device_rom_region() const447 const tiny_rom_entry *tms3203x_device::device_rom_region() const
448 {
449 	switch (m_chip_type)
450 	{
451 		default:
452 		case CHIP_TYPE_TMS32030:    return ROM_NAME( tms32030 );
453 		case CHIP_TYPE_TMS32031:    return ROM_NAME( tms32031 );
454 		case CHIP_TYPE_TMS32032:    return ROM_NAME( tms32032 );
455 	}
456 }
457 
458 //-------------------------------------------------
459 //  ROPCODE - fetch an opcode
460 //-------------------------------------------------
461 
ROPCODE(offs_t pc)462 inline uint32_t tms3203x_device::ROPCODE(offs_t pc)
463 {
464 	return m_cache.read_dword(pc);
465 }
466 
467 
468 //-------------------------------------------------
469 //  RMEM - read memory
470 //-------------------------------------------------
471 
RMEM(offs_t addr)472 inline uint32_t tms3203x_device::RMEM(offs_t addr)
473 {
474 	return m_program.read_dword(addr);
475 }
476 
477 
478 //-------------------------------------------------
479 //  WMEM - write memory
480 //-------------------------------------------------
481 
WMEM(offs_t addr,uint32_t data)482 inline void tms3203x_device::WMEM(offs_t addr, uint32_t data)
483 {
484 	m_program.write_dword(addr, data);
485 }
486 
487 
488 //-------------------------------------------------
489 //  device_start - start up the device
490 //-------------------------------------------------
491 
device_start()492 void tms3203x_device::device_start()
493 {
494 	// find address spaces
495 	space(AS_PROGRAM).cache(m_cache);
496 	space(AS_PROGRAM).specific(m_program);
497 
498 	// resolve devcb handlers
499 	m_xf0_cb.resolve_safe();
500 	m_xf1_cb.resolve_safe();
501 	m_iack_cb.resolve_safe();
502 	m_holda_cb.resolve_safe();
503 
504 	// set up the internal boot loader ROM
505 	if (m_mcbl_mode)
506 	{
507 		if (m_internal_rom->base() != nullptr)
508 			m_program.space().install_rom(0x000000, 0x000fff, m_internal_rom->base());
509 		else
510 			m_program.space().unmap_read(0x000000, 0x000fff);
511 	}
512 
513 	// save state
514 	save_item(NAME(m_pc));
515 	for (int regnum = 0; regnum < 36; regnum++)
516 		save_item(NAME(m_r[regnum].i32), regnum);
517 	save_item(NAME(m_bkmask));
518 	save_item(NAME(m_primary_bus_control));
519 	save_item(NAME(m_irq_state));
520 	save_item(NAME(m_delayed));
521 	save_item(NAME(m_irq_pending));
522 	save_item(NAME(m_is_idling));
523 	save_item(NAME(m_mcbl_mode));
524 	save_item(NAME(m_hold_state));
525 
526 	// register our state for the debugger
527 	state_add(TMS3203X_PC,      "PC",        m_pc);
528 	state_add(STATE_GENPC,      "GENPC",     m_pc).noshow();
529 	state_add(STATE_GENPCBASE,  "CURPC",     m_pc).noshow();
530 	state_add(STATE_GENFLAGS,   "GENFLAGS",  m_r[TMR_ST].i32[0]).mask(0xff).noshow().formatstr("%8s");
531 	state_add(TMS3203X_R0,      "R0",        m_r[TMR_R0].i32[0]);
532 	state_add(TMS3203X_R1,      "R1",        m_r[TMR_R1].i32[0]);
533 	state_add(TMS3203X_R2,      "R2",        m_r[TMR_R2].i32[0]);
534 	state_add(TMS3203X_R3,      "R3",        m_r[TMR_R3].i32[0]);
535 	state_add(TMS3203X_R4,      "R4",        m_r[TMR_R4].i32[0]);
536 	state_add(TMS3203X_R5,      "R5",        m_r[TMR_R5].i32[0]);
537 	state_add(TMS3203X_R6,      "R6",        m_r[TMR_R6].i32[0]);
538 	state_add(TMS3203X_R7,      "R7",        m_r[TMR_R7].i32[0]);
539 	state_add(TMS3203X_R0F,     "R0F",       m_iotemp).callimport().callexport().formatstr("%12s");
540 	state_add(TMS3203X_R1F,     "R1F",       m_iotemp).callimport().callexport().formatstr("%12s");
541 	state_add(TMS3203X_R2F,     "R2F",       m_iotemp).callimport().callexport().formatstr("%12s");
542 	state_add(TMS3203X_R3F,     "R3F",       m_iotemp).callimport().callexport().formatstr("%12s");
543 	state_add(TMS3203X_R4F,     "R4F",       m_iotemp).callimport().callexport().formatstr("%12s");
544 	state_add(TMS3203X_R5F,     "R5F",       m_iotemp).callimport().callexport().formatstr("%12s");
545 	state_add(TMS3203X_R6F,     "R6F",       m_iotemp).callimport().callexport().formatstr("%12s");
546 	state_add(TMS3203X_R7F,     "R7F",       m_iotemp).callimport().callexport().formatstr("%12s");
547 	state_add(TMS3203X_AR0,     "AR0",       m_r[TMR_AR0].i32[0]);
548 	state_add(TMS3203X_AR1,     "AR1",       m_r[TMR_AR1].i32[0]);
549 	state_add(TMS3203X_AR2,     "AR2",       m_r[TMR_AR2].i32[0]);
550 	state_add(TMS3203X_AR3,     "AR3",       m_r[TMR_AR3].i32[0]);
551 	state_add(TMS3203X_AR4,     "AR4",       m_r[TMR_AR4].i32[0]);
552 	state_add(TMS3203X_AR5,     "AR5",       m_r[TMR_AR5].i32[0]);
553 	state_add(TMS3203X_AR6,     "AR6",       m_r[TMR_AR6].i32[0]);
554 	state_add(TMS3203X_AR7,     "AR7",       m_r[TMR_AR7].i32[0]);
555 	state_add(TMS3203X_DP,      "DP",        m_r[TMR_DP].i32[0]).mask(0xff);
556 	state_add(TMS3203X_IR0,     "IR0",       m_r[TMR_IR0].i32[0]);
557 	state_add(TMS3203X_IR1,     "IR1",       m_r[TMR_IR1].i32[0]);
558 	state_add(TMS3203X_BK,      "BK",        m_r[TMR_BK].i32[0]);
559 	state_add(TMS3203X_SP,      "SP",        m_r[TMR_SP].i32[0]);
560 	state_add(TMS3203X_ST,      "ST",        m_r[TMR_ST].i32[0]);
561 	state_add(TMS3203X_IE,      "IE",        m_r[TMR_IE].i32[0]);
562 	state_add(TMS3203X_IF,      "IF",        m_r[TMR_IF].i32[0]);
563 	state_add(TMS3203X_IOF,     "IOF",       m_r[TMR_IOF].i32[0]);
564 	state_add(TMS3203X_RS,      "RS",        m_r[TMR_RS].i32[0]);
565 	state_add(TMS3203X_RE,      "RE",        m_r[TMR_RE].i32[0]);
566 	state_add(TMS3203X_RC,      "RC",        m_r[TMR_RC].i32[0]);
567 }
568 
569 
570 //-------------------------------------------------
571 //  device_reset - reset the device
572 //-------------------------------------------------
573 
device_reset()574 void tms3203x_device::device_reset()
575 {
576 	m_pc = RMEM(0);
577 
578 	// reset some registers
579 	IREG(TMR_IE) = 0;
580 	IREG(TMR_IF) = 0;
581 	IREG(TMR_ST) = 0;
582 	IREG(TMR_IOF) = 0;
583 
584 	// update IF with the external interrupt state (required for boot loader operation)
585 	IREG(TMR_IF) |= m_irq_state & 0x0f;
586 
587 	// reset peripheral registers
588 	m_primary_bus_control = 0x000010f8;
589 
590 	// reset internal stuff
591 	m_delayed = m_irq_pending = m_is_idling = false;
592 }
593 
594 
595 //-------------------------------------------------
596 //  memory_space_config - return the configuration
597 //  of the specified address space, or nullptr if
598 //  the space doesn't exist
599 //-------------------------------------------------
600 
memory_space_config() const601 device_memory_interface::space_config_vector tms3203x_device::memory_space_config() const
602 {
603 	return space_config_vector {
604 		std::make_pair(AS_PROGRAM, &m_program_config)
605 	};
606 }
607 
608 
609 //-------------------------------------------------
610 //  state_import - import state into the device,
611 //  after it has been set
612 //-------------------------------------------------
613 
state_import(const device_state_entry & entry)614 void tms3203x_device::state_import(const device_state_entry &entry)
615 {
616 	switch (entry.index())
617 	{
618 		case TMS3203X_R0F:
619 		case TMS3203X_R1F:
620 		case TMS3203X_R2F:
621 		case TMS3203X_R3F:
622 		case TMS3203X_R4F:
623 		case TMS3203X_R5F:
624 		case TMS3203X_R6F:
625 		case TMS3203X_R7F:
626 			m_r[TMR_R0 + (entry.index() - TMS3203X_R0F)].from_double(*(float *)&m_iotemp);
627 			break;
628 
629 		default:
630 			fatalerror("CPU_IMPORT_STATE(tms3203x) called for unexpected value\n");
631 	}
632 }
633 
634 
635 //-------------------------------------------------
636 //  state_export - export state into the device,
637 //  before returning it to the caller
638 //-------------------------------------------------
639 
state_export(const device_state_entry & entry)640 void tms3203x_device::state_export(const device_state_entry &entry)
641 {
642 	switch (entry.index())
643 	{
644 		case TMS3203X_R0F:
645 		case TMS3203X_R1F:
646 		case TMS3203X_R2F:
647 		case TMS3203X_R3F:
648 		case TMS3203X_R4F:
649 		case TMS3203X_R5F:
650 		case TMS3203X_R6F:
651 		case TMS3203X_R7F:
652 			*(float *)&m_iotemp = m_r[TMR_R0 + (entry.index() - TMS3203X_R0F)].as_float();
653 			break;
654 
655 		default:
656 			fatalerror("CPU_IMPORT_STATE(tms3203x) called for unexpected value\n");
657 	}
658 }
659 
660 
661 //-------------------------------------------------
662 //  state_string_export - export state as a string
663 //  for the debugger
664 //-------------------------------------------------
665 
state_string_export(const device_state_entry & entry,std::string & str) const666 void tms3203x_device::state_string_export(const device_state_entry &entry, std::string &str) const
667 {
668 	switch (entry.index())
669 	{
670 		case TMS3203X_R0F:
671 		case TMS3203X_R1F:
672 		case TMS3203X_R2F:
673 		case TMS3203X_R3F:
674 		case TMS3203X_R4F:
675 		case TMS3203X_R5F:
676 		case TMS3203X_R6F:
677 		case TMS3203X_R7F:
678 			str = string_format("%12g", m_r[TMR_R0 + (entry.index() - TMS3203X_R0F)].as_double());
679 			break;
680 
681 		case STATE_GENFLAGS:
682 			uint32_t temp = m_r[TMR_ST].i32[0];
683 			str = string_format("%c%c%c%c%c%c%c%c",
684 				(temp & 0x80) ? 'O':'.',
685 				(temp & 0x40) ? 'U':'.',
686 				(temp & 0x20) ? 'V':'.',
687 				(temp & 0x10) ? 'u':'.',
688 				(temp & 0x08) ? 'n':'.',
689 				(temp & 0x04) ? 'z':'.',
690 				(temp & 0x02) ? 'v':'.',
691 				(temp & 0x01) ? 'c':'.');
692 			break;
693 	}
694 }
695 
696 
697 //-------------------------------------------------
698 //  disassemble - call the disassembly
699 //  helper function
700 //-------------------------------------------------
701 
create_disassembler()702 std::unique_ptr<util::disasm_interface> tms3203x_device::create_disassembler()
703 {
704 	return std::make_unique<tms32031_disassembler>();
705 }
706 
707 
708 
709 //**************************************************************************
710 //  PUBLIC INTERFACES
711 //**************************************************************************
712 
713 //-------------------------------------------------
714 //  fp_to_float - convert a 32-bit value from DSP
715 //  floating-point format a 32-bit IEEE float
716 //-------------------------------------------------
717 
fp_to_float(uint32_t floatdata)718 float tms3203x_device::fp_to_float(uint32_t floatdata)
719 {
720 	tmsreg gen(floatdata << 8, (int32_t)floatdata >> 24);
721 	return gen.as_float();
722 }
723 
724 
725 //-------------------------------------------------
726 //  fp_to_double - convert a 32-bit value from DSP
727 //  floating-point format a 64-bit IEEE double
728 //-------------------------------------------------
729 
fp_to_double(uint32_t floatdata)730 double tms3203x_device::fp_to_double(uint32_t floatdata)
731 {
732 	tmsreg gen(floatdata << 8, (int32_t)floatdata >> 24);
733 	return gen.as_double();
734 }
735 
736 
737 //-------------------------------------------------
738 //  float_to_fp - convert a 32-bit IEEE float to
739 //  a 32-bit DSP floating-point value
740 //-------------------------------------------------
741 
float_to_fp(float fval)742 uint32_t tms3203x_device::float_to_fp(float fval)
743 {
744 	tmsreg gen(fval);
745 	return (gen.exponent() << 24) | ((uint32_t)gen.mantissa() >> 8);
746 }
747 
748 
749 //-------------------------------------------------
750 //  double_to_fp - convert a 64-bit IEEE double to
751 //  a 32-bit DSP floating-point value
752 //-------------------------------------------------
753 
double_to_fp(double dval)754 uint32_t tms3203x_device::double_to_fp(double dval)
755 {
756 	tmsreg gen(dval);
757 	return (gen.exponent() << 24) | ((uint32_t)gen.mantissa() >> 8);
758 }
759 
760 
761 
762 //**************************************************************************
763 //  EXECUTION
764 //**************************************************************************
765 
766 //-------------------------------------------------
767 //  check_irqs - check for pending IRQs and take
768 //  them if enabled
769 //-------------------------------------------------
770 
check_irqs()771 void tms3203x_device::check_irqs()
772 {
773 	// determine if we have any live interrupts
774 	uint16_t validints = IREG(TMR_IF) & IREG(TMR_IE) & 0x0fff;
775 	if (validints == 0 || (IREG(TMR_ST) & GIEFLAG) == 0)
776 		return;
777 
778 	// find the lowest signalled value
779 	int whichtrap = 0;
780 	for (int i = 0; i < 12; i++)
781 		if (validints & (1 << i))
782 		{
783 			whichtrap = i + 1;
784 			break;
785 		}
786 
787 	// no longer idling if we get here
788 	m_is_idling = false;
789 	if (!m_delayed)
790 	{
791 		uint16_t intmask = 1 << (whichtrap - 1);
792 
793 		// bit in IF is cleared when interrupt is taken
794 		IREG(TMR_IF) &= ~intmask;
795 		trap(whichtrap);
796 
797 		// after auto-clearing the interrupt bit, we need to re-trigger
798 		// level-sensitive interrupts
799 		if (m_chip_type == CHIP_TYPE_TMS32031 || (IREG(TMR_ST) & 0x4000) == 0)
800 			IREG(TMR_IF) |= m_irq_state & 0x0f;
801 	}
802 	else
803 		m_irq_pending = true;
804 }
805 
806 
807 //-------------------------------------------------
808 //  execute_min_cycles - return minimum number of
809 //  cycles it takes for one instruction to execute
810 //-------------------------------------------------
811 
execute_min_cycles() const812 uint32_t tms3203x_device::execute_min_cycles() const noexcept
813 {
814 	return 1;
815 }
816 
817 
818 //-------------------------------------------------
819 //  execute_max_cycles - return maximum number of
820 //  cycles it takes for one instruction to execute
821 //-------------------------------------------------
822 
execute_max_cycles() const823 uint32_t tms3203x_device::execute_max_cycles() const noexcept
824 {
825 	return 4;
826 }
827 
828 
829 //-------------------------------------------------
830 //  execute_input_lines - return the number of
831 //  input/interrupt lines
832 //-------------------------------------------------
833 
execute_input_lines() const834 uint32_t tms3203x_device::execute_input_lines() const noexcept
835 {
836 	return 14;
837 }
838 
839 
840 //-------------------------------------------------
841 //  execute_set_input - set input and IRQ lines
842 //-------------------------------------------------
843 
execute_set_input(int inputnum,int state)844 void tms3203x_device::execute_set_input(int inputnum, int state)
845 {
846 	if (inputnum == TMS3203X_MCBL)
847 	{
848 		// switch between microcomputer/boot loader and microprocessor modes
849 		bool old_mode = m_mcbl_mode;
850 		m_mcbl_mode = (state == ASSERT_LINE);
851 		if (m_mcbl_mode != old_mode)
852 		{
853 			if (m_mcbl_mode && (m_internal_rom->base() != nullptr))
854 				m_program.space().install_rom(0x000000, 0x000fff, m_internal_rom->base());
855 			else
856 				m_program.space().unmap_read(0x000000, 0x000fff);
857 		}
858 		return;
859 	}
860 
861 	if (inputnum == TMS3203X_HOLD)
862 	{
863 		m_hold_state = (state == ASSERT_LINE);
864 
865 		// FIXME: "there is a minimum of one cycle delay from the time when
866 		// the processor recognises /HOLD = 0 until /HOLDA = 0"
867 		if (m_hold_state)
868 		{
869 			// assert hold acknowledge if external hold enabled
870 			if (!(m_primary_bus_control & NOHOLD))
871 			{
872 				m_primary_bus_control |= HOLDST;
873 				m_holda_cb(ASSERT_LINE);
874 			}
875 		}
876 		else
877 		{
878 			// clear hold acknowledge if port is held externally
879 			if ((m_primary_bus_control & HOLDST) && !(m_primary_bus_control & HIZ))
880 			{
881 				m_primary_bus_control &= ~HOLDST;
882 				m_holda_cb(CLEAR_LINE);
883 			}
884 		}
885 		return;
886 	}
887 
888 	// update the external state
889 	uint16_t intmask = 1 << inputnum;
890 	if (state == ASSERT_LINE)
891 	{
892 		m_irq_state |= intmask;
893 		IREG(TMR_IF) |= intmask;
894 	}
895 	else
896 		m_irq_state &= ~intmask;
897 
898 	// external interrupts are level-sensitive on the '31 and can be
899 	// configured as such on the '32; in that case, if the external
900 	// signal is high, we need to update the value in IF accordingly
901 	if (m_chip_type != CHIP_TYPE_TMS32032 || (IREG(TMR_ST) & 0x4000) == 0)
902 		IREG(TMR_IF) |= m_irq_state & 0x0f;
903 }
904 
905 
906 //-------------------------------------------------
907 //  execute_run - execute until our icount expires
908 //-------------------------------------------------
909 
execute_run()910 void tms3203x_device::execute_run()
911 {
912 	// check IRQs up front
913 	check_irqs();
914 
915 	// if we're idling, just eat the cycles
916 	if (m_is_idling)
917 	{
918 		m_icount = 0;
919 		return;
920 	}
921 
922 	// non-debug case
923 	if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
924 	{
925 		while (m_icount > 0)
926 		{
927 			if ((IREG(TMR_ST) & RMFLAG) && m_pc == IREG(TMR_RE) + 1)
928 			{
929 				if ((int32_t)--IREG(TMR_RC) >= 0)
930 					m_pc = IREG(TMR_RS);
931 				else
932 				{
933 					IREG(TMR_ST) &= ~RMFLAG;
934 					if (m_delayed)
935 					{
936 						m_delayed = false;
937 						if (m_irq_pending)
938 						{
939 							m_irq_pending = false;
940 							check_irqs();
941 						}
942 					}
943 				}
944 				continue;
945 			}
946 
947 			execute_one();
948 		}
949 	}
950 
951 	// debugging case
952 	else
953 	{
954 		while (m_icount > 0)
955 		{
956 			// watch for out-of-range stack pointers
957 			if (IREG(TMR_SP) & 0xff000000)
958 				machine().debug_break();
959 			if ((IREG(TMR_ST) & RMFLAG) && m_pc == IREG(TMR_RE) + 1)
960 			{
961 				if ((int32_t)--IREG(TMR_RC) >= 0)
962 					m_pc = IREG(TMR_RS);
963 				else
964 				{
965 					IREG(TMR_ST) &= ~RMFLAG;
966 					if (m_delayed)
967 					{
968 						m_delayed = false;
969 						if (m_irq_pending)
970 						{
971 							m_irq_pending = false;
972 							check_irqs();
973 						}
974 					}
975 				}
976 				continue;
977 			}
978 
979 			debugger_instruction_hook(m_pc);
980 			execute_one();
981 		}
982 	}
983 }
984 
985 // internal peripherals
primary_bus_control_w(offs_t offset,uint32_t data,uint32_t mem_mask)986 void tms3203x_device::primary_bus_control_w(offs_t offset, uint32_t data, uint32_t mem_mask)
987 {
988 	// change in internal hold state
989 	if ((m_primary_bus_control ^ data) & HIZ)
990 	{
991 		if (m_primary_bus_control & HOLDST)
992 			m_primary_bus_control &= ~HOLDST;
993 		else
994 			m_primary_bus_control |= HOLDST;
995 		m_holda_cb(data & HIZ ? ASSERT_LINE : CLEAR_LINE);
996 	}
997 
998 	// enable of external hold with hold pending
999 	if ((m_primary_bus_control & NOHOLD) && !(data & NOHOLD) && m_hold_state)
1000 	{
1001 		m_primary_bus_control |= HOLDST;
1002 		m_holda_cb(ASSERT_LINE);
1003 	}
1004 
1005 	// update register
1006 	m_primary_bus_control = (m_primary_bus_control & ~(mem_mask | WMASK)) | (data & mem_mask & WMASK);
1007 }
1008 
1009 
1010 //**************************************************************************
1011 //  CORE OPCODES
1012 //**************************************************************************
1013 
1014 #include "32031ops.hxx"
1015