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