1 /*###################################################################################################
2 **
3 **	TMS34010: Portable Texas Instruments TMS34010 emulator
4 **
5 **	Copyright (C) Alex Pasadyn/Zsolt Vasvari 1998
6 **	 Parts based on code by Aaron Giles
7 **
8 **#################################################################################################*/
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include "driver.h"
13 #include "osd_cpu.h"
14 #include "cpuintrf.h"
15 #include "tms34010.h"
16 #include "34010ops.h"
17 
18 /************************************
19 
20 New 34020 ops:
21 
22 	0000 1100 000R dddd = ADDXYI IL,Rd
23 	iiii iiii iiii iiii
24 	iiii iiii iiii iiii
25 
26 	0000 0000 1111 00SD = BLMOVE S,D
27 
28 	0000 0110 0000 0000 = CEXEC S,c,ID,L
29 	cccc cccc S000 0000
30 	iiic cccc cccc cccc
31 
32 	1101 1000 0ccc cccS = CEXEC S,c,ID
33 	iiic cccc cccc cccc
34 
35 	0000 1000 1111 0010 = CLIP
36 
37 	0000 0110 011R dddd = CMOVCG Rd1,Rd2,S,c,ID
38 	cccc cccc S00R dddd
39 	iiic cccc cccc cccc
40 
41 	0000 0110 101R dddd = CMOVCM *Rd+,n,S,c,ID
42 	cccc cccc S00n nnnn
43 	iiic cccc cccc cccc
44 
45 	0000 0110 110R dddd = CMOVCM -*Rd,n,S,c,ID
46 	cccc cccc S00n nnnn
47 	iiic cccc cccc cccc
48 
49 	0000 0110 0110 0000 = CMOVCS c,ID
50 	cccc cccc 0000 0001
51 	iiic cccc cccc cccc
52 
53 	0000 0110 001R ssss = CMOVGC Rs,c,ID
54 	cccc cccc 0000 0000
55 	iiic cccc cccc cccc
56 
57 	0000 0110 010R ssss = CMOVGC Rs1,Rs2,S,c,ID
58 	cccc cccc S00R ssss
59 	iiic cccc cccc cccc
60 
61 	0000 0110 100n nnnn = CMOVMC *Rs+,n,S,c,ID
62 	cccc cccc S00R ssss
63 	iiic cccc cccc cccc
64 
65 	0000 1000 001n nnnn = CMOVMC -*Rs,n,S,c,ID
66 	cccc cccc S00R ssss
67 	iiic cccc cccc cccc
68 
69 	0000 0110 111R dddd = CMOVMC *Rs+,Rd,S,c,ID
70 	cccc cccc S00R ssss
71 	iiic cccc cccc cccc
72 
73 	0011 01kk kkkR dddd = CMPK k,Rd
74 
75 	0000 1010 100R dddd = CVDXYL Rd
76 
77 	0000 1010 011R dddd = CVMXYL Rd
78 
79 	1110 101s sssR dddd = CVSXYL Rs,Rd
80 
81 	0000 0010 101R dddd = EXGPS Rd
82 
83 	1101 1110 Z001 1010 = FLINE Z
84 
85 	0000 1010 1011 1011 = FPIXEQ
86 
87 	0000 1010 1101 1011 = FPIXNE
88 
89 	0000 0010 110R dddd = GETPS Rd
90 
91 	0000 0000 0100 0000 = IDLE
92 
93 	0000 1100 0101 0111 = LINIT
94 
95 	0000 0000 1000 0000 = MWAIT
96 
97 	0000 1010 0011 0111 = PFILL XY
98 
99 	0000 1110 0001 0111 = PIXBLT L,M,L
100 
101 	0000 1000 0110 0000 = RETM
102 
103 	0111 101s sssR dddd = RMO Rs,Rd
104 
105 	0000 0010 100R dddd = RPIX Rd
106 
107 	0000 0010 0111 0011 = SETCDP
108 
109 	0000 0010 1111 1011 = SETCMP
110 
111 	0000 0010 0101 0001 = SETCSP
112 
113 	0111 111s sssR dddd = SWAPF *Rs,Rd,0
114 
115 	0000 1110 1111 1010 = TFILL XY
116 
117 	0000 1000 0000 1111 = TRAPL
118 
119 	0000 1000 0101 0111 = VBLT B,L
120 
121 	0000 1010 0101 0111 = VFILL L
122 
123 	0000 1010 0000 0000 = VLCOL
124 
125 ************************************/
126 
127 
128 /*###################################################################################################
129 **	DEBUG STATE & STRUCTURES
130 **#################################################################################################*/
131 
132 #define VERBOSE 			0
133 #define LOG_CONTROL_REGS	0
134 #define LOG_GRAPHICS_OPS	0
135 
136 #if VERBOSE
137 #define LOG(x)	logerror x
138 #else
139 #define LOG(x)
140 #endif
141 
142 /*###################################################################################################
143 **	CORE STATE
144 **#################################################################################################*/
145 
146 /* TMS34010 State */
147 typedef struct
148 {
149 #ifdef MSB_FIRST
150 	INT16 y;
151 	INT16 x;
152 #else
153 	INT16 x;
154 	INT16 y;
155 #endif
156 } XY;
157 
158 typedef struct
159 {
160 	UINT32 op;
161 	UINT32 pc;
162 	UINT32 st;					/* Only here so we can display it in the debug window */
163 	union						/* The register files are interleaved, so */
164 	{							/* that the SP occupies the same location in both */
165 		INT32 Bregs[241];   	/* Only every 16th entry is actually used */
166 		XY BregsXY[241];
167 		struct
168 		{
169 			INT32 unused[225];
170 			union
171 			{
172 				INT32 Aregs[16];
173 				XY AregsXY[16];
174 			} a;
175 		} a;
176 	} regs;
177 	UINT32 nflag;
178 	UINT32 cflag;
179 	UINT32 notzflag;  /* So we can just do an assignment to set it */
180 	UINT32 vflag;
181 	UINT32 pflag;
182 	UINT32 ieflag;
183 	UINT32 fe0flag;
184 	UINT32 fe1flag;
185 	UINT32 fw[2];
186 	UINT32 fw_inc[2];  /* Same as fw[], except when fw = 0, fw_inc = 32 */
187 	UINT16 IOregs[32];
188 	UINT32 reset_deferred;
189 	UINT32 is_34020;
190 	mem_write_handler f0_write;
191 	mem_write_handler f1_write;
192 	mem_write_handler pixel_write;
193 	mem_read_handler f0_read;
194 	mem_read_handler f1_read;
195 	mem_read_handler pixel_read;
196 	UINT32 transparency;
197 	UINT32 window_checking;
198 	 INT32 (*raster_op)(INT32 newpix, INT32 oldpix);
199 	UINT32 xytolshiftcount1;
200 	UINT32 xytolshiftcount2;
201 	UINT16 *shiftreg;
202 	int (*irq_callback)(int irqline);
203 	int last_update_vcount;
204 	struct tms34010_config *config;
205 } tms34010_regs;
206 
207 
208 
209 /*###################################################################################################
210 **	GLOBAL VARIABLES
211 **#################################################################################################*/
212 
213 /* public globals */
214 int	tms34010_ICount;
215 
216 /* internal state */
217 static tms34010_regs 	state;
218 static tms34010_regs *	host_interface_context;
219 static UINT8 			host_interface_cpu;
220 static void *			dpyint_timer[MAX_CPU];		  /* Display interrupt timer */
221 static void *			vsblnk_timer[MAX_CPU];		  /* VBLANK start timer */
222 
223 /* default configuration */
224 static struct tms34010_config default_config =
225 {
226 	0,					/* don't halt on reset */
227 	NULL,				/* no interrupt callback */
228 	NULL,				/* no shiftreg functions */
229 	NULL				/* no shiftreg functions */
230 };
231 
232 static void check_interrupt(void);
233 
234 static timer_tm interval=0;
235 
236 /*###################################################################################################
237 **	FUNCTION TABLES
238 **#################################################################################################*/
239 
240 #include "34010fld.c"
241 
242 extern WRITE_HANDLER( wfield_01 );
243 extern WRITE_HANDLER( wfield_02 );
244 extern WRITE_HANDLER( wfield_03 );
245 extern WRITE_HANDLER( wfield_04 );
246 extern WRITE_HANDLER( wfield_05 );
247 extern WRITE_HANDLER( wfield_06 );
248 extern WRITE_HANDLER( wfield_07 );
249 extern WRITE_HANDLER( wfield_08 );
250 extern WRITE_HANDLER( wfield_09 );
251 extern WRITE_HANDLER( wfield_10 );
252 extern WRITE_HANDLER( wfield_11 );
253 extern WRITE_HANDLER( wfield_12 );
254 extern WRITE_HANDLER( wfield_13 );
255 extern WRITE_HANDLER( wfield_14 );
256 extern WRITE_HANDLER( wfield_15 );
257 extern WRITE_HANDLER( wfield_16 );
258 extern WRITE_HANDLER( wfield_17 );
259 extern WRITE_HANDLER( wfield_18 );
260 extern WRITE_HANDLER( wfield_19 );
261 extern WRITE_HANDLER( wfield_20 );
262 extern WRITE_HANDLER( wfield_21 );
263 extern WRITE_HANDLER( wfield_22 );
264 extern WRITE_HANDLER( wfield_23 );
265 extern WRITE_HANDLER( wfield_24 );
266 extern WRITE_HANDLER( wfield_25 );
267 extern WRITE_HANDLER( wfield_26 );
268 extern WRITE_HANDLER( wfield_27 );
269 extern WRITE_HANDLER( wfield_28 );
270 extern WRITE_HANDLER( wfield_29 );
271 extern WRITE_HANDLER( wfield_30 );
272 extern WRITE_HANDLER( wfield_31 );
273 extern WRITE_HANDLER( wfield_32 );
274 
275 static mem_write_handler wfield_functions[32] =
276 {
277 	wfield_32, wfield_01, wfield_02, wfield_03, wfield_04, wfield_05,
278 	wfield_06, wfield_07, wfield_08, wfield_09, wfield_10, wfield_11,
279 	wfield_12, wfield_13, wfield_14, wfield_15, wfield_16, wfield_17,
280 	wfield_18, wfield_19, wfield_20, wfield_21, wfield_22, wfield_23,
281 	wfield_24, wfield_25, wfield_26, wfield_27, wfield_28, wfield_29,
282 	wfield_30, wfield_31
283 };
284 
285 extern READ_HANDLER( rfield_z_01 );
286 extern READ_HANDLER( rfield_z_02 );
287 extern READ_HANDLER( rfield_z_03 );
288 extern READ_HANDLER( rfield_z_04 );
289 extern READ_HANDLER( rfield_z_05 );
290 extern READ_HANDLER( rfield_z_06 );
291 extern READ_HANDLER( rfield_z_07 );
292 extern READ_HANDLER( rfield_z_08 );
293 extern READ_HANDLER( rfield_z_09 );
294 extern READ_HANDLER( rfield_z_10 );
295 extern READ_HANDLER( rfield_z_11 );
296 extern READ_HANDLER( rfield_z_12 );
297 extern READ_HANDLER( rfield_z_13 );
298 extern READ_HANDLER( rfield_z_14 );
299 extern READ_HANDLER( rfield_z_15 );
300 extern READ_HANDLER( rfield_z_16 );
301 extern READ_HANDLER( rfield_z_17 );
302 extern READ_HANDLER( rfield_z_18 );
303 extern READ_HANDLER( rfield_z_19 );
304 extern READ_HANDLER( rfield_z_20 );
305 extern READ_HANDLER( rfield_z_21 );
306 extern READ_HANDLER( rfield_z_22 );
307 extern READ_HANDLER( rfield_z_23 );
308 extern READ_HANDLER( rfield_z_24 );
309 extern READ_HANDLER( rfield_z_25 );
310 extern READ_HANDLER( rfield_z_26 );
311 extern READ_HANDLER( rfield_z_27 );
312 extern READ_HANDLER( rfield_z_28 );
313 extern READ_HANDLER( rfield_z_29 );
314 extern READ_HANDLER( rfield_z_30 );
315 extern READ_HANDLER( rfield_z_31 );
316 extern READ_HANDLER( rfield_32 );
317 
318 static mem_read_handler rfield_functions_z[32] =
319 {
320 	rfield_32  , rfield_z_01, rfield_z_02, rfield_z_03, rfield_z_04, rfield_z_05,
321 	rfield_z_06, rfield_z_07, rfield_z_08, rfield_z_09, rfield_z_10, rfield_z_11,
322 	rfield_z_12, rfield_z_13, rfield_z_14, rfield_z_15, rfield_z_16, rfield_z_17,
323 	rfield_z_18, rfield_z_19, rfield_z_20, rfield_z_21, rfield_z_22, rfield_z_23,
324 	rfield_z_24, rfield_z_25, rfield_z_26, rfield_z_27, rfield_z_28, rfield_z_29,
325 	rfield_z_30, rfield_z_31
326 };
327 
328 extern READ_HANDLER( rfield_s_01 );
329 extern READ_HANDLER( rfield_s_02 );
330 extern READ_HANDLER( rfield_s_03 );
331 extern READ_HANDLER( rfield_s_04 );
332 extern READ_HANDLER( rfield_s_05 );
333 extern READ_HANDLER( rfield_s_06 );
334 extern READ_HANDLER( rfield_s_07 );
335 extern READ_HANDLER( rfield_s_08 );
336 extern READ_HANDLER( rfield_s_09 );
337 extern READ_HANDLER( rfield_s_10 );
338 extern READ_HANDLER( rfield_s_11 );
339 extern READ_HANDLER( rfield_s_12 );
340 extern READ_HANDLER( rfield_s_13 );
341 extern READ_HANDLER( rfield_s_14 );
342 extern READ_HANDLER( rfield_s_15 );
343 extern READ_HANDLER( rfield_s_16 );
344 extern READ_HANDLER( rfield_s_17 );
345 extern READ_HANDLER( rfield_s_18 );
346 extern READ_HANDLER( rfield_s_19 );
347 extern READ_HANDLER( rfield_s_20 );
348 extern READ_HANDLER( rfield_s_21 );
349 extern READ_HANDLER( rfield_s_22 );
350 extern READ_HANDLER( rfield_s_23 );
351 extern READ_HANDLER( rfield_s_24 );
352 extern READ_HANDLER( rfield_s_25 );
353 extern READ_HANDLER( rfield_s_26 );
354 extern READ_HANDLER( rfield_s_27 );
355 extern READ_HANDLER( rfield_s_28 );
356 extern READ_HANDLER( rfield_s_29 );
357 extern READ_HANDLER( rfield_s_30 );
358 extern READ_HANDLER( rfield_s_31 );
359 
360 static mem_read_handler rfield_functions_s[32] =
361 {
362 	rfield_32  , rfield_s_01, rfield_s_02, rfield_s_03, rfield_s_04, rfield_s_05,
363 	rfield_s_06, rfield_s_07, rfield_s_08, rfield_s_09, rfield_s_10, rfield_s_11,
364 	rfield_s_12, rfield_s_13, rfield_s_14, rfield_s_15, rfield_s_16, rfield_s_17,
365 	rfield_s_18, rfield_s_19, rfield_s_20, rfield_s_21, rfield_s_22, rfield_s_23,
366 	rfield_s_24, rfield_s_25, rfield_s_26, rfield_s_27, rfield_s_28, rfield_s_29,
367 	rfield_s_30, rfield_s_31
368 };
369 
370 
371 
372 /*###################################################################################################
373 **	MACROS
374 **#################################################################################################*/
375 
376 /* context finder */
377 #define FINDCONTEXT(_cpu) (cpu_is_saving_context(_cpu) ? cpu_getcontext(_cpu) : &state)
378 
379 /* register definitions and shortcuts */
380 #define PC				(state.pc)
381 #define ST				(state.st)
382 #define N_FLAG			(state.nflag)
383 #define NOTZ_FLAG		(state.notzflag)
384 #define C_FLAG			(state.cflag)
385 #define V_FLAG			(state.vflag)
386 #define P_FLAG			(state.pflag)
387 #define IE_FLAG			(state.ieflag)
388 #define FE0_FLAG		(state.fe0flag)
389 #define FE1_FLAG		(state.fe1flag)
390 
391 /* register file access */
392 #define AREG(i)			(state.regs.a.a.Aregs[i])
393 #define AREG_XY(i)		(state.regs.a.a.AregsXY[i])
394 #define AREG_X(i)		(state.regs.a.a.AregsXY[i].x)
395 #define AREG_Y(i)		(state.regs.a.a.AregsXY[i].y)
396 #define BREG(i)			(state.regs.Bregs[i])
397 #define BREG_XY(i)		(state.regs.BregsXY[i])
398 #define BREG_X(i)		(state.regs.BregsXY[i].x)
399 #define BREG_Y(i)		(state.regs.BregsXY[i].y)
400 #define SP				AREG(15)
401 #define FW(i)			(state.fw[i])
402 #define FW_INC(i)		(state.fw_inc[i])
403 #define BINDEX(i)		((i) << 4)
404 
405 /* opcode decode helpers */
406 #define ASRCREG			((state.op >> 5) & 0x0f)
407 #define ADSTREG			(state.op & 0x0f)
408 #define BSRCREG			((state.op & 0x1e0) >> 1)
409 #define BDSTREG			((state.op & 0x0f) << 4)
410 #define SKIP_WORD		(PC += (2 << 3))
411 #define SKIP_LONG		(PC += (4 << 3))
412 #define PARAM_K			((state.op >> 5) & 0x1f)
413 #define PARAM_N			(state.op & 0x1f)
414 #define PARAM_REL8		((INT8)state.op)
415 
416 /* memory I/O */
417 #define WFIELD0(a,b)	state.f0_write(a,b)
418 #define WFIELD1(a,b)	state.f1_write(a,b)
419 #define RFIELD0(a)		state.f0_read(a)
420 #define RFIELD1(a)		state.f1_read(a)
421 #define WPIXEL(a,b)		state.pixel_write(a,b)
422 #define RPIXEL(a)		state.pixel_read(a)
423 
424 /* Implied Operands */
425 #define SADDR			BREG(BINDEX(0))
426 #define SADDR_X			BREG_X(BINDEX(0))
427 #define SADDR_Y			BREG_Y(BINDEX(0))
428 #define SADDR_XY		BREG_XY(BINDEX(0))
429 #define SPTCH			BREG(BINDEX(1))
430 #define DADDR			BREG(BINDEX(2))
431 #define DADDR_X			BREG_X(BINDEX(2))
432 #define DADDR_Y			BREG_Y(BINDEX(2))
433 #define DADDR_XY		BREG_XY(BINDEX(2))
434 #define DPTCH			BREG(BINDEX(3))
435 #define OFFSET			BREG(BINDEX(4))
436 #define WSTART_X		BREG_X(BINDEX(5))
437 #define WSTART_Y		BREG_Y(BINDEX(5))
438 #define WEND_X			BREG_X(BINDEX(6))
439 #define WEND_Y			BREG_Y(BINDEX(6))
440 #define DYDX_X			BREG_X(BINDEX(7))
441 #define DYDX_Y			BREG_Y(BINDEX(7))
442 #define COLOR0			BREG(BINDEX(8))
443 #define COLOR1			BREG(BINDEX(9))
444 #define COUNT			BREG(BINDEX(10))
445 #define INC1_X			BREG_X(BINDEX(11))
446 #define INC1_Y			BREG_Y(BINDEX(11))
447 #define INC2_X			BREG_X(BINDEX(12))
448 #define INC2_Y			BREG_Y(BINDEX(12))
449 #define PATTRN			BREG(BINDEX(13))
450 #define TEMP			BREG(BINDEX(14))
451 
452 
453 
454 /*###################################################################################################
455 **	static INLINE SHORTCUTS
456 **#################################################################################################*/
457 
458 /* set the field widths - shortcut */
SET_FW(void)459 static INLINE void SET_FW(void)
460 {
461 	FW_INC(0) = FW(0) ? FW(0) : 0x20;
462 	FW_INC(1) = FW(1) ? FW(1) : 0x20;
463 
464 	state.f0_write = wfield_functions[FW(0)];
465 	state.f1_write = wfield_functions[FW(1)];
466 
467 	if (FE0_FLAG)
468 		state.f0_read  = rfield_functions_s[FW(0)];	/* Sign extend */
469 	else
470 		state.f0_read  = rfield_functions_z[FW(0)];	/* Zero extend */
471 
472 	if (FE1_FLAG)
473 		state.f1_read  = rfield_functions_s[FW(1)];	/* Sign extend */
474 	else
475 		state.f1_read  = rfield_functions_z[FW(1)];	/* Zero extend */
476 }
477 
478 /* Intialize Status to 0x0010 */
RESET_ST(void)479 static INLINE void RESET_ST(void)
480 {
481 	N_FLAG = C_FLAG = V_FLAG = P_FLAG = IE_FLAG = FE0_FLAG = FE1_FLAG = 0;
482 	NOTZ_FLAG = 1;
483 	FW(0) = 0x10;
484 	FW(1) = 0;
485 	SET_FW();
486 }
487 
488 /* Combine indiviual flags into the Status Register */
GET_ST(void)489 static INLINE UINT32 GET_ST(void)
490 {
491     UINT32 ret=0;
492 
493     if (N_FLAG) ret|=0x80000000;
494     if (C_FLAG) ret|=0x40000000;
495     if (!NOTZ_FLAG) ret|=0x20000000;
496     if (V_FLAG) ret|=0x10000000;
497     if (P_FLAG) ret|=0x02000000;
498     if (IE_FLAG) ret|=0x00200000;
499     if (FE1_FLAG) ret|=0x00000800;
500     ret|=(FW(1) << 6);
501     if (FE0_FLAG) ret|=0x00000020;
502     ret|=FW(0);
503     return ret;
504 
505     /*
506 	return (     N_FLAG ? 0x80000000 : 0) |
507 		   (     C_FLAG ? 0x40000000 : 0) |
508 		   (  NOTZ_FLAG ? 0 : 0x20000000) |
509 		   (     V_FLAG ? 0x10000000 : 0) |
510 		   (     P_FLAG ? 0x02000000 : 0) |
511 		   (    IE_FLAG ? 0x00200000 : 0) |
512 		   (   FE1_FLAG ? 0x00000800 : 0) |
513 		   (FW(1) << 6)                   |
514 		   (   FE0_FLAG ? 0x00000020 : 0) |
515 		   FW(0);
516 	*/
517 }
518 
519 /* Break up Status Register into indiviual flags */
SET_ST(UINT32 st)520 static INLINE void SET_ST(UINT32 st)
521 {
522 	N_FLAG    =    st & 0x80000000;
523 	C_FLAG    =    st & 0x40000000;
524 	NOTZ_FLAG =  !(st & 0x20000000);
525 	V_FLAG    =    st & 0x10000000;
526 	P_FLAG    =    st & 0x02000000;
527 	IE_FLAG   =    st & 0x00200000;
528 	FE1_FLAG  =    st & 0x00000800;
529 	FW(1)     =   (st >> 6) & 0x1f;
530 	FE0_FLAG  =    st & 0x00000020;
531 	FW(0)     =    st & 0x1f;
532 	SET_FW();
533 
534 	/* interrupts might have been enabled, check it */
535 	check_interrupt();
536 }
537 
538 /* shortcuts for reading opcodes */
ROPCODE(void)539 static INLINE UINT32 ROPCODE(void)
540 {
541 	UINT32 pc = TOBYTE(PC);
542 	PC += 2 << 3;
543 	return cpu_readop16(pc);
544 }
545 
PARAM_WORD(void)546 static INLINE INT16 PARAM_WORD(void)
547 {
548 	UINT32 pc = TOBYTE(PC);
549 	PC += 2 << 3;
550 	return cpu_readop_arg16(pc);
551 }
552 
PARAM_LONG(void)553 static INLINE INT32 PARAM_LONG(void)
554 {
555 	UINT32 pc = TOBYTE(PC);
556 	PC += 4 << 3;
557 	return (UINT16)cpu_readop_arg16(pc) | (cpu_readop_arg16(pc + 2) << 16);
558 }
559 
PARAM_WORD_NO_INC(void)560 static INLINE INT16 PARAM_WORD_NO_INC(void)
561 {
562 	return cpu_readop_arg16(TOBYTE(PC));
563 }
564 
PARAM_LONG_NO_INC(void)565 static INLINE INT32 PARAM_LONG_NO_INC(void)
566 {
567 	UINT32 pc = TOBYTE(PC);
568 	return (UINT16)cpu_readop_arg16(pc) | (cpu_readop_arg16(pc + 2) << 16);
569 }
570 
571 /* read memory byte */
READ_HANDLER(RBYTE)572 static INLINE READ_HANDLER( RBYTE )
573 {
574 	UINT32 ret;
575 	RFIELDMAC_8;
576 	return ret;
577 }
578 
579 /* write memory byte */
WRITE_HANDLER(WBYTE)580 static INLINE WRITE_HANDLER( WBYTE )
581 {
582 	WFIELDMAC_8;
583 }
584 
585 /* read memory long */
READ_HANDLER(RLONG)586 static INLINE READ_HANDLER( RLONG )
587 {
588 	RFIELDMAC_32;
589 }
590 
591 /* write memory long */
WRITE_HANDLER(WLONG)592 static INLINE WRITE_HANDLER( WLONG )
593 {
594 	WFIELDMAC_32;
595 }
596 
597 /* pushes/pops a value from the stack */
PUSH(UINT32 data)598 static INLINE void PUSH(UINT32 data)
599 {
600 	SP -= 0x20;
601 	TMS34010_WRMEM_DWORD(TOBYTE(SP), data);
602 }
603 
POP(void)604 static INLINE INT32 POP(void)
605 {
606 	INT32 ret = TMS34010_RDMEM_DWORD(TOBYTE(SP));
607 	SP += 0x20;
608 	return ret;
609 }
610 
611 
612 
613 /*###################################################################################################
614 **	PIXEL READS
615 **#################################################################################################*/
616 
617 #define RP(m1,m2)  											\
618 	/* TODO: Plane masking */								\
619 	return (TMS34010_RDMEM_WORD(TOBYTE(offset & 0xfffffff0)) >> (offset & m1)) & m2;
620 
READ_HANDLER(read_pixel_1)621 static READ_HANDLER( read_pixel_1 ) { RP(0x0f,0x01) }
READ_HANDLER(read_pixel_2)622 static READ_HANDLER( read_pixel_2 ) { RP(0x0e,0x03) }
READ_HANDLER(read_pixel_4)623 static READ_HANDLER( read_pixel_4 ) { RP(0x0c,0x0f) }
READ_HANDLER(read_pixel_8)624 static READ_HANDLER( read_pixel_8 ) { RP(0x08,0xff) }
READ_HANDLER(read_pixel_16)625 static READ_HANDLER( read_pixel_16 )
626 {
627 	/* TODO: Plane masking */
628 	return TMS34010_RDMEM_WORD(TOBYTE(offset & 0xfffffff0));
629 }
630 
631 /* Shift register read */
READ_HANDLER(read_pixel_shiftreg)632 static READ_HANDLER( read_pixel_shiftreg )
633 {
634 	if (state.config->to_shiftreg)
635 		state.config->to_shiftreg(offset, &state.shiftreg[0]);
636 	/*else
637 		logerror("To ShiftReg function not set. PC = %08X\n", PC);*/
638 	return state.shiftreg[0];
639 }
640 
641 
642 
643 /*###################################################################################################
644 **	PIXEL WRITES
645 **#################################################################################################*/
646 
647 /* No Raster Op + No Transparency */
648 #define WP(m1,m2)  																			\
649 	UINT32 a = TOBYTE(offset & 0xfffffff0);													\
650 	UINT32 pix = TMS34010_RDMEM_WORD(a);													\
651 	UINT32 shiftcount = offset & m1;														\
652 																							\
653 	/* TODO: plane masking */																\
654 	data &= m2;																				\
655 	pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount);								\
656 	TMS34010_WRMEM_WORD(a, pix);															\
657 
658 /* No Raster Op + Transparency */
659 #define WP_T(m1,m2)  																		\
660 	/* TODO: plane masking */																\
661 	data &= m2;																				\
662 	if (data)																				\
663 	{																						\
664 		UINT32 a = TOBYTE(offset & 0xfffffff0);												\
665 		UINT32 pix = TMS34010_RDMEM_WORD(a);												\
666 		UINT32 shiftcount = offset & m1;													\
667 																							\
668 		/* TODO: plane masking */															\
669 		pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount);							\
670 		TMS34010_WRMEM_WORD(a, pix);														\
671 	}						  																\
672 
673 /* Raster Op + No Transparency */
674 #define WP_R(m1,m2)  																		\
675 	UINT32 a = TOBYTE(offset & 0xfffffff0);													\
676 	UINT32 pix = TMS34010_RDMEM_WORD(a);													\
677 	UINT32 shiftcount = offset & m1;														\
678 																							\
679 	/* TODO: plane masking */																\
680 	data = state.raster_op(data & m2, (pix >> shiftcount) & m2) & m2;						\
681 	pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount);								\
682 	TMS34010_WRMEM_WORD(a, pix);															\
683 
684 /* Raster Op + Transparency */
685 #define WP_R_T(m1,m2)  																		\
686 	UINT32 a = TOBYTE(offset & 0xfffffff0);													\
687 	UINT32 pix = TMS34010_RDMEM_WORD(a);													\
688 	UINT32 shiftcount = offset & m1;														\
689 																							\
690 	/* TODO: plane masking */																\
691 	data = state.raster_op(data & m2, (pix >> shiftcount) & m2) & m2;						\
692 	if (data)																				\
693 	{																						\
694 		pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount);							\
695 		TMS34010_WRMEM_WORD(a, pix);														\
696 	}						  																\
697 
698 
699 /* No Raster Op + No Transparency */
WRITE_HANDLER(write_pixel_1)700 static WRITE_HANDLER( write_pixel_1 ) { WP(0x0f, 0x01); }
WRITE_HANDLER(write_pixel_2)701 static WRITE_HANDLER( write_pixel_2 ) { WP(0x0e, 0x03); }
WRITE_HANDLER(write_pixel_4)702 static WRITE_HANDLER( write_pixel_4 ) { WP(0x0c, 0x0f); }
WRITE_HANDLER(write_pixel_8)703 static WRITE_HANDLER( write_pixel_8 ) { WP(0x08, 0xff); }
WRITE_HANDLER(write_pixel_16)704 static WRITE_HANDLER( write_pixel_16 )
705 {
706 	/* TODO: plane masking */
707 	TMS34010_WRMEM_WORD(TOBYTE(offset & 0xfffffff0), data);
708 }
709 
710 /* No Raster Op + Transparency */
WRITE_HANDLER(write_pixel_t_1)711 static WRITE_HANDLER( write_pixel_t_1 ) { WP_T(0x0f, 0x01); }
WRITE_HANDLER(write_pixel_t_2)712 static WRITE_HANDLER( write_pixel_t_2 ) { WP_T(0x0e, 0x03); }
WRITE_HANDLER(write_pixel_t_4)713 static WRITE_HANDLER( write_pixel_t_4 ) { WP_T(0x0c, 0x0f); }
WRITE_HANDLER(write_pixel_t_8)714 static WRITE_HANDLER( write_pixel_t_8 ) { WP_T(0x08, 0xff); }
WRITE_HANDLER(write_pixel_t_16)715 static WRITE_HANDLER( write_pixel_t_16 )
716 {
717 	/* TODO: plane masking */
718 	if (data)
719 		TMS34010_WRMEM_WORD(TOBYTE(offset & 0xfffffff0), data);
720 }
721 
722 /* Raster Op + No Transparency */
WRITE_HANDLER(write_pixel_r_1)723 static WRITE_HANDLER( write_pixel_r_1 ) { WP_R(0x0f, 0x01); }
WRITE_HANDLER(write_pixel_r_2)724 static WRITE_HANDLER( write_pixel_r_2 ) { WP_R(0x0e, 0x03); }
WRITE_HANDLER(write_pixel_r_4)725 static WRITE_HANDLER( write_pixel_r_4 ) { WP_R(0x0c, 0x0f); }
WRITE_HANDLER(write_pixel_r_8)726 static WRITE_HANDLER( write_pixel_r_8 ) { WP_R(0x08, 0xff); }
WRITE_HANDLER(write_pixel_r_16)727 static WRITE_HANDLER( write_pixel_r_16 )
728 {
729 	/* TODO: plane masking */
730 	UINT32 a = TOBYTE(offset & 0xfffffff0);
731 	TMS34010_WRMEM_WORD(a, state.raster_op(data, TMS34010_RDMEM_WORD(a)));
732 }
733 
734 /* Raster Op + Transparency */
WRITE_HANDLER(write_pixel_r_t_1)735 static WRITE_HANDLER( write_pixel_r_t_1 ) { WP_R_T(0x0f,0x01); }
WRITE_HANDLER(write_pixel_r_t_2)736 static WRITE_HANDLER( write_pixel_r_t_2 ) { WP_R_T(0x0e,0x03); }
WRITE_HANDLER(write_pixel_r_t_4)737 static WRITE_HANDLER( write_pixel_r_t_4 ) { WP_R_T(0x0c,0x0f); }
WRITE_HANDLER(write_pixel_r_t_8)738 static WRITE_HANDLER( write_pixel_r_t_8 ) { WP_R_T(0x08,0xff); }
WRITE_HANDLER(write_pixel_r_t_16)739 static WRITE_HANDLER( write_pixel_r_t_16 )
740 {
741 	/* TODO: plane masking */
742 	UINT32 a = TOBYTE(offset & 0xfffffff0);
743 	data = state.raster_op(data, TMS34010_RDMEM_WORD(a));
744 
745 	if (data)
746 		TMS34010_WRMEM_WORD(a, data);
747 }
748 
749 /* Shift register write */
WRITE_HANDLER(write_pixel_shiftreg)750 static WRITE_HANDLER( write_pixel_shiftreg )
751 {
752 	if (state.config->from_shiftreg)
753 		state.config->from_shiftreg(offset, &state.shiftreg[0]);
754 	/*else
755 		logerror("From ShiftReg function not set. PC = %08X\n", PC);*/
756 }
757 
758 
759 
760 /*###################################################################################################
761 **	RASTER OPS
762 **#################################################################################################*/
763 
764 /* Raster operations */
raster_op_1(INT32 newpix,INT32 oldpix)765 static INT32 raster_op_1(INT32 newpix, INT32 oldpix)  { return newpix & oldpix; }
raster_op_2(INT32 newpix,INT32 oldpix)766 static INT32 raster_op_2(INT32 newpix, INT32 oldpix)  { return newpix & ~oldpix; }
raster_op_3(INT32 newpix,INT32 oldpix)767 static INT32 raster_op_3(INT32 newpix, INT32 oldpix)  { return 0; }
raster_op_4(INT32 newpix,INT32 oldpix)768 static INT32 raster_op_4(INT32 newpix, INT32 oldpix)  { return newpix | ~oldpix; }
raster_op_5(INT32 newpix,INT32 oldpix)769 static INT32 raster_op_5(INT32 newpix, INT32 oldpix)  { return ~(newpix ^ oldpix); }
raster_op_6(INT32 newpix,INT32 oldpix)770 static INT32 raster_op_6(INT32 newpix, INT32 oldpix)  { return ~oldpix; }
raster_op_7(INT32 newpix,INT32 oldpix)771 static INT32 raster_op_7(INT32 newpix, INT32 oldpix)  { return ~(newpix | oldpix); }
raster_op_8(INT32 newpix,INT32 oldpix)772 static INT32 raster_op_8(INT32 newpix, INT32 oldpix)  { return newpix | oldpix; }
raster_op_9(INT32 newpix,INT32 oldpix)773 static INT32 raster_op_9(INT32 newpix, INT32 oldpix)  { return oldpix; }
raster_op_10(INT32 newpix,INT32 oldpix)774 static INT32 raster_op_10(INT32 newpix, INT32 oldpix) { return newpix ^ oldpix; }
raster_op_11(INT32 newpix,INT32 oldpix)775 static INT32 raster_op_11(INT32 newpix, INT32 oldpix) { return ~newpix & oldpix; }
raster_op_12(INT32 newpix,INT32 oldpix)776 static INT32 raster_op_12(INT32 newpix, INT32 oldpix) { return 0xffff; }
raster_op_13(INT32 newpix,INT32 oldpix)777 static INT32 raster_op_13(INT32 newpix, INT32 oldpix) { return ~newpix | oldpix; }
raster_op_14(INT32 newpix,INT32 oldpix)778 static INT32 raster_op_14(INT32 newpix, INT32 oldpix) { return ~(newpix & oldpix); }
raster_op_15(INT32 newpix,INT32 oldpix)779 static INT32 raster_op_15(INT32 newpix, INT32 oldpix) { return ~newpix; }
raster_op_16(INT32 newpix,INT32 oldpix)780 static INT32 raster_op_16(INT32 newpix, INT32 oldpix) { return newpix + oldpix; }
raster_op_17(INT32 newpix,INT32 oldpix)781 static INT32 raster_op_17(INT32 newpix, INT32 oldpix)
782 {
783 	INT32 max = (UINT32)0xffffffff >> (32 - IOREG(REG_PSIZE));
784 	INT32 res = newpix + oldpix;
785 	return (res > max) ? max : res;
786 }
raster_op_18(INT32 newpix,INT32 oldpix)787 static INT32 raster_op_18(INT32 newpix, INT32 oldpix) { return oldpix - newpix; }
raster_op_19(INT32 newpix,INT32 oldpix)788 static INT32 raster_op_19(INT32 newpix, INT32 oldpix) { return (oldpix > newpix) ? oldpix - newpix : 0; }
raster_op_20(INT32 newpix,INT32 oldpix)789 static INT32 raster_op_20(INT32 newpix, INT32 oldpix) { return (oldpix > newpix) ? oldpix : newpix; }
raster_op_21(INT32 newpix,INT32 oldpix)790 static INT32 raster_op_21(INT32 newpix, INT32 oldpix) { return (oldpix > newpix) ? newpix : oldpix; }
791 
792 
793 
794 /*###################################################################################################
795 **	OPCODE TABLE & IMPLEMENTATIONS
796 **#################################################################################################*/
797 
798 /* includes the static function prototypes and the master opcode table */
799 #include "34010tbl.c"
800 
801 /* includes the actual opcode implementations */
802 #include "34010ops.c"
803 #include "34010gfx.c"
804 
805 
806 
807 /*###################################################################################################
808 **	Internal interrupt check
809 *#################################################################################################*/
810 
811 /* Generate pending interrupts. Do NOT inline this function on DJGPP,
812    it causes a slowdown */
check_interrupt(void)813 static void check_interrupt(void)
814 {
815 	int vector = 0;
816 	int irqline = -1;
817 	int irq;
818 
819 	/* early out if no interrupts pending */
820 	irq = IOREG(REG_INTPEND);
821 	if (!irq)
822 		return;
823 
824 	/* check for NMI first */
825 	if (irq & TMS34010_NMI)
826 	{
827 		LOG(("TMS34010#%d takes NMI\n", cpu_getactivecpu()));
828 
829 		/* ack the NMI */
830 		IOREG(REG_INTPEND) &= ~TMS34010_NMI;
831 
832 		/* handle NMI mode bit */
833 		if (!(IOREG(REG_HSTCTLH) & 0x0200))
834 		{
835 			PUSH(PC);
836 			PUSH(GET_ST());
837 		}
838 
839 		/* leap to the vector */
840 		RESET_ST();
841 		PC = RLONG(0xfffffee0);
842 		change_pc29(PC);
843 		return;
844 	}
845 
846 	/* early out if everything else is disabled */
847 	irq &= IOREG(REG_INTENB);
848 	if (!IE_FLAG || !irq)
849 		return;
850 
851 	/* host interrupt */
852 	if (irq & TMS34010_HI)
853 	{
854 		LOG(("TMS34010#%d takes HI\n", cpu_getactivecpu()));
855 		vector = 0xfffffec0;
856 	}
857 
858 	/* display interrupt */
859 	else if (irq & TMS34010_DI)
860 	{
861 		LOG(("TMS34010#%d takes DI\n", cpu_getactivecpu()));
862 		vector = 0xfffffea0;
863 	}
864 
865 	/* window violation interrupt */
866 	else if (irq & TMS34010_WV)
867 	{
868 		LOG(("TMS34010#%d takes WV\n", cpu_getactivecpu()));
869 		vector = 0xfffffe80;
870 	}
871 
872 	/* external 1 interrupt */
873 	else if (irq & TMS34010_INT1)
874 	{
875 		LOG(("TMS34010#%d takes INT1\n", cpu_getactivecpu()));
876 		vector = 0xffffffc0;
877 		irqline = 0;
878 	}
879 
880 	/* external 2 interrupt */
881 	else if (irq & TMS34010_INT2)
882 	{
883 		LOG(("TMS34010#%d takes INT2\n", cpu_getactivecpu()));
884 		vector = 0xffffffa0;
885 		irqline = 1;
886 	}
887 
888 	/* if we took something, generate it */
889 	if (vector)
890 	{
891 		PUSH(PC);
892 		PUSH(GET_ST());
893 		RESET_ST();
894 		PC = RLONG(vector);
895 		change_pc29(PC);
896 
897 		/* call the callback for externals */
898 		if (irqline >= 0)
899 			(void)(*state.irq_callback)(irqline);
900 	}
901 }
902 
903 
904 
905 /*###################################################################################################
906 **	Reset the CPU emulation
907 **#################################################################################################*/
908 
tms34010_reset(void * param)909 void tms34010_reset(void *param)
910 {
911 	struct tms34010_config *config = param ? (struct tms34010_config *)param : (struct tms34010_config *)&default_config;
912 
913 	/* zap the state and copy in the config pointer */
914 	memset(&state, 0, sizeof(state));
915 	state.is_34020 = 0;
916 	state.config = config;
917 
918 	/* allocate the shiftreg */
919 	state.shiftreg = (UINT16*)malloc(SHIFTREG_SIZE);
920 
921 	/* fetch the initial PC and reset the state */
922 	PC = RLONG(0xffffffe0);
923 	change_pc29(PC)
924 	RESET_ST();
925 
926 	/* HALT the CPU if requested, and remember to re-read the starting PC */
927 	/* the first time we are run */
928 	state.reset_deferred = config->halt_on_reset;
929 	if (config->halt_on_reset)
930 		tms34010_io_register_w(REG_HSTCTLH * 2, 0x8000);
931 
932 	/* reset the timers and the host interface (but only the first time) */
933 	host_interface_context = NULL;
934 
935     interval = TIME_IN_HZ(Machine->drv->frames_per_second);
936 }
937 
tms34020_reset(void * param)938 void tms34020_reset(void *param)
939 {
940 	tms34010_reset(param);
941 	state.is_34020 = 1;
942 }
943 
944 
945 
946 /*###################################################################################################
947 **	Shut down the CPU emulation
948 **#################################################################################################*/
949 
tms34010_exit(void)950 void tms34010_exit(void)
951 {
952 	int i;
953 
954 	/* clear out the timers */
955 	for (i = 0; i < MAX_CPU; i++)
956 		dpyint_timer[i] = vsblnk_timer[i] = NULL;
957 
958 	/* free memory */
959 	if (state.shiftreg)
960 		free(state.shiftreg);
961 	state.shiftreg = NULL;
962 }
963 
tms34020_exit(void)964 void tms34020_exit(void)
965 {
966 	tms34010_exit();
967 }
968 
969 
970 
971 /*###################################################################################################
972 **	Get all registers in given buffer
973 **#################################################################################################*/
974 
tms34010_get_context(void * dst)975 unsigned tms34010_get_context(void *dst)
976 {
977 	if (dst)
978 		*(tms34010_regs *)dst = state;
979 	return sizeof(tms34010_regs);
980 }
981 
tms34020_get_context(void * dst)982 unsigned tms34020_get_context(void *dst)
983 {
984 	return tms34010_get_context(dst);
985 }
986 
987 
988 
989 /*###################################################################################################
990 **	Set all registers to given values
991 **#################################################################################################*/
992 
tms34010_set_context(void * src)993 void tms34010_set_context(void *src)
994 {
995 	if (src)
996 		state = *(tms34010_regs *)src;
997 	change_pc29(PC)
998 	check_interrupt();
999 }
1000 
tms34020_set_context(void * src)1001 void tms34020_set_context(void *src)
1002 {
1003 	tms34010_set_context(src);
1004 }
1005 
1006 
1007 
1008 /*###################################################################################################
1009 **	Return program counter
1010 **#################################################################################################*/
1011 
tms34010_get_pc(void)1012 unsigned tms34010_get_pc(void)
1013 {
1014 	return PC;
1015 }
1016 
tms34020_get_pc(void)1017 unsigned tms34020_get_pc(void)
1018 {
1019 	return tms34010_get_pc();
1020 }
1021 
1022 
1023 
1024 /*###################################################################################################
1025 **	Set program counter
1026 **#################################################################################################*/
1027 
tms34010_set_pc(unsigned val)1028 void tms34010_set_pc(unsigned val)
1029 {
1030 	PC = val;
1031 	change_pc29(PC)
1032 }
1033 
tms34020_set_pc(unsigned val)1034 void tms34020_set_pc(unsigned val)
1035 {
1036 	tms34010_set_pc(val);
1037 }
1038 
1039 
1040 
1041 /*###################################################################################################
1042 **	Return stack pointer
1043 **#################################################################################################*/
1044 
tms34010_get_sp(void)1045 unsigned tms34010_get_sp(void)
1046 {
1047 	return SP;
1048 }
1049 
tms34020_get_sp(void)1050 unsigned tms34020_get_sp(void)
1051 {
1052 	return tms34010_get_sp();
1053 }
1054 
1055 
1056 
1057 /*###################################################################################################
1058 **	Set stack pointer
1059 **#################################################################################################*/
1060 
tms34010_set_sp(unsigned val)1061 void tms34010_set_sp(unsigned val)
1062 {
1063 	SP = val;
1064 }
1065 
tms34020_set_sp(unsigned val)1066 void tms34020_set_sp(unsigned val)
1067 {
1068 	tms34010_set_sp(val);
1069 }
1070 
1071 
1072 
1073 /*###################################################################################################
1074 **	Return a specific register
1075 **#################################################################################################*/
1076 
tms34010_get_reg(int regnum)1077 unsigned tms34010_get_reg(int regnum)
1078 {
1079 	switch (regnum)
1080 	{
1081 		case TMS34010_PC:  return PC;
1082 		case TMS34010_SP:  return SP;
1083 		case TMS34010_ST:  return ST;
1084 		case TMS34010_A0:  return AREG(0);
1085 		case TMS34010_A1:  return AREG(1);
1086 		case TMS34010_A2:  return AREG(2);
1087 		case TMS34010_A3:  return AREG(3);
1088 		case TMS34010_A4:  return AREG(4);
1089 		case TMS34010_A5:  return AREG(5);
1090 		case TMS34010_A6:  return AREG(6);
1091 		case TMS34010_A7:  return AREG(7);
1092 		case TMS34010_A8:  return AREG(8);
1093 		case TMS34010_A9:  return AREG(9);
1094 		case TMS34010_A10: return AREG(10);
1095 		case TMS34010_A11: return AREG(11);
1096 		case TMS34010_A12: return AREG(12);
1097 		case TMS34010_A13: return AREG(13);
1098 		case TMS34010_A14: return AREG(14);
1099 		case TMS34010_B0:  return BREG(BINDEX(0));
1100 		case TMS34010_B1:  return BREG(BINDEX(1));
1101 		case TMS34010_B2:  return BREG(BINDEX(2));
1102 		case TMS34010_B3:  return BREG(BINDEX(3));
1103 		case TMS34010_B4:  return BREG(BINDEX(4));
1104 		case TMS34010_B5:  return BREG(BINDEX(5));
1105 		case TMS34010_B6:  return BREG(BINDEX(6));
1106 		case TMS34010_B7:  return BREG(BINDEX(7));
1107 		case TMS34010_B8:  return BREG(BINDEX(8));
1108 		case TMS34010_B9:  return BREG(BINDEX(9));
1109 		case TMS34010_B10: return BREG(BINDEX(10));
1110 		case TMS34010_B11: return BREG(BINDEX(11));
1111 		case TMS34010_B12: return BREG(BINDEX(12));
1112 		case TMS34010_B13: return BREG(BINDEX(13));
1113 		case TMS34010_B14: return BREG(BINDEX(14));
1114 /* TODO: return contents of [SP + wordsize * (CPU_SP_CONTENTS-regnum)] */
1115 		default:
1116 			if (regnum <= REG_SP_CONTENTS)
1117 			{
1118 				unsigned offset = SP + 4 * (REG_SP_CONTENTS - regnum);
1119 				return cpu_readmem29_dword(TOBYTE(offset));
1120 			}
1121 	}
1122 	return 0;
1123 }
1124 
tms34020_get_reg(int regnum)1125 unsigned tms34020_get_reg(int regnum)
1126 {
1127 	return tms34010_get_reg(regnum);
1128 }
1129 
1130 
1131 
1132 /*###################################################################################################
1133 **	Set a specific register
1134 **#################################################################################################*/
1135 
tms34010_set_reg(int regnum,unsigned val)1136 void tms34010_set_reg(int regnum, unsigned val)
1137 {
1138 	switch (regnum)
1139 	{
1140 		case TMS34010_PC:  PC = val; break;
1141 		case TMS34010_SP:  SP = val; break;
1142 		case TMS34010_ST:  ST = val; break;
1143 		case TMS34010_A0:  AREG(0) = val; break;
1144 		case TMS34010_A1:  AREG(1) = val; break;
1145 		case TMS34010_A2:  AREG(2) = val; break;
1146 		case TMS34010_A3:  AREG(3) = val; break;
1147 		case TMS34010_A4:  AREG(4) = val; break;
1148 		case TMS34010_A5:  AREG(5) = val; break;
1149 		case TMS34010_A6:  AREG(6) = val; break;
1150 		case TMS34010_A7:  AREG(7) = val; break;
1151 		case TMS34010_A8:  AREG(8) = val; break;
1152 		case TMS34010_A9:  AREG(9) = val; break;
1153 		case TMS34010_A10: AREG(10) = val; break;
1154 		case TMS34010_A11: AREG(11) = val; break;
1155 		case TMS34010_A12: AREG(12) = val; break;
1156 		case TMS34010_A13: AREG(13) = val; break;
1157 		case TMS34010_A14: AREG(14) = val; break;
1158 		case TMS34010_B0:  BREG(BINDEX(0)) = val; break;
1159 		case TMS34010_B1:  BREG(BINDEX(1)) = val; break;
1160 		case TMS34010_B2:  BREG(BINDEX(2)) = val; break;
1161 		case TMS34010_B3:  BREG(BINDEX(3)) = val; break;
1162 		case TMS34010_B4:  BREG(BINDEX(4)) = val; break;
1163 		case TMS34010_B5:  BREG(BINDEX(5)) = val; break;
1164 		case TMS34010_B6:  BREG(BINDEX(6)) = val; break;
1165 		case TMS34010_B7:  BREG(BINDEX(7)) = val; break;
1166 		case TMS34010_B8:  BREG(BINDEX(8)) = val; break;
1167 		case TMS34010_B9:  BREG(BINDEX(9)) = val; break;
1168 		case TMS34010_B10: BREG(BINDEX(10)) = val; break;
1169 		case TMS34010_B11: BREG(BINDEX(11)) = val; break;
1170 		case TMS34010_B12: BREG(BINDEX(12)) = val; break;
1171 		case TMS34010_B13: BREG(BINDEX(13)) = val; break;
1172 		case TMS34010_B14: BREG(BINDEX(14)) = val; break;
1173 /* TODO: set contents of [SP + wordsize * (CPU_SP_CONTENTS-regnum)] */
1174 		default:
1175 			if (regnum <= REG_SP_CONTENTS)
1176 			{
1177 				unsigned offset = SP + 4 * (REG_SP_CONTENTS - regnum);
1178 				cpu_writemem29_word(TOBYTE(offset), val); /* ??? */
1179 			}
1180 	}
1181 }
1182 
tms34020_set_reg(int regnum,unsigned val)1183 void tms34020_set_reg(int regnum, unsigned val)
1184 {
1185 	tms34010_set_reg(regnum, val);
1186 }
1187 
1188 
1189 
1190 /*###################################################################################################
1191 **	Set NMI line state
1192 **#################################################################################################*/
1193 
tms34010_set_nmi_line(int linestate)1194 void tms34010_set_nmi_line(int linestate)
1195 {
1196 	/* Does not apply: the NMI is an internal interrupt for the TMS34010 */
1197 }
1198 
tms34020_set_nmi_line(int linestate)1199 void tms34020_set_nmi_line(int linestate)
1200 {
1201 	tms34010_set_nmi_line(linestate);
1202 }
1203 
1204 
1205 
1206 /*###################################################################################################
1207 **	Set IRQ line state
1208 **#################################################################################################*/
1209 
tms34010_set_irq_line(int irqline,int linestate)1210 void tms34010_set_irq_line(int irqline, int linestate)
1211 {
1212 	LOG(("TMS34010#%d set irq line %d state %d\n", cpu_getactivecpu(), irqline, linestate));
1213 
1214 	/* set the pending interrupt */
1215 	switch (irqline)
1216 	{
1217 		case 0:
1218 			if (linestate != CLEAR_LINE)
1219 				IOREG(REG_INTPEND) |= TMS34010_INT1;
1220 			else
1221 				IOREG(REG_INTPEND) &= ~TMS34010_INT1;
1222 			break;
1223 		case 1:
1224 			if (linestate != CLEAR_LINE)
1225 				IOREG(REG_INTPEND) |= TMS34010_INT2;
1226 			else
1227 				IOREG(REG_INTPEND) &= ~TMS34010_INT2;
1228 			break;
1229 	}
1230 	check_interrupt();
1231 }
1232 
tms34020_set_irq_line(int irqline,int linestate)1233 void tms34020_set_irq_line(int irqline, int linestate)
1234 {
1235 	tms34010_set_irq_line(irqline, linestate);
1236 }
1237 
1238 
1239 
1240 /*###################################################################################################
1241 **	Set IRQ callback
1242 **#################################################################################################*/
1243 
tms34010_set_irq_callback(int (* callback)(int irqline))1244 void tms34010_set_irq_callback(int (*callback)(int irqline))
1245 {
1246 	state.irq_callback = callback;
1247 }
1248 
tms34020_set_irq_callback(int (* callback)(int irqline))1249 void tms34020_set_irq_callback(int (*callback)(int irqline))
1250 {
1251 	tms34010_set_irq_callback(callback);
1252 }
1253 
1254 
1255 
1256 /*###################################################################################################
1257 **	Generate internal interrupt
1258 *#################################################################################################*/
1259 
tms34010_internal_interrupt(int type)1260 void tms34010_internal_interrupt(int type)
1261 {
1262 	LOG(("TMS34010#%d set internal interrupt $%04x\n", cpu_getactivecpu(), type));
1263 	IOREG(REG_INTPEND) |= type;
1264 	check_interrupt();
1265 }
1266 
tms34020_internal_interrupt(int type)1267 void tms34020_internal_interrupt(int type)
1268 {
1269 	tms34010_internal_interrupt(type);
1270 }
1271 
1272 
1273 
1274 /*###################################################################################################
1275 **	Execute
1276 *#################################################################################################*/
1277 
tms34010_execute(int cycles)1278 int tms34010_execute(int cycles)
1279 {
1280 	/* Get out if CPU is halted. Absolutely no interrupts must be taken!!! */
1281 	if (IOREG(REG_HSTCTLH) & 0x8000)
1282 		return cycles;
1283 
1284 	/* if the CPU's reset was deferred, do it now */
1285 	if (state.reset_deferred)
1286 	{
1287 		state.reset_deferred = 0;
1288 		PC = RLONG(0xffffffe0);
1289 	}
1290 
1291 	/* execute starting now */
1292 	tms34010_ICount = cycles;
1293 	change_pc29(PC)
1294 	do
1295 	{
1296 		state.op = ROPCODE();
1297 		(*opcode_table[state.op >> 4])();
1298 
1299 		state.op = ROPCODE();
1300 		(*opcode_table[state.op >> 4])();
1301 
1302 		state.op = ROPCODE();
1303 		(*opcode_table[state.op >> 4])();
1304 
1305 		state.op = ROPCODE();
1306 		(*opcode_table[state.op >> 4])();
1307 
1308 	} while (tms34010_ICount > 0);
1309 
1310 	return cycles - tms34010_ICount;
1311 }
1312 
tms34020_execute(int cycles)1313 int tms34020_execute(int cycles)
1314 {
1315 	return tms34010_execute(cycles);
1316 }
1317 
1318 
1319 
1320 /*###################################################################################################
1321 **	Return a formatted string for a register
1322 *#################################################################################################*/
1323 
tms34010_info(void * context,int regnum)1324 const char *tms34010_info(void *context, int regnum)
1325 {
1326 	switch (regnum)
1327 	{
1328 		case CPU_INFO_NAME: return "TMS34010";
1329 		case CPU_INFO_FAMILY: return "Texas Instruments 34010";
1330 		case CPU_INFO_VERSION: return "1.0";
1331 		case CPU_INFO_FILE: return __FILE__;
1332 		case CPU_INFO_CREDITS: return "Copyright (C) Alex Pasadyn/Zsolt Vasvari 1998\nParts based on code by Aaron Giles";
1333 	}
1334 	return "";
1335 }
1336 
tms34020_info(void * context,int regnum)1337 const char *tms34020_info(void *context, int regnum)
1338 {
1339 	switch (regnum)
1340 	{
1341 		case CPU_INFO_NAME: 	return "TMS34020";
1342 		case CPU_INFO_FAMILY: 	return "Texas Instruments 34020";
1343 		default:				return tms34010_info(context, regnum);
1344 	}
1345 }
1346 
1347 
1348 
1349 /*###################################################################################################
1350 **	Disassemble
1351 *#################################################################################################*/
1352 
tms34010_dasm(char * buffer,unsigned pc)1353 unsigned tms34010_dasm(char *buffer, unsigned pc)
1354 {
1355 	sprintf( buffer, "$%04X", cpu_readop16(pc>>3) );
1356 	return 2;
1357 }
1358 
tms34020_dasm(char * buffer,unsigned pc)1359 unsigned tms34020_dasm(char *buffer, unsigned pc)
1360 {
1361 	return tms34010_dasm(buffer, pc);
1362 }
1363 
1364 
1365 
1366 /*###################################################################################################
1367 **	PIXEL OPS
1368 **#################################################################################################*/
1369 
1370 static mem_write_handler pixel_write_ops[4][5] =
1371 {
1372 	{ write_pixel_1,     write_pixel_2,     write_pixel_4,     write_pixel_8,     write_pixel_16     },
1373 	{ write_pixel_r_1,   write_pixel_r_2,   write_pixel_r_4,   write_pixel_r_8,   write_pixel_r_16   },
1374 	{ write_pixel_t_1,   write_pixel_t_2,   write_pixel_t_4,   write_pixel_t_8,   write_pixel_t_16   },
1375 	{ write_pixel_r_t_1, write_pixel_r_t_2, write_pixel_r_t_4, write_pixel_r_t_8, write_pixel_r_t_16 }
1376 };
1377 
1378 static mem_read_handler pixel_read_ops[5] =
1379 {
1380 	read_pixel_1,        read_pixel_2,      read_pixel_4,      read_pixel_8,      read_pixel_16
1381 };
1382 
1383 
set_pixel_function(tms34010_regs * context)1384 static void set_pixel_function(tms34010_regs *context)
1385 {
1386 	UINT32 i1,i2;
1387 
1388 	if (CONTEXT_IOREG(context, REG_DPYCTL) & 0x0800)
1389 	{
1390 		/* Shift Register Transfer */
1391 		context->pixel_write = write_pixel_shiftreg;
1392 		context->pixel_read  = read_pixel_shiftreg;
1393 		return;
1394 	}
1395 
1396 	switch (CONTEXT_IOREG(context, REG_PSIZE))
1397 	{
1398 		default:
1399 		case 0x01: i2 = 0; break;
1400 		case 0x02: i2 = 1; break;
1401 		case 0x04: i2 = 2; break;
1402 		case 0x08: i2 = 3; break;
1403 		case 0x10: i2 = 4; break;
1404 	}
1405 
1406 	if (context->transparency)
1407 		i1 = context->raster_op ? 3 : 2;
1408 	else
1409 		i1 = context->raster_op ? 1 : 0;
1410 
1411 	context->pixel_write = pixel_write_ops[i1][i2];
1412 	context->pixel_read  = pixel_read_ops [i2];
1413 }
1414 
1415 
1416 
1417 /*###################################################################################################
1418 **	RASTER OPS
1419 **#################################################################################################*/
1420 
1421 static INT32 (*raster_ops[32]) (INT32 newpix, INT32 oldpix) =
1422 {
1423 	           0, raster_op_1 , raster_op_2 , raster_op_3,
1424 	raster_op_4 , raster_op_5 , raster_op_6 , raster_op_7,
1425 	raster_op_8 , raster_op_9 , raster_op_10, raster_op_11,
1426 	raster_op_12, raster_op_13, raster_op_14, raster_op_15,
1427 	raster_op_16, raster_op_17, raster_op_18, raster_op_19,
1428 	raster_op_20, raster_op_21,            0,            0,
1429 	           0,            0,            0,            0,
1430 	           0,            0,            0,            0,
1431 };
1432 
1433 
set_raster_op(tms34010_regs * context)1434 static void set_raster_op(tms34010_regs *context)
1435 {
1436 	context->raster_op = raster_ops[(IOREG(REG_CONTROL) >> 10) & 0x1f];
1437 }
1438 
1439 
1440 
1441 /*###################################################################################################
1442 **	VIDEO TIMING HELPERS
1443 **#################################################################################################*/
1444 
scanline_to_vcount(tms34010_regs * context,int scanline)1445 static INLINE int scanline_to_vcount(tms34010_regs *context, int scanline)
1446 {
1447 	if (Machine->visible_area.min_y == 0)
1448 		scanline += CONTEXT_IOREG(context, REG_VEBLNK);
1449 	if (scanline > CONTEXT_IOREG(context, REG_VTOTAL))
1450 		scanline -= CONTEXT_IOREG(context, REG_VTOTAL);
1451 	return scanline;
1452 }
1453 
1454 
vcount_to_scanline(tms34010_regs * context,int vcount)1455 static INLINE int vcount_to_scanline(tms34010_regs *context, int vcount)
1456 {
1457 	if (Machine->visible_area.min_y == 0)
1458 		vcount -= CONTEXT_IOREG(context, REG_VEBLNK);
1459 	if (vcount < 0)
1460 		vcount += CONTEXT_IOREG(context, REG_VTOTAL);
1461 	if (vcount > Machine->visible_area.max_y)
1462 		vcount = 0;
1463 	return vcount;
1464 }
1465 
1466 
update_display_address(tms34010_regs * context,int vcount)1467 static void update_display_address(tms34010_regs *context, int vcount)
1468 {
1469 	UINT32 dpyadr = CONTEXT_IOREG(context, REG_DPYADR) & 0xfffc;
1470 	UINT32 dpytap = CONTEXT_IOREG(context, REG_DPYTAP) & 0x3fff;
1471 	INT32 dudate = CONTEXT_IOREG(context, REG_DPYCTL) & 0x03fc;
1472 	int org = CONTEXT_IOREG(context, REG_DPYCTL) & 0x0400;
1473 	int scans = (CONTEXT_IOREG(context, REG_DPYSTRT) & 3) + 1;
1474 
1475 	/* anytime during VBLANK is effectively the start of the next frame */
1476 	if (vcount >= CONTEXT_IOREG(context, REG_VSBLNK) || vcount <= CONTEXT_IOREG(context, REG_VEBLNK))
1477 		context->last_update_vcount = vcount = CONTEXT_IOREG(context, REG_VEBLNK);
1478 
1479 	/* otherwise, compute the updated address */
1480 	else
1481 	{
1482 		int rows = vcount - context->last_update_vcount;
1483 		if (rows < 0) rows += CONTEXT_IOREG(context, REG_VCOUNT);
1484 		dpyadr -= rows * dudate / scans;
1485 		CONTEXT_IOREG(context, REG_DPYADR) = dpyadr | (CONTEXT_IOREG(context, REG_DPYADR) & 0x0003);
1486 		context->last_update_vcount = vcount;
1487 	}
1488 
1489 	/* now compute the actual address */
1490 	if (org == 0) dpyadr ^= 0xfffc;
1491 	dpyadr <<= 8;
1492 	dpyadr |= dpytap << 4;
1493 
1494 	/* callback */
1495 	if (context->config->display_addr_changed)
1496 	{
1497 		if (org != 0) dudate = -dudate;
1498 		(*context->config->display_addr_changed)(dpyadr & 0x00ffffff, (dudate << 8) / scans, vcount_to_scanline(context, vcount));
1499 	}
1500 }
1501 
1502 
vsblnk_callback(int cpunum)1503 static void vsblnk_callback(int cpunum)
1504 {
1505 	/* reset timer for next frame */
1506 	//float interval = TIME_IN_HZ(Machine->drv->frames_per_second);
1507 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpunum);
1508 	vsblnk_timer[cpunum] = timer_set(interval, cpunum, vsblnk_callback);
1509 	CONTEXT_IOREG(context, REG_DPYADR) = CONTEXT_IOREG(context, REG_DPYSTRT);
1510 	update_display_address(context, CONTEXT_IOREG(context, REG_VSBLNK));
1511 }
1512 
1513 
dpyint_callback(int cpunum)1514 static void dpyint_callback(int cpunum)
1515 {
1516 	/* reset timer for next frame */
1517 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpunum);
1518 	//float interval = TIME_IN_HZ(Machine->drv->frames_per_second);
1519 	dpyint_timer[cpunum] = timer_set(interval, cpunum, dpyint_callback);
1520 	cpu_generate_internal_interrupt(cpunum, TMS34010_DI);
1521 
1522 	/* allow a callback so we can update before they are likely to do nasty things */
1523 	if (context->config->display_int_callback)
1524 		(*context->config->display_int_callback)(vcount_to_scanline(context, CONTEXT_IOREG(context, REG_DPYINT)));
1525 }
1526 
1527 
update_timers(int cpunum,tms34010_regs * context)1528 static void update_timers(int cpunum, tms34010_regs *context)
1529 {
1530 	int dpyint = CONTEXT_IOREG(context, REG_DPYINT);
1531 	int vsblnk = CONTEXT_IOREG(context, REG_VSBLNK);
1532 
1533 	/* remove any old timers */
1534 	if (dpyint_timer[cpunum])
1535 		timer_remove(dpyint_timer[cpunum]);
1536 	if (vsblnk_timer[cpunum])
1537 		timer_remove(vsblnk_timer[cpunum]);
1538 
1539 	/* set new timers */
1540 	dpyint_timer[cpunum] = timer_set(cpu_getscanlinetime(vcount_to_scanline(context, dpyint)), cpunum, dpyint_callback);
1541 	vsblnk_timer[cpunum] = timer_set(cpu_getscanlinetime(vcount_to_scanline(context, vsblnk)), cpunum, vsblnk_callback);
1542 }
1543 
1544 
1545 
1546 /*###################################################################################################
1547 **	I/O REGISTER WRITES
1548 **#################################################################################################*/
1549 
1550 /*
1551 static const char *ioreg_name[] =
1552 {
1553 	"HESYNC", "HEBLNK", "HSBLNK", "HTOTAL",
1554 	"VESYNC", "VEBLNK", "VSBLNK", "VTOTAL",
1555 	"DPYCTL", "DPYSTART", "DPYINT", "CONTROL",
1556 	"HSTDATA", "HSTADRL", "HSTADRH", "HSTCTLL",
1557 	"HSTCTLH", "INTENB", "INTPEND", "CONVSP",
1558 	"CONVDP", "PSIZE", "PMASK", "RESERVED",
1559 	"RESERVED", "RESERVED", "RESERVED", "DPYTAP",
1560 	"HCOUNT", "VCOUNT", "DPYADR", "REFCNT"
1561 };
1562 */
1563 
common_io_register_w(int cpunum,tms34010_regs * context,int reg,int data)1564 static void common_io_register_w(int cpunum, tms34010_regs *context, int reg, int data)
1565 {
1566 	int oldreg, newreg;
1567 
1568 	/* Set register */
1569 	reg >>= 1;
1570 	oldreg = CONTEXT_IOREG(context, reg);
1571 	CONTEXT_IOREG(context, reg) = data;
1572 
1573 	switch (reg)
1574 	{
1575 		case REG_DPYINT:
1576 			if (data != oldreg || !dpyint_timer[cpunum])
1577 				update_timers(cpunum, context);
1578 			break;
1579 
1580 		case REG_VSBLNK:
1581 			if (data != oldreg || !vsblnk_timer[cpunum])
1582 				update_timers(cpunum, context);
1583 			break;
1584 
1585 		case REG_VEBLNK:
1586 			if (data != oldreg)
1587 				update_timers(cpunum, context);
1588 			break;
1589 
1590 		case REG_CONTROL:
1591 			context->transparency = data & 0x20;
1592 			context->window_checking = (data >> 6) & 0x03;
1593 			set_raster_op(context);
1594 			set_pixel_function(context);
1595 			break;
1596 
1597 		case REG_PSIZE:
1598 			set_pixel_function(context);
1599 
1600 			switch (data)
1601 			{
1602 				default:
1603 				case 0x01: context->xytolshiftcount2 = 0; break;
1604 				case 0x02: context->xytolshiftcount2 = 1; break;
1605 				case 0x04: context->xytolshiftcount2 = 2; break;
1606 				case 0x08: context->xytolshiftcount2 = 3; break;
1607 				case 0x10: context->xytolshiftcount2 = 4; break;
1608 			}
1609 			break;
1610 
1611 		case REG_PMASK:
1612 			/*if (data) logerror("Plane masking not supported. PC=%08X\n", cpu_get_pc());*/
1613 			break;
1614 
1615 		case REG_DPYCTL:
1616 			set_pixel_function(context);
1617 			if ((oldreg ^ data) & 0x03fc)
1618 				update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
1619 			break;
1620 
1621 		case REG_DPYADR:
1622 			if (data != oldreg)
1623 			{
1624 				context->last_update_vcount = scanline_to_vcount(context, cpu_getscanline());
1625 				update_display_address(context, context->last_update_vcount);
1626 			}
1627 			break;
1628 
1629 		case REG_DPYSTRT:
1630 			if (data != oldreg)
1631 				update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
1632 			break;
1633 
1634 		case REG_DPYTAP:
1635 			if ((oldreg ^ data) & 0x3fff)
1636 				update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
1637 			break;
1638 
1639 		case REG_HSTCTLH:
1640 			/* if the CPU is halting itself, stop execution right away */
1641 			if ((data & 0x8000) && context == &state)
1642 				tms34010_ICount = 0;
1643 			cpu_set_halt_line(cpunum, (data & 0x8000) ? ASSERT_LINE : CLEAR_LINE);
1644 
1645 			/* NMI issued? */
1646 			if (data & 0x0100)
1647 				cpu_generate_internal_interrupt(cpunum, TMS34010_NMI);
1648 			break;
1649 
1650 		case REG_HSTCTLL:
1651 			/* the TMS34010 can change MSGOUT, can set INTOUT, and can clear INTIN */
1652 			if (cpunum == cpu_getactivecpu())
1653 			{
1654 				newreg = (oldreg & 0xff8f) | (data & 0x0070);
1655 				newreg |= data & 0x0080;
1656 				newreg &= data | ~0x0008;
1657 			}
1658 
1659 			/* the host can change MSGIN, can set INTIN, and can clear INTOUT */
1660 			else
1661 			{
1662 				newreg = (oldreg & 0xfff8) | (data & 0x0007);
1663 				newreg &= data | ~0x0080;
1664 				newreg |= data & 0x0008;
1665 			}
1666 			CONTEXT_IOREG(context, reg) = newreg;
1667 
1668 			/* output interrupt? */
1669 			if (!(oldreg & 0x0080) && (newreg & 0x0080))
1670 			{
1671 				//logerror("CPU#%d Output int = 1\n", cpunum);
1672 				if (context->config->output_int)
1673 					(*context->config->output_int)(1);
1674 			}
1675 			else if ((oldreg & 0x0080) && !(newreg & 0x0080))
1676 			{
1677 				//logerror("CPU#%d Output int = 0\n", cpunum);
1678 				if (context->config->output_int)
1679 					(*context->config->output_int)(0);
1680 			}
1681 
1682 			/* input interrupt? (should really be state-based, but the functions don't exist!) */
1683 			if (!(oldreg & 0x0008) && (newreg & 0x0008))
1684 			{
1685 				//logerror("CPU#%d Input int = 1\n", cpunum);
1686 				cpu_generate_internal_interrupt(cpunum, TMS34010_HI);
1687 			}
1688 			else if ((oldreg & 0x0008) && !(newreg & 0x0008))
1689 			{
1690 				//logerror("CPU#%d Input int = 0\n", cpunum);
1691 				CONTEXT_IOREG(context, REG_INTPEND) &= ~TMS34010_HI;
1692 			}
1693 			break;
1694 
1695 		case REG_CONVDP:
1696 			context->xytolshiftcount1 = ~data & 0x0f;
1697 			break;
1698 
1699 		case REG_INTENB:
1700 			if (CONTEXT_IOREG(context, REG_INTENB) & CONTEXT_IOREG(context, REG_INTPEND))
1701 				check_interrupt();
1702 			break;
1703 	}
1704 
1705 	/*if (LOG_CONTROL_REGS)
1706 		logerror("CPU#%d: %s = %04X (%d)\n", cpunum, ioreg_name[reg], CONTEXT_IOREG(context, reg), cpu_getscanline());*/
1707 }
1708 
WRITE_HANDLER(tms34010_io_register_w)1709 WRITE_HANDLER( tms34010_io_register_w )
1710 {
1711 	if (!host_interface_context)
1712 		common_io_register_w(cpu_getactivecpu(), &state, offset, data);
1713 	else
1714 		common_io_register_w(host_interface_cpu, host_interface_context, offset, data);
1715 }
1716 
1717 
1718 
1719 /*###################################################################################################
1720 **	I/O REGISTER READS
1721 **#################################################################################################*/
1722 
common_io_register_r(int cpunum,tms34010_regs * context,int reg)1723 static int common_io_register_r(int cpunum, tms34010_regs *context, int reg)
1724 {
1725 	int result, total;
1726 
1727 	reg >>= 1;
1728 	/*if (LOG_CONTROL_REGS)
1729 		logerror("CPU#%d: read %s\n", cpunum, ioreg_name[reg]);*/
1730 
1731 	switch (reg)
1732 	{
1733 		case REG_VCOUNT:
1734 			return scanline_to_vcount(context, cpu_getscanline());
1735 
1736 		case REG_HCOUNT:
1737 
1738 			/* scale the horizontal position from screen width to HTOTAL */
1739 			result = cpu_gethorzbeampos();
1740 			total = CONTEXT_IOREG(context, REG_HTOTAL);
1741 			result = result * total / Machine->drv->screen_width;
1742 
1743 			/* offset by the HBLANK end */
1744 			result += CONTEXT_IOREG(context, REG_HEBLNK);
1745 
1746 			/* wrap around */
1747 			if (result > total)
1748 				result -= total;
1749 			return result;
1750 
1751 		case REG_DPYADR:
1752 			update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
1753 			break;
1754 	}
1755 
1756 	return CONTEXT_IOREG(context, reg);
1757 }
1758 
1759 
READ_HANDLER(tms34010_io_register_r)1760 READ_HANDLER( tms34010_io_register_r )
1761 {
1762 	if (!host_interface_context)
1763 		return common_io_register_r(cpu_getactivecpu(), &state, offset);
1764 	else
1765 		return common_io_register_r(host_interface_cpu, host_interface_context, offset);
1766 }
1767 
1768 
1769 
1770 /*###################################################################################################
1771 **	UTILITY FUNCTIONS
1772 **#################################################################################################*/
1773 
tms34010_io_display_blanked(int cpu)1774 int tms34010_io_display_blanked(int cpu)
1775 {
1776 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpu);
1777 	return (!(context->IOregs[REG_DPYCTL] & 0x8000));
1778 }
1779 
1780 
tms34010_get_DPYSTRT(int cpu)1781 int tms34010_get_DPYSTRT(int cpu)
1782 {
1783 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpu);
1784 	return context->IOregs[REG_DPYSTRT];
1785 }
1786 
1787 
1788 
1789 /*###################################################################################################
1790 **	SAVE STATE
1791 **#################################################################################################*/
1792 
tms34010_state_save(int cpunum,void * f)1793 void tms34010_state_save(int cpunum, void *f)
1794 {
1795 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpunum);
1796 	osd_fwrite(f,context,sizeof(state));
1797 	osd_fwrite(f,&tms34010_ICount,sizeof(tms34010_ICount));
1798 	osd_fwrite(f,state.shiftreg,sizeof(SHIFTREG_SIZE));
1799 }
1800 
1801 
tms34010_state_load(int cpunum,void * f)1802 void tms34010_state_load(int cpunum, void *f)
1803 {
1804 	/* Don't reload the following */
1805 	UINT16 *shiftreg_save = state.shiftreg;
1806 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpunum);
1807 
1808 	osd_fread(f,context,sizeof(state));
1809 	osd_fread(f,&tms34010_ICount,sizeof(tms34010_ICount));
1810 	change_pc29(PC);
1811 	SET_FW();
1812 	tms34010_io_register_w(REG_DPYINT<<1,IOREG(REG_DPYINT));
1813 	set_raster_op(&state);
1814 	set_pixel_function(&state);
1815 
1816 	state.shiftreg      = shiftreg_save;
1817 
1818 	osd_fread(f,state.shiftreg,sizeof(SHIFTREG_SIZE));
1819 }
1820 
1821 
1822 
1823 /*###################################################################################################
1824 **	HOST INTERFACE WRITES
1825 **#################################################################################################*/
1826 
tms34010_host_w(int cpunum,int reg,int data)1827 void tms34010_host_w(int cpunum, int reg, int data)
1828 {
1829 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpunum);
1830 	const struct cpu_interface *interface;
1831 	unsigned int addr;
1832 	int oldcpu;
1833 
1834 	switch (reg)
1835 	{
1836 		/* upper 16 bits of the address */
1837 		case TMS34010_HOST_ADDRESS_H:
1838 			CONTEXT_IOREG(context, REG_HSTADRH) = data;
1839 			break;
1840 
1841 		/* lower 16 bits of the address */
1842 		case TMS34010_HOST_ADDRESS_L:
1843 			CONTEXT_IOREG(context, REG_HSTADRL) = data & 0xfff0;
1844 			break;
1845 
1846 		/* actual data */
1847 		case TMS34010_HOST_DATA:
1848 
1849 			/* swap to the target cpu */
1850 			oldcpu = cpu_getactivecpu();
1851 			memorycontextswap(cpunum);
1852 
1853 			/* write to the address */
1854 			host_interface_cpu = cpunum;
1855 			host_interface_context = context;
1856 			addr = (CONTEXT_IOREG(context, REG_HSTADRH) << 16) | CONTEXT_IOREG(context, REG_HSTADRL);
1857 			TMS34010_WRMEM_WORD(TOBYTE(addr), data);
1858 			host_interface_context = NULL;
1859 
1860 			/* optional postincrement */
1861 			if (CONTEXT_IOREG(context, REG_HSTCTLH) & 0x0800)
1862 			{
1863 				addr += 0x10;
1864 				CONTEXT_IOREG(context, REG_HSTADRH) = addr >> 16;
1865 				CONTEXT_IOREG(context, REG_HSTADRL) = (UINT16)addr;
1866 			}
1867 
1868 			/* swap back */
1869 			memorycontextswap(oldcpu);
1870 			interface = &cpuintf[Machine->drv->cpu[oldcpu].cpu_type & ~CPU_FLAGS_MASK];
1871 			(*interface->set_op_base)((*interface->get_pc)());
1872 			break;
1873 
1874 		/* control register */
1875 		case TMS34010_HOST_CONTROL:
1876 			common_io_register_w(cpunum, context, REG_HSTCTLH * 2, data & 0xff00);
1877 			common_io_register_w(cpunum, context, REG_HSTCTLL * 2, data & 0x00ff);
1878 			break;
1879 
1880 		/* error case */
1881 		default:
1882 			//logerror("tms34010_host_control_w called on invalid register %d\n", reg);
1883 			break;
1884 	}
1885 }
1886 
1887 
1888 
1889 /*###################################################################################################
1890 **	HOST INTERFACE READS
1891 **#################################################################################################*/
1892 
tms34010_host_r(int cpunum,int reg)1893 int tms34010_host_r(int cpunum, int reg)
1894 {
1895 	tms34010_regs *context = (tms34010_regs *)FINDCONTEXT(cpunum);
1896 	const struct cpu_interface *interface;
1897 	unsigned int addr;
1898 	int oldcpu, result;
1899 
1900 	switch (reg)
1901 	{
1902 		/* upper 16 bits of the address */
1903 		case TMS34010_HOST_ADDRESS_H:
1904 			return CONTEXT_IOREG(context, REG_HSTADRH);
1905 
1906 		/* lower 16 bits of the address */
1907 		case TMS34010_HOST_ADDRESS_L:
1908 			return CONTEXT_IOREG(context, REG_HSTADRL);
1909 
1910 		/* actual data */
1911 		case TMS34010_HOST_DATA:
1912 
1913 			/* swap to the target cpu */
1914 			oldcpu = cpu_getactivecpu();
1915 			memorycontextswap(cpunum);
1916 
1917 			/* read from the address */
1918 			host_interface_cpu = cpunum;
1919 			host_interface_context = context;
1920 			addr = (CONTEXT_IOREG(context, REG_HSTADRH) << 16) | CONTEXT_IOREG(context, REG_HSTADRL);
1921 			result = TMS34010_RDMEM_WORD(TOBYTE(addr));
1922 			host_interface_context = NULL;
1923 
1924 			/* optional postincrement (it says preincrement, but data is preloaded, so it
1925 			   is effectively a postincrement */
1926 			if (CONTEXT_IOREG(context, REG_HSTCTLH) & 0x1000)
1927 			{
1928 				addr += 0x10;
1929 				CONTEXT_IOREG(context, REG_HSTADRH) = addr >> 16;
1930 				CONTEXT_IOREG(context, REG_HSTADRL) = (UINT16)addr;
1931 			}
1932 
1933 			/* swap back */
1934 			memorycontextswap(oldcpu);
1935 			interface = &cpuintf[Machine->drv->cpu[oldcpu].cpu_type & ~CPU_FLAGS_MASK];
1936 			(*interface->set_op_base)((*interface->get_pc)());
1937 			return result;
1938 
1939 		/* control register */
1940 		case TMS34010_HOST_CONTROL:
1941 			return (CONTEXT_IOREG(context, REG_HSTCTLH) & 0xff00) | (CONTEXT_IOREG(context, REG_HSTCTLL) & 0x00ff);
1942 	}
1943 
1944 	/* error case */
1945 	//logerror("tms34010_host_control_r called on invalid register %d\n", reg);
1946 	return 0;
1947 }
1948