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