1 /**************************************************************************\
2 * Texas Instruments TMS32010 DSP Emulator *
3 * *
4 * Copyright (C) 1999-2004+ Tony La Porta *
5 * You are not allowed to distribute this software commercially. *
6 * Written for the MAME project. *
7 * *
8 * *
9 * Notes : The term 'DMA' within this document, is in reference *
10 * to Direct Memory Addressing, and NOT the usual term *
11 * of Direct Memory Access. *
12 * This is a word based microcontroller, with addressing *
13 * architecture based on the Harvard addressing scheme. *
14 * *
15 * *
16 * *
17 * **** Change Log **** *
18 * *
19 * TLP (13-Jul-2002) *
20 * - Added Save-State support *
21 * - Converted the pending_irq flag to INTF (a real flag in this device) *
22 * - Fixed the ignore Interrupt Request for previous critical *
23 * instructions requiring an extra instruction to be processed. For *
24 * this reason, instant IRQ servicing cannot be supported here, so *
25 * INTF needs to be polled within the instruction execution loop *
26 * - Removed IRQ callback (IRQ ACK not supported on this device) *
27 * - A pending IRQ will remain pending until it's serviced. De-asserting *
28 * the IRQ Pin does not remove a pending IRQ state *
29 * - BIO is no longer treated as an IRQ line. It's polled when required. *
30 * This is the true behaviour of the device *
31 * - Removed the Clear OV flag from overflow instructions. Overflow *
32 * instructions can only set the flag. Flag test instructions clear it *
33 * - Fixed the ABST, SUBC and SUBH instructions *
34 * - Fixed the signedness in many equation based instructions *
35 * - Added the missing Previous PC to the get_register function *
36 * - Changed Cycle timings to include clock ticks *
37 * - Converted some registers from ints to pairs for much cleaner code *
38 * TLP (20-Jul-2002) Ver 1.10 *
39 * - Fixed the dissasembly from the debugger *
40 * - Changed all references from TMS320C10 to TMS32010 *
41 * ASG (24-Sep-2002) Ver 1.20 *
42 * - Fixed overflow handling *
43 * - Simplified logic in a few locations *
44 * TLP (22-Feb-2004) Ver 1.21 *
45 * - Overflow for ADDH only affects upper 16bits (was modifying 32 bits) *
46 * - Internal Data Memory map is assigned here now *
47 * - Cycle counts for invalid opcodes 7F1E and 7F1F are now 0 *
48 * *
49 \**************************************************************************/
50
51
52
53 #include "burnint.h"
54 #include "driver.h"
55 #include "state.h"
56 //#include "mamedbg.h"
57 #include "tms32010.h"
58 //#include "debugger.h"
59
60
61 /* 1 cycle equals 4 clock ticks */
62 #if 0
63 #define CLK TMS32010_CLOCK_DIVIDER
64 #else
65 #define CLK 1 /* Moved the clock timing back into the driver */
66 #endif
67
68
69 #ifndef INLINE
70 #define INLINE static inline
71 #endif
72
73
74 UINT16 *tms32010_ram = NULL;
75 UINT16 *tms32010_rom = NULL;
76
77 static UINT32 tms32010_cycles = 0;
78 static UINT32 tms32010_current_cycles = 0;
79
80 static void (*tms32010_write_port)(INT32,UINT16);
81 static UINT16 (*tms32010_read_port)(INT32);
82
program_read_word_16be(UINT16 address)83 static UINT16 program_read_word_16be(UINT16 address)
84 {
85 UINT16 r = tms32010_rom[address & 0xfff];
86 r = (r << 8) | (r >> 8);
87 return r;
88 }
89
program_write_word_16be(UINT16 address,UINT16 data)90 static void program_write_word_16be(UINT16 address, UINT16 data)
91 {
92 data = (data << 8) | (data >> 8);
93
94 tms32010_rom[address & 0xfff] = data;
95 }
96
data_read_word_16be(UINT16 address)97 static UINT16 data_read_word_16be(UINT16 address)
98 {
99 UINT16 r = tms32010_ram[address & 0xff];
100
101 r = (r << 8) | (r >> 8);
102
103 return r;
104 }
105
data_write_word_16be(UINT16 address,UINT16 data)106 static void data_write_word_16be(UINT16 address, UINT16 data)
107 {
108 data = (data << 8) | (data >> 8);
109
110 tms32010_ram[address & 0xff] = data;
111 }
112
io_read_word(INT32 offset)113 UINT16 io_read_word(INT32 offset)
114 {
115 if (tms32010_read_port) {
116 UINT16 r = tms32010_read_port(offset);
117 return r;
118 }
119
120 return 0;
121 }
122
io_write_word(INT32 offset,UINT16 data)123 void io_write_word(INT32 offset, UINT16 data)
124 {
125 if (tms32010_write_port) {
126 tms32010_write_port(offset, data);
127 return;
128 }
129 }
130
tms32010_set_write_port_handler(void (* pointer)(INT32,UINT16))131 void tms32010_set_write_port_handler(void (*pointer)(INT32,UINT16))
132 {
133 tms32010_write_port = pointer;
134 }
135
tms32010_set_read_port_handler(UINT16 (* pointer)(INT32))136 void tms32010_set_read_port_handler(UINT16 (*pointer)(INT32))
137 {
138 tms32010_read_port = pointer;
139 }
140
141
142 #define TMS32010_BIO_In (io_read_word(TMS32010_BIO))
143 #define TMS32010_In(Port) (io_read_word(Port))
144 #define TMS32010_Out(Port,Value) (io_write_word(Port,Value))
145 #define TMS32010_ROM_RDMEM(A) (program_read_word_16be((A)))
146 #define TMS32010_ROM_WRMEM(A,V) (program_write_word_16be((A),V))
147 #define TMS32010_RAM_RDMEM(A) (data_read_word_16be((A)))
148 #define TMS32010_RAM_WRMEM(A,V) (data_write_word_16be((A),V))
149 #define TMS32010_RDOP(A) (program_read_word_16be((A)))
150 #define TMS32010_RDOP_ARG(A) (program_read_word_16be((A)))
151
152
153
154 #define M_RDROM(A) TMS32010_ROM_RDMEM(A)
155 #define M_WRTROM(A,V) TMS32010_ROM_WRMEM(A,V)
156 #define M_RDRAM(A) TMS32010_RAM_RDMEM(A)
157 #define M_WRTRAM(A,V) TMS32010_RAM_WRMEM(A,V)
158 #define M_RDOP(A) TMS32010_RDOP(A)
159 #define M_RDOP_ARG(A) TMS32010_RDOP_ARG(A)
160 #define P_IN(A) TMS32010_In(A)
161 #define P_OUT(A,V) TMS32010_Out(A,V)
162 #define BIO_IN TMS32010_BIO_In
163
164
165
166 typedef struct /* Page 3-6 shows all registers */
167 {
168 /******************** CPU Internal Registers *******************/
169 UINT16 PC;
170 UINT16 PREVPC; /* previous program counter */
171 UINT16 STR;
172 PAIR ACC;
173 PAIR ALU;
174 PAIR Preg;
175 UINT16 Treg;
176 UINT16 AR[2];
177 UINT16 STACK[4];
178
179 /********************** Status data ****************************/
180 PAIR opcode;
181 INT32 INTF; /* Pending Interrupt flag */
182 } tms32010_Regs;
183
184 static tms32010_Regs R;
185 static PAIR oldacc;
186 static UINT16 memaccess;
187 static INT32 tms32010_icount;
188 static INT32 addr_mask;
189 typedef void (*opcode_fn) (void);
190
191
192 /******** The following is the Status (Flag) register definition. *********/
193 /* 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */
194 /* OV | OVM | INTM | 1 | 1 | 1 | 1 | ARP | 1 | 1 | 1 | 1 | 1 | 1 | 1 | DP */
195 #define OV_FLAG 0x8000 /* OV (Overflow flag) 1 indicates an overflow */
196 #define OVM_FLAG 0x4000 /* OVM (Overflow Mode bit) 1 forces ACC overflow to greatest positive or negative saturation value */
197 #define INTM_FLAG 0x2000 /* INTM (Interrupt Mask flag) 0 enables maskable interrupts */
198 #define ARP_REG 0x0100 /* ARP (Auxiliary Register Pointer) */
199 #define DP_REG 0x0001 /* DP (Data memory Pointer (bank) bit) */
200
201 #define OV ( R.STR & OV_FLAG) /* OV (Overflow flag) */
202 #define OVM ( R.STR & OVM_FLAG) /* OVM (Overflow Mode bit) 1 indicates an overflow */
203 #define INTM ( R.STR & INTM_FLAG) /* INTM (Interrupt enable flag) 0 enables maskable interrupts */
204 #define ARP ((R.STR & ARP_REG) >> 8) /* ARP (Auxiliary Register Pointer) */
205 #define DP ((R.STR & DP_REG) << 7) /* DP (Data memory Pointer bit) */
206
207 #define DMA_DP (DP | (R.opcode.b.l & 0x7f)) /* address used in direct memory access operations */
208 #define DMA_DP1 (0x80 | R.opcode.b.l) /* address used in direct memory access operations for sst instruction */
209 #define IND (R.AR[ARP] & 0xff) /* address used in indirect memory access operations */
210
211
212
213
214 /************************************************************************
215 * Shortcuts
216 ************************************************************************/
217
CLR(UINT16 flag)218 INLINE void CLR(UINT16 flag) { R.STR &= ~flag; R.STR |= 0x1efe; }
SET(UINT16 flag)219 INLINE void SET(UINT16 flag) { R.STR |= flag; R.STR |= 0x1efe; }
220
221
CALCULATE_ADD_OVERFLOW(INT32 addval)222 INLINE void CALCULATE_ADD_OVERFLOW(INT32 addval)
223 {
224 if ((INT32)(~(oldacc.d ^ addval) & (oldacc.d ^ R.ACC.d)) < 0) {
225 SET(OV_FLAG);
226 if (OVM)
227 R.ACC.d = ((INT32)oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
228 }
229 }
CALCULATE_SUB_OVERFLOW(INT32 subval)230 INLINE void CALCULATE_SUB_OVERFLOW(INT32 subval)
231 {
232 if ((INT32)((oldacc.d ^ subval) & (oldacc.d ^ R.ACC.d)) < 0) {
233 SET(OV_FLAG);
234 if (OVM)
235 R.ACC.d = ((INT32)oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
236 }
237 }
238
POP_STACK(void)239 INLINE UINT16 POP_STACK(void)
240 {
241 UINT16 data = R.STACK[3];
242 R.STACK[3] = R.STACK[2];
243 R.STACK[2] = R.STACK[1];
244 R.STACK[1] = R.STACK[0];
245 return (data & addr_mask);
246 }
PUSH_STACK(UINT16 data)247 INLINE void PUSH_STACK(UINT16 data)
248 {
249 R.STACK[0] = R.STACK[1];
250 R.STACK[1] = R.STACK[2];
251 R.STACK[2] = R.STACK[3];
252 R.STACK[3] = (data & addr_mask);
253 }
254
GET_MEM_ADDR(UINT16 DMA)255 INLINE void GET_MEM_ADDR(UINT16 DMA)
256 {
257 if (R.opcode.b.l & 0x80)
258 memaccess = IND;
259 else
260 memaccess = DMA;
261 }
UPDATE_AR(void)262 INLINE void UPDATE_AR(void)
263 {
264 if (R.opcode.b.l & 0x30) {
265 UINT16 tmpAR = R.AR[ARP];
266 if (R.opcode.b.l & 0x20) tmpAR++ ;
267 if (R.opcode.b.l & 0x10) tmpAR-- ;
268 R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
269 }
270 }
UPDATE_ARP(void)271 INLINE void UPDATE_ARP(void)
272 {
273 if (~R.opcode.b.l & 0x08) {
274 if (R.opcode.b.l & 0x01) SET(ARP_REG);
275 else CLR(ARP_REG);
276 }
277 }
278
279
getdata(UINT8 shift,UINT8 signext)280 INLINE void getdata(UINT8 shift,UINT8 signext)
281 {
282 GET_MEM_ADDR(DMA_DP);
283 R.ALU.d = (UINT16)M_RDRAM(memaccess);
284 if (signext) R.ALU.d = (INT16)R.ALU.d;
285 R.ALU.d <<= shift;
286 if (R.opcode.b.l & 0x80) {
287 UPDATE_AR();
288 UPDATE_ARP();
289 }
290 }
291
putdata(UINT16 data)292 INLINE void putdata(UINT16 data)
293 {
294 GET_MEM_ADDR(DMA_DP);
295 if (R.opcode.b.l & 0x80) {
296 UPDATE_AR();
297 UPDATE_ARP();
298 }
299 M_WRTRAM(memaccess,data);
300 }
putdata_sar(UINT8 data)301 INLINE void putdata_sar(UINT8 data)
302 {
303 GET_MEM_ADDR(DMA_DP);
304 if (R.opcode.b.l & 0x80) {
305 UPDATE_AR();
306 UPDATE_ARP();
307 }
308 M_WRTRAM(memaccess,R.AR[data]);
309 }
putdata_sst(UINT16 data)310 INLINE void putdata_sst(UINT16 data)
311 {
312 GET_MEM_ADDR(DMA_DP1); /* Page 1 only */
313 if (R.opcode.b.l & 0x80) {
314 UPDATE_AR();
315 }
316 M_WRTRAM(memaccess,data);
317 }
318
319
320
321 /************************************************************************
322 * Emulate the Instructions
323 ************************************************************************/
324
325 /* This following function is here to fill in the void for */
326 /* the opcode call function. This function is never called. */
327
other_7F_opcodes(void)328 static void other_7F_opcodes(void) { }
329
330
illegal(void)331 static void illegal(void)
332 {
333 logerror("TMS32010: PC=%04x, Illegal opcode = %04x\n", (R.PC-1), R.opcode.w.l);
334 }
335
abst(void)336 static void abst(void)
337 {
338 if ( (INT32)(R.ACC.d) < 0 ) {
339 R.ACC.d = -R.ACC.d;
340 if (OVM && (R.ACC.d == 0x80000000)) R.ACC.d-- ;
341 }
342 }
343
344 /*** The manual does not mention overflow with the ADD? instructions *****
345 *** however I implemented overflow, coz it doesnt make sense otherwise **
346 *** and newer generations of this type of chip supported it. I think ****
347 *** the manual is wrong (apart from other errors the manual has). *******
348
349 static void add_sh(void) { getdata(R.opcode.b.h,1); R.ACC.d += R.ALU.d; }
350 static void addh(void) { getdata(0,0); R.ACC.d += (R.ALU.d << 16); }
351 ***/
352
add_sh(void)353 static void add_sh(void)
354 {
355 oldacc.d = R.ACC.d;
356 getdata((R.opcode.b.h & 0xf),1);
357 R.ACC.d += R.ALU.d;
358 CALCULATE_ADD_OVERFLOW(R.ALU.d);
359 }
addh(void)360 static void addh(void)
361 {
362 oldacc.d = R.ACC.d;
363 getdata(0,0);
364 R.ACC.w.h += R.ALU.w.l;
365 if ((INT16)(~(oldacc.w.h ^ R.ALU.w.h) & (oldacc.w.h ^ R.ACC.w.h)) < 0) {
366 SET(OV_FLAG);
367 if (OVM)
368 R.ACC.w.h = ((INT16)oldacc.w.h < 0) ? 0x8000 : 0x7fff;
369 }
370 }
adds(void)371 static void adds(void)
372 {
373 oldacc.d = R.ACC.d;
374 getdata(0,0);
375 R.ACC.d += R.ALU.d;
376 CALCULATE_ADD_OVERFLOW(R.ALU.d);
377 }
and_(void)378 static void and_(void)
379 {
380 getdata(0,0);
381 R.ACC.d &= R.ALU.d;
382 }
apac(void)383 static void apac(void)
384 {
385 oldacc.d = R.ACC.d;
386 R.ACC.d += R.Preg.d;
387 CALCULATE_ADD_OVERFLOW(R.Preg.d);
388 }
br(void)389 static void br(void)
390 {
391 R.PC = M_RDOP_ARG(R.PC);
392 }
banz(void)393 static void banz(void)
394 {
395 if (R.AR[ARP] & 0x01ff)
396 R.PC = M_RDOP_ARG(R.PC);
397 else
398 R.PC++ ;
399 R.ALU.w.l = R.AR[ARP];
400 R.ALU.w.l-- ;
401 R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (R.ALU.w.l & 0x01ff);
402 }
bgez(void)403 static void bgez(void)
404 {
405 if ( (INT32)(R.ACC.d) >= 0 )
406 R.PC = M_RDOP_ARG(R.PC);
407 else
408 R.PC++ ;
409 }
bgz(void)410 static void bgz(void)
411 {
412 if ( (INT32)(R.ACC.d) > 0 )
413 R.PC = M_RDOP_ARG(R.PC);
414 else
415 R.PC++ ;
416 }
bioz(void)417 static void bioz(void)
418 {
419 if (BIO_IN != CPU_IRQSTATUS_NONE)
420 R.PC = M_RDOP_ARG(R.PC);
421 else
422 R.PC++ ;
423 }
blez(void)424 static void blez(void)
425 {
426 if ( (INT32)(R.ACC.d) <= 0 )
427 R.PC = M_RDOP_ARG(R.PC);
428 else
429 R.PC++ ;
430 }
blz(void)431 static void blz(void)
432 {
433 if ( (INT32)(R.ACC.d) < 0 )
434 R.PC = M_RDOP_ARG(R.PC);
435 else
436 R.PC++ ;
437 }
bnz(void)438 static void bnz(void)
439 {
440 if (R.ACC.d != 0)
441 R.PC = M_RDOP_ARG(R.PC);
442 else
443 R.PC++ ;
444 }
bv(void)445 static void bv(void)
446 {
447 if (OV) {
448 R.PC = M_RDOP_ARG(R.PC);
449 CLR(OV_FLAG);
450 }
451 else
452 R.PC++ ;
453 }
bz(void)454 static void bz(void)
455 {
456 if (R.ACC.d == 0)
457 R.PC = M_RDOP_ARG(R.PC);
458 else
459 R.PC++ ;
460 }
cala(void)461 static void cala(void)
462 {
463 PUSH_STACK(R.PC);
464 R.PC = R.ACC.w.l & addr_mask;
465 }
call(void)466 static void call(void)
467 {
468 R.PC++ ;
469 PUSH_STACK(R.PC);
470 R.PC = M_RDOP_ARG((R.PC - 1)) & addr_mask;
471 }
dint(void)472 static void dint(void)
473 {
474 SET(INTM_FLAG);
475 }
dmov(void)476 static void dmov(void)
477 {
478 getdata(0,0);
479 M_WRTRAM((memaccess + 1),R.ALU.w.l);
480 }
eint(void)481 static void eint(void)
482 {
483 CLR(INTM_FLAG);
484 }
in_p(void)485 static void in_p(void)
486 {
487 R.ALU.w.l = P_IN( (R.opcode.b.h & 7) );
488 putdata(R.ALU.w.l);
489 }
lac_sh(void)490 static void lac_sh(void)
491 {
492 getdata((R.opcode.b.h & 0x0f),1);
493 R.ACC.d = R.ALU.d;
494 }
lack(void)495 static void lack(void)
496 {
497 R.ACC.d = R.opcode.b.l;
498 }
lar_ar0(void)499 static void lar_ar0(void)
500 {
501 getdata(0,0);
502 R.AR[0] = R.ALU.w.l;
503 }
lar_ar1(void)504 static void lar_ar1(void)
505 {
506 getdata(0,0);
507 R.AR[1] = R.ALU.w.l;
508 }
lark_ar0(void)509 static void lark_ar0(void)
510 {
511 R.AR[0] = R.opcode.b.l;
512 }
lark_ar1(void)513 static void lark_ar1(void)
514 {
515 R.AR[1] = R.opcode.b.l;
516 }
larp_mar(void)517 static void larp_mar(void)
518 {
519 if (R.opcode.b.l & 0x80) {
520 UPDATE_AR();
521 UPDATE_ARP();
522 }
523 }
ldp(void)524 static void ldp(void)
525 {
526 getdata(0,0);
527 if (R.ALU.d & 1)
528 SET(DP_REG);
529 else
530 CLR(DP_REG);
531 }
ldpk(void)532 static void ldpk(void)
533 {
534 if (R.opcode.b.l & 1)
535 SET(DP_REG);
536 else
537 CLR(DP_REG);
538 }
lst(void)539 static void lst(void)
540 {
541 R.opcode.b.l |= 0x08; /* Next arp not supported here, so mask it */
542 getdata(0,0);
543 R.ALU.w.l &= (~INTM_FLAG); /* Must not affect INTM */
544 R.STR &= INTM_FLAG;
545 R.STR |= R.ALU.w.l;
546 R.STR |= 0x1efe;
547 }
lt(void)548 static void lt(void)
549 {
550 getdata(0,0);
551 R.Treg = R.ALU.w.l;
552 }
lta(void)553 static void lta(void)
554 {
555 oldacc.d = R.ACC.d;
556 getdata(0,0);
557 R.Treg = R.ALU.w.l;
558 R.ACC.d += R.Preg.d;
559 CALCULATE_ADD_OVERFLOW(R.Preg.d);
560 }
ltd(void)561 static void ltd(void)
562 {
563 oldacc.d = R.ACC.d;
564 getdata(0,0);
565 R.Treg = R.ALU.w.l;
566 M_WRTRAM((memaccess + 1),R.ALU.w.l);
567 R.ACC.d += R.Preg.d;
568 CALCULATE_ADD_OVERFLOW(R.Preg.d);
569 }
mpy(void)570 static void mpy(void)
571 {
572 getdata(0,0);
573 R.Preg.d = (INT16)R.ALU.w.l * (INT16)R.Treg;
574 if (R.Preg.d == 0x40000000) R.Preg.d = 0xc0000000;
575 }
mpyk(void)576 static void mpyk(void)
577 {
578 R.Preg.d = (INT16)R.Treg * ((INT16)(R.opcode.w.l << 3) >> 3);
579 }
nop(void)580 static void nop(void)
581 {
582 /* Nothing to do */
583 }
or_(void)584 static void or_(void)
585 {
586 getdata(0,0);
587 R.ACC.w.l |= R.ALU.w.l;
588 }
out_p(void)589 static void out_p(void)
590 {
591 getdata(0,0);
592 P_OUT( (R.opcode.b.h & 7), R.ALU.w.l );
593 }
pac(void)594 static void pac(void)
595 {
596 R.ACC.d = R.Preg.d;
597 }
pop(void)598 static void pop(void)
599 {
600 R.ACC.w.l = POP_STACK();
601 R.ACC.w.h = 0x0000;
602 }
push(void)603 static void push(void)
604 {
605 PUSH_STACK(R.ACC.w.l);
606 }
ret(void)607 static void ret(void)
608 {
609 R.PC = POP_STACK();
610 }
rovm(void)611 static void rovm(void)
612 {
613 CLR(OVM_FLAG);
614 }
sach_sh(void)615 static void sach_sh(void)
616 {
617 R.ALU.d = (R.ACC.d << (R.opcode.b.h & 7));
618 putdata(R.ALU.w.h);
619 }
sacl(void)620 static void sacl(void)
621 {
622 putdata(R.ACC.w.l);
623 }
sar_ar0(void)624 static void sar_ar0(void)
625 {
626 putdata_sar(0);
627 }
sar_ar1(void)628 static void sar_ar1(void)
629 {
630 putdata_sar(1);
631 }
sovm(void)632 static void sovm(void)
633 {
634 SET(OVM_FLAG);
635 }
spac(void)636 static void spac(void)
637 {
638 oldacc.d = R.ACC.d;
639 R.ACC.d -= R.Preg.d;
640 CALCULATE_SUB_OVERFLOW(R.Preg.d);
641 }
sst(void)642 static void sst(void)
643 {
644 putdata_sst(R.STR);
645 }
sub_sh(void)646 static void sub_sh(void)
647 {
648 oldacc.d = R.ACC.d;
649 getdata((R.opcode.b.h & 0x0f),1);
650 R.ACC.d -= R.ALU.d;
651 CALCULATE_SUB_OVERFLOW(R.ALU.d);
652 }
subc(void)653 static void subc(void)
654 {
655 oldacc.d = R.ACC.d;
656 getdata(15,0);
657 R.ALU.d -= R.ALU.d;
658 if ((INT32)((oldacc.d ^ R.ALU.d) & (oldacc.d ^ R.ACC.d)) < 0)
659 SET(OV_FLAG);
660 if ( (INT32)(R.ALU.d) >= 0 )
661 R.ACC.d = ((R.ALU.d << 1) + 1);
662 else
663 R.ACC.d = (R.ACC.d << 1);
664 }
subh(void)665 static void subh(void)
666 {
667 oldacc.d = R.ACC.d;
668 getdata(16,0);
669 R.ACC.d -= R.ALU.d;
670 CALCULATE_SUB_OVERFLOW(R.ALU.d);
671 }
subs(void)672 static void subs(void)
673 {
674 oldacc.d = R.ACC.d;
675 getdata(0,0);
676 R.ACC.d -= R.ALU.d;
677 CALCULATE_SUB_OVERFLOW(R.ALU.d);
678 }
tblr(void)679 static void tblr(void)
680 {
681 R.ALU.d = M_RDROM((R.ACC.w.l & addr_mask));
682 putdata(R.ALU.w.l);
683 R.STACK[0] = R.STACK[1];
684 }
tblw(void)685 static void tblw(void)
686 {
687 getdata(0,0);
688 M_WRTROM(((R.ACC.w.l & addr_mask)),R.ALU.w.l);
689 R.STACK[0] = R.STACK[1];
690 }
xor_(void)691 static void xor_(void)
692 {
693 getdata(0,0);
694 R.ACC.w.l ^= R.ALU.w.l;
695 }
zac(void)696 static void zac(void)
697 {
698 R.ACC.d = 0;
699 }
zalh(void)700 static void zalh(void)
701 {
702 getdata(0,0);
703 R.ACC.w.h = R.ALU.w.l;
704 R.ACC.w.l = 0x0000;
705 }
zals(void)706 static void zals(void)
707 {
708 getdata(0,0);
709 R.ACC.w.l = R.ALU.w.l;
710 R.ACC.w.h = 0x0000;
711 }
712
713
714 /***********************************************************************
715 * Cycle Timings
716 ***********************************************************************/
717
718 static unsigned cycles_main[256]=
719 {
720 /*00*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
721 /*10*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
722 /*20*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
723 /*30*/ 1*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 1*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
724 /*40*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
725 /*50*/ 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
726 /*60*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 3*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
727 /*70*/ 1*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 3*CLK, 1*CLK, 0*CLK,
728 /*80*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
729 /*90*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
730 /*A0*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
731 /*B0*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
732 /*C0*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
733 /*D0*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
734 /*E0*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
735 /*F0*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 2*CLK, 2*CLK, 2*CLK, 0*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK
736 };
737
738 static unsigned cycles_7F_other[32]=
739 {
740 /*80*/ 1*CLK, 1*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 2*CLK, 2*CLK, 1*CLK, 1*CLK,
741 /*90*/ 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 2*CLK, 2*CLK, 0*CLK, 0*CLK
742 };
743
744
745 /***********************************************************************
746 * Opcode Table
747 ***********************************************************************/
748
749 static opcode_fn opcode_main[256]=
750 {
751 /*00*/ add_sh ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh
752 /*08*/ ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh ,add_sh
753 /*10*/ ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh
754 /*18*/ ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh ,sub_sh
755 /*20*/ ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh
756 /*28*/ ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh ,lac_sh
757 /*30*/ ,sar_ar0 ,sar_ar1 ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
758 /*38*/ ,lar_ar0 ,lar_ar1 ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
759 /*40*/ ,in_p ,in_p ,in_p ,in_p ,in_p ,in_p ,in_p ,in_p
760 /*48*/ ,out_p ,out_p ,out_p ,out_p ,out_p ,out_p ,out_p ,out_p
761 /*50*/ ,sacl ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
762 /*58*/ ,sach_sh ,sach_sh ,sach_sh ,sach_sh ,sach_sh ,sach_sh ,sach_sh ,sach_sh
763 /*60*/ ,addh ,adds ,subh ,subs ,subc ,zalh ,zals ,tblr
764 /*68*/ ,larp_mar ,dmov ,lt ,ltd ,lta ,mpy ,ldpk ,ldp
765 /*70*/ ,lark_ar0 ,lark_ar1 ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
766 /*78*/ ,xor_ ,and_ ,or_ ,lst ,sst ,tblw ,lack ,other_7F_opcodes
767 /*80*/ ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk
768 /*88*/ ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk
769 /*90*/ ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk
770 /*98*/ ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk ,mpyk
771 /*A0*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
772 /*A8*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
773 /*B0*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
774 /*B8*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
775 /*C0*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
776 /*C8*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
777 /*D0*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
778 /*D8*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
779 /*E0*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
780 /*E8*/ ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
781 /*F0*/ ,illegal ,illegal ,illegal ,illegal ,banz ,bv ,bioz ,illegal
782 /*F8*/ ,call ,br ,blz ,blez ,bgz ,bgez ,bnz ,bz
783 };
784
785 static opcode_fn opcode_7F_other[32]=
786 {
787 /*80*/ nop ,dint ,eint ,illegal ,illegal ,illegal ,illegal ,illegal
788 /*88*/ ,abst ,zac ,rovm ,sovm ,cala ,ret ,pac ,apac
789 /*90*/ ,spac ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal ,illegal
790 /*98*/ ,illegal ,illegal ,illegal ,illegal ,push ,pop ,illegal ,illegal
791 };
792
793
794
795 /****************************************************************************
796 * Inits CPU emulation
797 ****************************************************************************/
tms32010_init(void)798 void tms32010_init (void)
799 {
800 #if 0
801 state_save_register_item("tms32010", index, R.PC);
802 state_save_register_item("tms32010", index, R.PREVPC);
803 state_save_register_item("tms32010", index, R.STR);
804 state_save_register_item("tms32010", index, R.ACC.d);
805 state_save_register_item("tms32010", index, R.ALU.d);
806 state_save_register_item("tms32010", index, R.Preg.d);
807 state_save_register_item("tms32010", index, R.Treg);
808 state_save_register_item("tms32010", index, R.AR[0]);
809 state_save_register_item("tms32010", index, R.AR[1]);
810 state_save_register_item("tms32010", index, R.STACK[0]);
811 state_save_register_item("tms32010", index, R.STACK[1]);
812 state_save_register_item("tms32010", index, R.STACK[2]);
813 state_save_register_item("tms32010", index, R.STACK[3]);
814 state_save_register_item("tms32010", index, R.INTF);
815 state_save_register_item("tms32010", index, R.opcode.d);
816 #endif
817 }
818
819 /****************************************************************************
820 * Reset registers to their initial values
821 ****************************************************************************/
tms32010_reset(void)822 void tms32010_reset (void)
823 {
824 R.PC = 0;
825 R.STR = 0xfefe;
826 R.ACC.d = 0;
827 R.INTF = TMS32010_INT_NONE;
828 addr_mask = 0x0fff; /* TMS32010 can only address 0x0fff */
829 /* however other TMS3201x devices */
830 /* can address up to 0xffff (incase */
831 /* their support is ever added). */
832
833 tms32010_cycles = 0;
834 }
835
836
837 /****************************************************************************
838 * Shut down CPU emulation
839 ****************************************************************************/
tms32010_exit(void)840 void tms32010_exit (void)
841 {
842 /* nothing to do ? */
843 }
844
845
846 /****************************************************************************
847 * Issue an interrupt if necessary
848 ****************************************************************************/
tms32010_Ext_IRQ(void)849 int tms32010_Ext_IRQ(void)
850 {
851 if (INTM == 0)
852 {
853 logerror("TMS32010: EXT INTERRUPT\n");
854 R.INTF = TMS32010_INT_NONE;
855 SET(INTM_FLAG);
856 PUSH_STACK(R.PC);
857 R.PC = 0x0002;
858 return (3*CLK); /* 3 cycles used due to PUSH and DINT operation ? */
859 }
860 return (0*CLK);
861 }
862
863
864
865 /****************************************************************************
866 * Execute IPeriod. Return 0 if emulation should be stopped
867 ****************************************************************************/
tms32010_execute(int cycles)868 int tms32010_execute(int cycles)
869 {
870 tms32010_icount = cycles;
871
872 tms32010_current_cycles = cycles;
873
874 do
875 {
876 if (R.INTF) {
877 /* Dont service INT if prev instruction was MPY, MPYK or EINT */
878 if ((R.opcode.b.h != 0x6d) && ((R.opcode.b.h & 0xe0) != 0x80) && (R.opcode.w.l != 0x7f82))
879 tms32010_icount -= tms32010_Ext_IRQ();
880 }
881
882 R.PREVPC = R.PC;
883
884 //CALL_MAME_DEBUG;
885
886 R.opcode.d = M_RDOP(R.PC);
887 R.PC++;
888
889 if (R.opcode.b.h != 0x7f) { /* Do all opcodes except the 7Fxx ones */
890 tms32010_icount -= cycles_main[R.opcode.b.h];
891 (*(opcode_main[R.opcode.b.h]))();
892 }
893 else { /* Opcode major byte 7Fxx has many opcodes in its minor byte */
894 tms32010_icount -= cycles_7F_other[(R.opcode.b.l & 0x1f)];
895 (*(opcode_7F_other[(R.opcode.b.l & 0x1f)]))();
896 }
897 } while (tms32010_icount>0);
898
899 tms32010_current_cycles = 0;
900 tms32010_cycles += cycles - tms32010_icount;
901
902 return cycles - tms32010_icount;
903 }
904
tms32010TotalCycles()905 UINT32 tms32010TotalCycles()
906 {
907 return tms32010_cycles + (tms32010_current_cycles - tms32010_icount);
908 }
909
tms32010NewFrame()910 void tms32010NewFrame()
911 {
912 tms32010_cycles = 0;
913 }
914
tms32010RunEnd()915 void tms32010RunEnd()
916 {
917 tms32010_icount = 0;
918 }
919
tms32010_scan(INT32 nAction)920 void tms32010_scan(INT32 nAction)
921 {
922 if (nAction & ACB_DRIVER_DATA) {
923 struct BurnArea ba;
924 memset(&ba, 0, sizeof(ba));
925 ba.Data = &R;
926 ba.nLen = sizeof(tms32010_Regs);
927 ba.szName = "tms32010 Regs";
928 BurnAcb(&ba);
929
930 SCAN_VAR(oldacc);
931 SCAN_VAR(memaccess);
932 SCAN_VAR(tms32010_icount);
933 }
934 }
935
936 #if 0
937 /****************************************************************************
938 * Get all registers in given buffer
939 ****************************************************************************/
940 static void tms32010_get_context (void *dst)
941 {
942 if( dst )
943 *(tms32010_Regs*)dst = R;
944 }
945
946 /****************************************************************************
947 * Set all registers to given values
948 ****************************************************************************/
949 static void tms32010_set_context (void *src)
950 {
951 if (src)
952 R = *(tms32010_Regs*)src;
953 }
954 #endif
955
956 /****************************************************************************
957 * Set IRQ line state
958 ****************************************************************************/
tms32010_set_irq_line(int irqline,int state)959 void tms32010_set_irq_line(int irqline, int state)
960 {
961 /* Pending Interrupts cannot be cleared! */
962 if (state == CPU_IRQSTATUS_ACK) R.INTF |= TMS32010_INT_PENDING;
963 }
964
965 #if 0
966 static offs_t tms32010_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
967 {
968 #ifdef MAME_DEBUG
969 return Dasm32010( buffer, pc, oprom, opram );
970 #else
971 sprintf( buffer, "$%04X", (oprom[0] << 8) | oprom[1] );
972 return 2;
973 #endif
974 }
975
976
977 /****************************************************************************
978 * Internal Memory Map
979 ****************************************************************************/
980
981 static ADDRESS_MAP_START( tms32010_ram, ADDRESS_SPACE_DATA, 16 )
982 AM_RANGE(0x00, 0x7f) AM_RAM /* Page 0 */
983 AM_RANGE(0x80, 0x8f) AM_RAM /* Page 1 */
984 ADDRESS_MAP_END
985
986
987 /**************************************************************************
988 * Generic set_info
989 **************************************************************************/
990
991 static void tms32010_set_info(UINT32 state, union cpuinfo *info)
992 {
993 switch (state)
994 {
995 /* --- the following bits of info are set as 64-bit signed integers --- */
996 case CPUINFO_INT_INPUT_STATE + 0: tms32010_set_irq_line(0, info->i); break;
997
998 case CPUINFO_INT_PC:
999 case CPUINFO_INT_REGISTER + TMS32010_PC: R.PC = info->i; break;
1000 /* This is actually not a stack pointer, but the stack contents */
1001 /* Stack is a 4 level First In Last Out stack */
1002 case CPUINFO_INT_SP:
1003 case CPUINFO_INT_REGISTER + TMS32010_STK3: R.STACK[3] = info->i; break;
1004 case CPUINFO_INT_REGISTER + TMS32010_STR: R.STR = info->i; break;
1005 case CPUINFO_INT_REGISTER + TMS32010_ACC: R.ACC.d = info->i; break;
1006 case CPUINFO_INT_REGISTER + TMS32010_PREG: R.Preg.d = info->i; break;
1007 case CPUINFO_INT_REGISTER + TMS32010_TREG: R.Treg = info->i; break;
1008 case CPUINFO_INT_REGISTER + TMS32010_AR0: R.AR[0] = info->i; break;
1009 case CPUINFO_INT_REGISTER + TMS32010_AR1: R.AR[1] = info->i; break;
1010 }
1011 }
1012
1013
1014
1015 /**************************************************************************
1016 * Generic get_info
1017 **************************************************************************/
1018
1019 void tms32010_get_info(UINT32 state, union cpuinfo *info)
1020 {
1021 switch (state)
1022 {
1023 /* --- the following bits of info are returned as 64-bit signed integers --- */
1024 case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(R); break;
1025 case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
1026 case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
1027 case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
1028 case CPUINFO_INT_CLOCK_DIVIDER: info->i = TMS32010_CLOCK_DIVIDER; break;
1029 case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
1030 case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
1031 case CPUINFO_INT_MIN_CYCLES: info->i = 1*CLK; break;
1032 case CPUINFO_INT_MAX_CYCLES: info->i = 3*CLK; break;
1033
1034 case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
1035 case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 12; break;
1036 case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -1; break;
1037 case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 16; break;
1038 case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; break;
1039 case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = -1; break;
1040 case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
1041 case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 5; break;
1042 case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = -1; break;
1043
1044 case CPUINFO_INT_INPUT_STATE + 0: info->i = (R.INTF & TMS32010_INT_PENDING) ? ASSERT_LINE : CLEAR_LINE; break;
1045
1046 case CPUINFO_INT_PREVIOUSPC: info->i = R.PREVPC; break;
1047
1048 case CPUINFO_INT_PC:
1049 case CPUINFO_INT_REGISTER + TMS32010_PC: info->i = R.PC; break;
1050 /* This is actually not a stack pointer, but the stack contents */
1051 case CPUINFO_INT_SP:
1052 case CPUINFO_INT_REGISTER + TMS32010_STK3: info->i = R.STACK[3]; break;
1053 case CPUINFO_INT_REGISTER + TMS32010_ACC: info->i = R.ACC.d; break;
1054 case CPUINFO_INT_REGISTER + TMS32010_STR: info->i = R.STR; break;
1055 case CPUINFO_INT_REGISTER + TMS32010_PREG: info->i = R.Preg.d; break;
1056 case CPUINFO_INT_REGISTER + TMS32010_TREG: info->i = R.Treg; break;
1057 case CPUINFO_INT_REGISTER + TMS32010_AR0: info->i = R.AR[0]; break;
1058 case CPUINFO_INT_REGISTER + TMS32010_AR1: info->i = R.AR[1]; break;
1059
1060 /* --- the following bits of info are returned as pointers to data or functions --- */
1061 case CPUINFO_PTR_SET_INFO: info->setinfo = tms32010_set_info; break;
1062 case CPUINFO_PTR_GET_CONTEXT: info->getcontext = tms32010_get_context; break;
1063 case CPUINFO_PTR_SET_CONTEXT: info->setcontext = tms32010_set_context; break;
1064 case CPUINFO_PTR_INIT: info->init = tms32010_init; break;
1065 case CPUINFO_PTR_RESET: info->reset = tms32010_reset; break;
1066 case CPUINFO_PTR_EXIT: info->exit = tms32010_exit; break;
1067 case CPUINFO_PTR_EXECUTE: info->execute = tms32010_execute; break;
1068 case CPUINFO_PTR_BURN: info->burn = NULL; break;
1069 case CPUINFO_PTR_DISASSEMBLE: info->disassemble = tms32010_dasm; break;
1070 case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &tms32010_icount; break;
1071 case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map = construct_map_tms32010_ram; break;
1072
1073 /* --- the following bits of info are returned as NULL-terminated strings --- */
1074 case CPUINFO_STR_NAME: strcpy(info->s = cpuintrf_temp_str(), "TMS32010"); break;
1075 case CPUINFO_STR_CORE_FAMILY: strcpy(info->s = cpuintrf_temp_str(), "Texas Instruments TMS32010"); break;
1076 case CPUINFO_STR_CORE_VERSION: strcpy(info->s = cpuintrf_temp_str(), "1.21"); break;
1077 case CPUINFO_STR_CORE_FILE: strcpy(info->s = cpuintrf_temp_str(), __FILE__); break;
1078 case CPUINFO_STR_CORE_CREDITS: strcpy(info->s = cpuintrf_temp_str(), "Copyright (C)1999-2004+ by Tony La Porta"); break;
1079
1080 case CPUINFO_STR_FLAGS:
1081 sprintf(info->s = cpuintrf_temp_str(), "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
1082 R.STR & 0x8000 ? 'O':'.',
1083 R.STR & 0x4000 ? 'M':'.',
1084 R.STR & 0x2000 ? 'I':'.',
1085 R.STR & 0x1000 ? '.':'?',
1086 R.STR & 0x0800 ? 'a':'?',
1087 R.STR & 0x0400 ? 'r':'?',
1088 R.STR & 0x0200 ? 'p':'?',
1089 R.STR & 0x0100 ? '1':'0',
1090 R.STR & 0x0080 ? '.':'?',
1091 R.STR & 0x0040 ? '.':'?',
1092 R.STR & 0x0020 ? '.':'?',
1093 R.STR & 0x0010 ? '.':'?',
1094 R.STR & 0x0008 ? '.':'?',
1095 R.STR & 0x0004 ? 'd':'?',
1096 R.STR & 0x0002 ? 'p':'?',
1097 R.STR & 0x0001 ? '1':'0');
1098 break;
1099
1100 case CPUINFO_STR_REGISTER + +TMS32010_PC: sprintf(info->s = cpuintrf_temp_str(), "PC:%04X", R.PC); break;
1101 case CPUINFO_STR_REGISTER + +TMS32010_SP: sprintf(info->s = cpuintrf_temp_str(), "SP:%X", 0); /* fake stack pointer */ break;
1102 case CPUINFO_STR_REGISTER + +TMS32010_STR: sprintf(info->s = cpuintrf_temp_str(), "STR:%04X", R.STR); break;
1103 case CPUINFO_STR_REGISTER + +TMS32010_ACC: sprintf(info->s = cpuintrf_temp_str(), "ACC:%08X", R.ACC.d); break;
1104 case CPUINFO_STR_REGISTER + +TMS32010_PREG: sprintf(info->s = cpuintrf_temp_str(), "P:%08X", R.Preg.d); break;
1105 case CPUINFO_STR_REGISTER + +TMS32010_TREG: sprintf(info->s = cpuintrf_temp_str(), "T:%04X", R.Treg); break;
1106 case CPUINFO_STR_REGISTER + +TMS32010_AR0: sprintf(info->s = cpuintrf_temp_str(), "AR0:%04X", R.AR[0]); break;
1107 case CPUINFO_STR_REGISTER + +TMS32010_AR1: sprintf(info->s = cpuintrf_temp_str(), "AR1:%04X", R.AR[1]); break;
1108 case CPUINFO_STR_REGISTER + +TMS32010_STK0: sprintf(info->s = cpuintrf_temp_str(), "STK0:%04X", R.STACK[0]); break;
1109 case CPUINFO_STR_REGISTER + +TMS32010_STK1: sprintf(info->s = cpuintrf_temp_str(), "STK1:%04X", R.STACK[1]); break;
1110 case CPUINFO_STR_REGISTER + +TMS32010_STK2: sprintf(info->s = cpuintrf_temp_str(), "STK2:%04X", R.STACK[2]); break;
1111 case CPUINFO_STR_REGISTER + +TMS32010_STK3: sprintf(info->s = cpuintrf_temp_str(), "STK3:%04X", R.STACK[3]); break;
1112 }
1113 }
1114 #endif
1115