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