1 /***************************************************************************
2
3 TMS34010: Portable Texas Instruments TMS34010 emulator
4
5 Copyright Alex Pasadyn/Zsolt Vasvari
6 Parts based on code by Aaron Giles
7
8 ***************************************************************************/
9
10 #include "burnint.h"
11 #include "tiles_generic.h"
12 #include "tms34010.h"
13 #include "34010ops.h"
14 #include "stddef.h"
15
16
17 /***************************************************************************
18 DEBUG STATE & STRUCTURES
19 ***************************************************************************/
20
21 #define VERBOSE 0
22 #define LOG_CONTROL_REGS 0
23 #define LOG_GRAPHICS_OPS 0
24
25 #define logerror
26 #define fatalerror
27
28 #define LOG(x) do { if (VERBOSE) logerror x; } while (0)
29
30 enum {
31 CLEAR_LINE = 0,
32 ASSERT_LINE,
33 HOLD_LINE,
34 PULSE_LINE
35 };
36
37
38 /***************************************************************************
39 CORE STATE
40 ***************************************************************************/
41
42 /* TMS34010 State */
43 typedef struct
44 {
45 #ifdef LSB_FIRST
46 INT16 x;
47 INT16 y;
48 #else
49 INT16 y;
50 INT16 x;
51 #endif
52 } XY;
53
54 typedef struct tms34010_regs
55 {
56 UINT16 op;
57 UINT32 pc;
58 UINT32 st;
59 UINT32 convsp;
60 UINT32 convdp;
61 UINT32 convmp;
62 INT32 gfxcycles;
63 UINT8 pixelshift;
64 UINT8 is_34020;
65 UINT8 reset_deferred;
66 UINT8 hblank_stable;
67
68 INT32 irqhold[2];
69
70 INT64 total_cycles;
71 INT32 timer_cyc;
72 UINT32 timer_active;
73 INT32 cycles_start;
74 INT32 icounter;
75 INT32 stop;
76
77 /* A registers 0-15 map to regs[0]-regs[15] */
78 /* B registers 0-15 map to regs[30]-regs[15] */
79 union
80 {
81 INT32 reg;
82 XY xy;
83 } regs[31];
84
85 /* for the 34010, we only copy 32 of these into the new state */
86 UINT16 IOregs[64];
87
88 UINT8 external_host_access;
89
90 UINT32 pointer_separator;
91
92 tms34010_config config;
93 UINT16 *shiftreg;
94 void (*timer_cb)();
95
96 void (*pixel_write)(offs_t offset, UINT32 data);
97 UINT32 (*pixel_read)(offs_t offset);
98 UINT32 (*raster_op)(UINT32 newpix, UINT32 oldpix);
99 } tms34010_regs;
100
101 /***************************************************************************
102 GLOBAL VARIABLES
103 ***************************************************************************/
104
105 /* public globals */
106 #define tms34010_ICount state.icounter
107
108 /* internal state */
109 static tms34010_regs state;
110
111 static void check_interrupt(void);
112 static void check_timer(int cyc);
113 static void set_raster_op(void);
114 static void set_pixel_function(void);
115
tms34010_context_size()116 int tms34010_context_size()
117 {
118 return sizeof(tms34010_regs);
119 }
120
tms34010_get_context(void * get)121 void tms34010_get_context(void *get)
122 {
123 memcpy(get, &state, sizeof(tms34010_regs));
124 }
125
tms34010_set_context(void * set)126 void tms34010_set_context(void *set)
127 {
128 memcpy(&state, set, sizeof(tms34010_regs));
129 }
130
131 /***************************************************************************
132 MACROS
133 ***************************************************************************/
134
135 /* status register definitions */
136 #define STBIT_N (1 << 31)
137 #define STBIT_C (1 << 30)
138 #define STBIT_Z (1 << 29)
139 #define STBIT_V (1 << 28)
140 #define STBIT_P (1 << 25)
141 #define STBIT_IE (1 << 21)
142 #define STBIT_FE1 (1 << 11)
143 #define STBITS_F1 (0x1f << 6)
144 #define STBIT_FE0 (1 << 5)
145 #define STBITS_F0 (0x1f << 0)
146
147 /* register definitions and shortcuts */
148 #define PC (state.pc)
149 #define ST (state.st)
150 #define N_FLAG (state.st & STBIT_N)
151 #define Z_FLAG (state.st & STBIT_Z)
152 #define C_FLAG (state.st & STBIT_C)
153 #define V_FLAG (state.st & STBIT_V)
154 #define P_FLAG (state.st & STBIT_P)
155 #define IE_FLAG (state.st & STBIT_IE)
156 #define FE0_FLAG (state.st & STBIT_FE0)
157 #define FE1_FLAG (state.st & STBIT_FE1)
158
159 /* register file access */
160 #define AREG(i) (state.regs[i].reg)
161 #define AREG_XY(i) (state.regs[i].xy)
162 #define AREG_X(i) (state.regs[i].xy.x)
163 #define AREG_Y(i) (state.regs[i].xy.y)
164 #define BREG(i) (state.regs[30 - (i)].reg)
165 #define BREG_XY(i) (state.regs[30 - (i)].xy)
166 #define BREG_X(i) (state.regs[30 - (i)].xy.x)
167 #define BREG_Y(i) (state.regs[30 - (i)].xy.y)
168 #define SP AREG(15)
169 #define FW(i) ((state.st >> (i ? 6 : 0)) & 0x1f)
170 #define FWEX(i) ((state.st >> (i ? 6 : 0)) & 0x3f)
171
172 /* opcode decode helpers */
173 #define SRCREG ((state.op >> 5) & 0x0f)
174 #define DSTREG (state.op & 0x0f)
175 #define SKIP_WORD (PC += (2 << 3))
176 #define SKIP_LONG (PC += (4 << 3))
177 #define PARAM_K ((state.op >> 5) & 0x1f)
178 #define PARAM_N (state.op & 0x1f)
179 #define PARAM_REL8 ((INT8)state.op)
180
181 /* memory I/O */
182 #define WFIELD0(a,b) (*tms34010_wfield_functions[FW(0)])(a,b)
183 #define WFIELD1(a,b) (*tms34010_wfield_functions[FW(1)])(a,b)
184 #define RFIELD0(a) (*tms34010_rfield_functions[FWEX(0)])(a)
185 #define RFIELD1(a) (*tms34010_rfield_functions[FWEX(1)])(a)
186 #define WPIXEL(a,b) state.pixel_write(a,b)
187 #define RPIXEL(a) state.pixel_read(a)
188
189 /* Implied Operands */
190 #define SADDR BREG(0)
191 #define SADDR_X BREG_X(0)
192 #define SADDR_Y BREG_Y(0)
193 #define SADDR_XY BREG_XY(0)
194 #define SPTCH BREG(1)
195 #define DADDR BREG(2)
196 #define DADDR_X BREG_X(2)
197 #define DADDR_Y BREG_Y(2)
198 #define DADDR_XY BREG_XY(2)
199 #define DPTCH BREG(3)
200 #define OFFSET BREG(4)
201 #define WSTART_X BREG_X(5)
202 #define WSTART_Y BREG_Y(5)
203 #define WEND_X BREG_X(6)
204 #define WEND_Y BREG_Y(6)
205 #define DYDX_X BREG_X(7)
206 #define DYDX_Y BREG_Y(7)
207 #define COLOR0 BREG(8)
208 #define COLOR1 BREG(9)
209 #define COUNT BREG(10)
210 #define INC1_X BREG_X(11)
211 #define INC1_Y BREG_Y(11)
212 #define INC2_X BREG_X(12)
213 #define INC2_Y BREG_Y(12)
214 #define PATTRN BREG(13)
215 #define TEMP BREG(14)
216
217 /* I/O registers */
218 #define WINDOW_CHECKING ((IOREG(REG_CONTROL) >> 6) & 0x03)
219
220
221
222 /***************************************************************************
223 INLINE SHORTCUTS
224 ***************************************************************************/
225
226 /* Combine indiviual flags into the Status Register */
GET_ST(void)227 INLINE UINT32 GET_ST(void)
228 {
229 return state.st;
230 }
231
232 /* Break up Status Register into indiviual flags */
SET_ST(UINT32 st)233 INLINE void SET_ST(UINT32 st)
234 {
235 state.st = st;
236 /* interrupts might have been enabled, check it */
237 check_interrupt();
238 }
239
240 /* Intialize Status to 0x0010 */
RESET_ST(void)241 INLINE void RESET_ST(void)
242 {
243 SET_ST(0x00000010);
244 }
245
246 /* shortcuts for reading opcodes */
ROPCODE(void)247 INLINE UINT32 ROPCODE(void)
248 {
249 UINT32 pc = TOBYTE(PC);
250 PC += 2 << 3;
251 return cpu_readop16(pc);
252 }
253
PARAM_WORD(void)254 INLINE INT16 PARAM_WORD(void)
255 {
256 UINT32 pc = TOBYTE(PC);
257 PC += 2 << 3;
258 return cpu_readop_arg16(pc);
259 }
260
PARAM_LONG(void)261 INLINE INT32 PARAM_LONG(void)
262 {
263 UINT32 pc = TOBYTE(PC);
264 PC += 4 << 3;
265 return (UINT16)cpu_readop_arg16(pc) | (cpu_readop_arg16(pc + 2) << 16);
266 }
267
PARAM_WORD_NO_INC(void)268 INLINE INT16 PARAM_WORD_NO_INC(void)
269 {
270 return cpu_readop_arg16(TOBYTE(PC));
271 }
272
PARAM_LONG_NO_INC(void)273 INLINE INT32 PARAM_LONG_NO_INC(void)
274 {
275 UINT32 pc = TOBYTE(PC);
276 return (UINT16)cpu_readop_arg16(pc) | (cpu_readop_arg16(pc + 2) << 16);
277 }
278
279 /* read memory byte */
RBYTE(offs_t offset)280 INLINE UINT32 RBYTE(offs_t offset)
281 {
282 UINT32 ret;
283 RFIELDMAC_8;
284 return ret;
285 }
286
287 /* write memory byte */
WBYTE(offs_t offset,UINT32 data)288 INLINE void WBYTE(offs_t offset, UINT32 data)
289 {
290 WFIELDMAC_8;
291 }
292
293 /* read memory long */
RLONG(offs_t offset)294 INLINE UINT32 RLONG(offs_t offset)
295 {
296 RFIELDMAC_32;
297 }
298
299 /* write memory long */
WLONG(offs_t offset,UINT32 data)300 INLINE void WLONG(offs_t offset, UINT32 data)
301 {
302 WFIELDMAC_32;
303 }
304
305 /* pushes/pops a value from the stack */
PUSH(UINT32 data)306 INLINE void PUSH(UINT32 data)
307 {
308 SP -= 0x20;
309 WLONG(SP, data);
310 }
311
POP(void)312 INLINE INT32 POP(void)
313 {
314 INT32 ret = RLONG(SP);
315 SP += 0x20;
316 return ret;
317 }
318
319
320
321 /***************************************************************************
322 PIXEL READS
323 ***************************************************************************/
324
325 #define RP(m1,m2) \
326 /* TODO: Plane masking */ \
327 return (TMS34010_RDMEM_WORD(TOBYTE(offset & 0xfffffff0)) >> (offset & m1)) & m2;
328
read_pixel_1(offs_t offset)329 static UINT32 read_pixel_1(offs_t offset) { RP(0x0f,0x01) }
read_pixel_2(offs_t offset)330 static UINT32 read_pixel_2(offs_t offset) { RP(0x0e,0x03) }
read_pixel_4(offs_t offset)331 static UINT32 read_pixel_4(offs_t offset) { RP(0x0c,0x0f) }
read_pixel_8(offs_t offset)332 static UINT32 read_pixel_8(offs_t offset) { RP(0x08,0xff) }
read_pixel_16(offs_t offset)333 static UINT32 read_pixel_16(offs_t offset)
334 {
335 /* TODO: Plane masking */
336 return TMS34010_RDMEM_WORD(TOBYTE(offset & 0xfffffff0));
337 }
read_pixel_32(offs_t offset)338 static UINT32 read_pixel_32(offs_t offset)
339 {
340 /* TODO: Plane masking */
341 return TMS34010_RDMEM_DWORD(TOBYTE(offset & 0xffffffe0));
342 }
343
344 /* Shift register read */
read_pixel_shiftreg(offs_t offset)345 static UINT32 read_pixel_shiftreg(offs_t offset)
346 {
347 if (state.config.to_shiftreg)
348 state.config.to_shiftreg(offset, &state.shiftreg[0]);
349 else
350 fatalerror("To ShiftReg function not set. PC = %08X\n", PC);
351 return state.shiftreg[0];
352 }
353
354
355
356 /***************************************************************************
357 PIXEL WRITES
358 ***************************************************************************/
359
360 /* No Raster Op + No Transparency */
361 #define WP(m1,m2) \
362 UINT32 a = TOBYTE(offset & 0xfffffff0); \
363 UINT32 pix = TMS34010_RDMEM_WORD(a); \
364 UINT32 shiftcount = offset & m1; \
365 \
366 /* TODO: plane masking */ \
367 data &= m2; \
368 pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
369 TMS34010_WRMEM_WORD(a, pix); \
370
371 /* No Raster Op + Transparency */
372 #define WP_T(m1,m2) \
373 /* TODO: plane masking */ \
374 data &= m2; \
375 if (data) \
376 { \
377 UINT32 a = TOBYTE(offset & 0xfffffff0); \
378 UINT32 pix = TMS34010_RDMEM_WORD(a); \
379 UINT32 shiftcount = offset & m1; \
380 \
381 /* TODO: plane masking */ \
382 pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
383 TMS34010_WRMEM_WORD(a, pix); \
384 } \
385
386 /* Raster Op + No Transparency */
387 #define WP_R(m1,m2) \
388 UINT32 a = TOBYTE(offset & 0xfffffff0); \
389 UINT32 pix = TMS34010_RDMEM_WORD(a); \
390 UINT32 shiftcount = offset & m1; \
391 \
392 /* TODO: plane masking */ \
393 data = state.raster_op(data & m2, (pix >> shiftcount) & m2) & m2; \
394 pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
395 TMS34010_WRMEM_WORD(a, pix); \
396
397 /* Raster Op + Transparency */
398 #define WP_R_T(m1,m2) \
399 UINT32 a = TOBYTE(offset & 0xfffffff0); \
400 UINT32 pix = TMS34010_RDMEM_WORD(a); \
401 UINT32 shiftcount = offset & m1; \
402 \
403 /* TODO: plane masking */ \
404 data = state.raster_op(data & m2, (pix >> shiftcount) & m2) & m2; \
405 if (data) \
406 { \
407 pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
408 TMS34010_WRMEM_WORD(a, pix); \
409 } \
410
411
412 /* No Raster Op + No Transparency */
write_pixel_1(offs_t offset,UINT32 data)413 static void write_pixel_1(offs_t offset, UINT32 data) { WP(0x0f, 0x01); }
write_pixel_2(offs_t offset,UINT32 data)414 static void write_pixel_2(offs_t offset, UINT32 data) { WP(0x0e, 0x03); }
write_pixel_4(offs_t offset,UINT32 data)415 static void write_pixel_4(offs_t offset, UINT32 data) { WP(0x0c, 0x0f); }
write_pixel_8(offs_t offset,UINT32 data)416 static void write_pixel_8(offs_t offset, UINT32 data) { WP(0x08, 0xff); }
write_pixel_16(offs_t offset,UINT32 data)417 static void write_pixel_16(offs_t offset, UINT32 data)
418 {
419 /* TODO: plane masking */
420 TMS34010_WRMEM_WORD(TOBYTE(offset & 0xfffffff0), data);
421 }
write_pixel_32(offs_t offset,UINT32 data)422 static void write_pixel_32(offs_t offset, UINT32 data)
423 {
424 /* TODO: plane masking */
425 TMS34010_WRMEM_WORD(TOBYTE(offset & 0xffffffe0), data);
426 }
427
428 /* No Raster Op + Transparency */
write_pixel_t_1(offs_t offset,UINT32 data)429 static void write_pixel_t_1(offs_t offset, UINT32 data) { WP_T(0x0f, 0x01); }
write_pixel_t_2(offs_t offset,UINT32 data)430 static void write_pixel_t_2(offs_t offset, UINT32 data) { WP_T(0x0e, 0x03); }
write_pixel_t_4(offs_t offset,UINT32 data)431 static void write_pixel_t_4(offs_t offset, UINT32 data) { WP_T(0x0c, 0x0f); }
write_pixel_t_8(offs_t offset,UINT32 data)432 static void write_pixel_t_8(offs_t offset, UINT32 data) { WP_T(0x08, 0xff); }
write_pixel_t_16(offs_t offset,UINT32 data)433 static void write_pixel_t_16(offs_t offset, UINT32 data)
434 {
435 /* TODO: plane masking */
436 if (data)
437 TMS34010_WRMEM_WORD(TOBYTE(offset & 0xfffffff0), data);
438 }
write_pixel_t_32(offs_t offset,UINT32 data)439 static void write_pixel_t_32(offs_t offset, UINT32 data)
440 {
441 /* TODO: plane masking */
442 if (data)
443 TMS34010_WRMEM_DWORD(TOBYTE(offset & 0xffffffe0), data);
444 }
445
446 /* Raster Op + No Transparency */
write_pixel_r_1(offs_t offset,UINT32 data)447 static void write_pixel_r_1(offs_t offset, UINT32 data) { WP_R(0x0f, 0x01); }
write_pixel_r_2(offs_t offset,UINT32 data)448 static void write_pixel_r_2(offs_t offset, UINT32 data) { WP_R(0x0e, 0x03); }
write_pixel_r_4(offs_t offset,UINT32 data)449 static void write_pixel_r_4(offs_t offset, UINT32 data) { WP_R(0x0c, 0x0f); }
write_pixel_r_8(offs_t offset,UINT32 data)450 static void write_pixel_r_8(offs_t offset, UINT32 data) { WP_R(0x08, 0xff); }
write_pixel_r_16(offs_t offset,UINT32 data)451 static void write_pixel_r_16(offs_t offset, UINT32 data)
452 {
453 /* TODO: plane masking */
454 UINT32 a = TOBYTE(offset & 0xfffffff0);
455 TMS34010_WRMEM_WORD(a, state.raster_op(data, TMS34010_RDMEM_WORD(a)));
456 }
write_pixel_r_32(offs_t offset,UINT32 data)457 static void write_pixel_r_32(offs_t offset, UINT32 data)
458 {
459 /* TODO: plane masking */
460 UINT32 a = TOBYTE(offset & 0xffffffe0);
461 TMS34010_WRMEM_DWORD(a, state.raster_op(data, TMS34010_RDMEM_DWORD(a)));
462 }
463
464 /* Raster Op + Transparency */
write_pixel_r_t_1(offs_t offset,UINT32 data)465 static void write_pixel_r_t_1(offs_t offset, UINT32 data) { WP_R_T(0x0f,0x01); }
write_pixel_r_t_2(offs_t offset,UINT32 data)466 static void write_pixel_r_t_2(offs_t offset, UINT32 data) { WP_R_T(0x0e,0x03); }
write_pixel_r_t_4(offs_t offset,UINT32 data)467 static void write_pixel_r_t_4(offs_t offset, UINT32 data) { WP_R_T(0x0c,0x0f); }
write_pixel_r_t_8(offs_t offset,UINT32 data)468 static void write_pixel_r_t_8(offs_t offset, UINT32 data) { WP_R_T(0x08,0xff); }
write_pixel_r_t_16(offs_t offset,UINT32 data)469 static void write_pixel_r_t_16(offs_t offset, UINT32 data)
470 {
471 /* TODO: plane masking */
472 UINT32 a = TOBYTE(offset & 0xfffffff0);
473 data = state.raster_op(data, TMS34010_RDMEM_WORD(a));
474
475 if (data)
476 TMS34010_WRMEM_WORD(a, data);
477 }
write_pixel_r_t_32(offs_t offset,UINT32 data)478 static void write_pixel_r_t_32(offs_t offset, UINT32 data)
479 {
480 /* TODO: plane masking */
481 UINT32 a = TOBYTE(offset & 0xffffffe0);
482 data = state.raster_op(data, TMS34010_RDMEM_DWORD(a));
483
484 if (data)
485 TMS34010_WRMEM_DWORD(a, data);
486 }
487
488 /* Shift register write */
write_pixel_shiftreg(offs_t offset,UINT32 data)489 static void write_pixel_shiftreg(offs_t offset, UINT32 data)
490 {
491 if (state.config.from_shiftreg)
492 state.config.from_shiftreg(offset, &state.shiftreg[0]);
493 else
494 fatalerror("From ShiftReg function not set. PC = %08X\n", PC);
495 }
496
497
498
499 /***************************************************************************
500 RASTER OPS
501 ***************************************************************************/
502
503 /* Raster operations */
raster_op_1(UINT32 newpix,UINT32 oldpix)504 static UINT32 raster_op_1(UINT32 newpix, UINT32 oldpix) { return newpix & oldpix; }
raster_op_2(UINT32 newpix,UINT32 oldpix)505 static UINT32 raster_op_2(UINT32 newpix, UINT32 oldpix) { return newpix & ~oldpix; }
raster_op_3(UINT32 newpix,UINT32 oldpix)506 static UINT32 raster_op_3(UINT32 newpix, UINT32 oldpix) { return 0; }
raster_op_4(UINT32 newpix,UINT32 oldpix)507 static UINT32 raster_op_4(UINT32 newpix, UINT32 oldpix) { return newpix | ~oldpix; }
raster_op_5(UINT32 newpix,UINT32 oldpix)508 static UINT32 raster_op_5(UINT32 newpix, UINT32 oldpix) { return ~(newpix ^ oldpix); }
raster_op_6(UINT32 newpix,UINT32 oldpix)509 static UINT32 raster_op_6(UINT32 newpix, UINT32 oldpix) { return ~oldpix; }
raster_op_7(UINT32 newpix,UINT32 oldpix)510 static UINT32 raster_op_7(UINT32 newpix, UINT32 oldpix) { return ~(newpix | oldpix); }
raster_op_8(UINT32 newpix,UINT32 oldpix)511 static UINT32 raster_op_8(UINT32 newpix, UINT32 oldpix) { return newpix | oldpix; }
raster_op_9(UINT32 newpix,UINT32 oldpix)512 static UINT32 raster_op_9(UINT32 newpix, UINT32 oldpix) { return oldpix; }
raster_op_10(UINT32 newpix,UINT32 oldpix)513 static UINT32 raster_op_10(UINT32 newpix, UINT32 oldpix) { return newpix ^ oldpix; }
raster_op_11(UINT32 newpix,UINT32 oldpix)514 static UINT32 raster_op_11(UINT32 newpix, UINT32 oldpix) { return ~newpix & oldpix; }
raster_op_12(UINT32 newpix,UINT32 oldpix)515 static UINT32 raster_op_12(UINT32 newpix, UINT32 oldpix) { return 0xffff; }
raster_op_13(UINT32 newpix,UINT32 oldpix)516 static UINT32 raster_op_13(UINT32 newpix, UINT32 oldpix) { return ~newpix | oldpix; }
raster_op_14(UINT32 newpix,UINT32 oldpix)517 static UINT32 raster_op_14(UINT32 newpix, UINT32 oldpix) { return ~(newpix & oldpix); }
raster_op_15(UINT32 newpix,UINT32 oldpix)518 static UINT32 raster_op_15(UINT32 newpix, UINT32 oldpix) { return ~newpix; }
raster_op_16(UINT32 newpix,UINT32 oldpix)519 static UINT32 raster_op_16(UINT32 newpix, UINT32 oldpix) { return newpix + oldpix; }
raster_op_17(UINT32 newpix,UINT32 oldpix)520 static UINT32 raster_op_17(UINT32 newpix, UINT32 oldpix)
521 {
522 UINT32 max = (UINT32)0xffffffff >> (32 - IOREG(REG_PSIZE));
523 UINT32 res = newpix + oldpix;
524 return (res > max) ? max : res;
525 }
raster_op_18(UINT32 newpix,UINT32 oldpix)526 static UINT32 raster_op_18(UINT32 newpix, UINT32 oldpix) { return oldpix - newpix; }
raster_op_19(UINT32 newpix,UINT32 oldpix)527 static UINT32 raster_op_19(UINT32 newpix, UINT32 oldpix) { return (oldpix > newpix) ? oldpix - newpix : 0; }
raster_op_20(UINT32 newpix,UINT32 oldpix)528 static UINT32 raster_op_20(UINT32 newpix, UINT32 oldpix) { return (oldpix > newpix) ? oldpix : newpix; }
raster_op_21(UINT32 newpix,UINT32 oldpix)529 static UINT32 raster_op_21(UINT32 newpix, UINT32 oldpix) { return (oldpix > newpix) ? newpix : oldpix; }
530
531
532
533 /***************************************************************************
534 OPCODE TABLE & IMPLEMENTATIONS
535 ***************************************************************************/
536
537 /* includes the static function prototypes and the master opcode table */
538 #include "34010tbl.c"
539 #include "34010fld.c"
540
541 /* includes the actual opcode implementations */
542 #include "34010ops.c"
543 #include "34010gfx.c"
544
cpu_getactivecpu()545 static int cpu_getactivecpu()
546 {
547 return 0;
548 }
549
550 /***************************************************************************
551 Internal interrupt check
552 ****************************************************************************/
553
554 /* Generate pending interrupts. */
check_interrupt(void)555 static void check_interrupt(void)
556 {
557 int vector = 0;
558 int irqline = -1;
559 int irq;
560
561 /* check for NMI first */
562 if (IOREG(REG_HSTCTLH) & 0x0100)
563 {
564 LOG(("TMS34010#%d takes NMI\n", cpu_getactivecpu()));
565
566 /* ack the NMI */
567 IOREG(REG_HSTCTLH) &= ~0x0100;
568
569 /* handle NMI mode bit */
570 if (!(IOREG(REG_HSTCTLH) & 0x0200))
571 {
572 PUSH(PC);
573 PUSH(GET_ST());
574 }
575
576 /* leap to the vector */
577 RESET_ST();
578 PC = RLONG(0xfffffee0);
579 change_pc(TOBYTE(PC));
580 COUNT_CYCLES(16);
581 return;
582 }
583
584 /* early out if everything else is disabled */
585 irq = IOREG(REG_INTPEND) & IOREG(REG_INTENB);
586
587 //if (irq)
588 // bprintf(0, _T("check_interrupt(): %x IE_FLAG %x\n"), irq, IE_FLAG);
589
590 if (!IE_FLAG || !irq)
591 return;
592
593 /* host interrupt */
594 if (irq & TMS34010_HI)
595 {
596 LOG(("TMS34010#%d takes HI\n", cpu_getactivecpu()));
597 vector = 0xfffffec0;
598 }
599
600 /* display interrupt */
601 else if (irq & TMS34010_DI)
602 {
603 //bprintf(0, _T("TMS34010#%d takes DI\n"), cpu_getactivecpu());
604 vector = 0xfffffea0;
605 }
606
607 /* window violation interrupt */
608 else if (irq & TMS34010_WV)
609 {
610 LOG(("TMS34010#%d takes WV\n", cpu_getactivecpu()));
611 vector = 0xfffffe80;
612 }
613
614 /* external 1 interrupt */
615 else if (irq & TMS34010_INT1)
616 {
617 //bprintf(0, _T("TMS34 takes INT1 (irq0)\n"));
618 LOG(("TMS34010#%d takes INT1\n", cpu_getactivecpu()));
619 vector = 0xffffffc0;
620 irqline = 0;
621 }
622
623 /* external 2 interrupt */
624 else if (irq & TMS34010_INT2)
625 {
626 LOG(("TMS34010#%d takes INT2\n", cpu_getactivecpu()));
627 vector = 0xffffffa0;
628 irqline = 1;
629 }
630
631 /* if we took something, generate it */
632 if (vector)
633 {
634 PUSH(PC);
635 PUSH(GET_ST());
636 RESET_ST();
637 PC = RLONG(vector);
638 change_pc(TOBYTE(PC));
639 COUNT_CYCLES(16);
640
641 // irq hold function
642 if (irqline >= 0 && state.irqhold[irqline]) {
643 tms34010_set_irq_line(irqline, 0);
644 state.irqhold[irqline] = 0;
645 }
646 }
647 }
648
649
650
651 /***************************************************************************
652 Reset the CPU emulation
653 ***************************************************************************/
tms34010_init()654 void tms34010_init()
655 {
656 memset(&state, 0, sizeof(state));
657
658 state.shiftreg = (UINT16*)BurnMalloc(SHIFTREG_SIZE);
659 }
660
tms34010_set_cycperframe(INT32 cpf)661 void tms34010_set_cycperframe(INT32 cpf)
662 {
663 state.config.cpu_cyc_per_frame = cpf;
664 }
665
tms34010_set_pixclock(INT32 pxlclock,INT32 pxl_per_clock)666 void tms34010_set_pixclock(INT32 pxlclock, INT32 pxl_per_clock)
667 {
668 state.config.pixclock = pxlclock;
669 state.config.pixperclock = pxl_per_clock;
670 }
671
tms34010_set_output_int(void (* oi_func)(INT32))672 void tms34010_set_output_int(void (*oi_func)(INT32))
673 {
674 state.config.output_int = oi_func;
675 }
676
tms34010_set_halt_on_reset(INT32 onoff)677 void tms34010_set_halt_on_reset(INT32 onoff)
678 {
679 state.config.halt_on_reset = onoff;
680 }
681
tms34010_set_toshift(void (* to_shiftreg)(UINT32,UINT16 *))682 void tms34010_set_toshift(void (*to_shiftreg)(UINT32, UINT16 *))
683 {
684 state.config.to_shiftreg = to_shiftreg;
685 }
686
tms34010_set_fromshift(void (* from_shiftreg)(UINT32,UINT16 *))687 void tms34010_set_fromshift(void (*from_shiftreg)(UINT32, UINT16 *))
688 {
689 state.config.from_shiftreg = from_shiftreg;
690 }
691
tms34010_exit()692 void tms34010_exit()
693 {
694 if (state.shiftreg) {
695 BurnFree(state.shiftreg);
696 }
697 }
698
tms34010_reset()699 void tms34010_reset()
700 {
701 /* clear the state & leave the config section alone */
702 memset(&state, 0, STRUCT_SIZE_HELPER(struct tms34010_regs, pointer_separator));
703
704 /* fetch the initial PC and reset the state */
705 PC = RLONG(0xffffffe0) & 0xfffffff0;
706 change_pc(TOBYTE(PC));
707 RESET_ST();
708
709 /* HALT the CPU if requested, and remember to re-read the starting PC */
710 /* the first time we are run */
711 state.reset_deferred = state.config.halt_on_reset;
712 if (state.config.halt_on_reset)
713 tms34010_io_register_w(REG_HSTCTLH << 4, 0x8000);
714
715 state.timer_active = 0;
716 state.timer_cyc = 0;
717 }
718
719 #if (HAS_TMS34020)
tms34020_reset()720 void tms34020_reset()
721 {
722 tms34010_reset();
723 state.is_34020 = 1;
724 }
725 #endif
726
tms34010_scan(INT32 nAction)727 void tms34010_scan(INT32 nAction)
728 {
729 if (nAction & ACB_DRIVER_DATA) {
730 ScanVar(&state, STRUCT_SIZE_HELPER(struct tms34010_regs, pointer_separator), "TMS340x0 Struct");
731 ScanVar(state.shiftreg, SHIFTREG_SIZE, "TMS340x0 Shiftreg");
732 }
733
734 if (nAction & ACB_WRITE) { // load state
735 change_pc(TOBYTE(PC));
736 set_raster_op();
737 set_pixel_function();
738 }
739 }
740
check_timer(int cyc)741 static void check_timer(int cyc)
742 {
743 if (state.timer_active) {
744 state.timer_cyc -= cyc;
745 if (state.timer_cyc <= 0) {
746 //bprintf(0, _T("timer hit @ %I64d\n"), TMS34010TotalCycles());
747 state.timer_active = 0;
748 state.timer_cyc = 0;
749
750 if (state.timer_cb) {
751 state.timer_cb();
752 } else {
753 bprintf(0, _T("no timer cb!\n"));
754 }
755 }
756 }
757 }
758
tms34010_timer_set_cb(void (* t_cb)())759 void tms34010_timer_set_cb(void (*t_cb)())
760 {
761 state.timer_cb = t_cb;
762 }
763
tms34010_timer_arm(int cycle)764 void tms34010_timer_arm(int cycle)
765 {
766 //bprintf(0, _T("timer arm @ %d time now %I64d\n"), cycle, TMS34010TotalCycles());
767 if (state.timer_active) {
768 bprintf(0, _T("TMS34010: timer_arm() arm timer when timer pending!\n"));
769 }
770 state.timer_active = 1;
771 state.timer_cyc = cycle;
772 }
773
774
775 /***************************************************************************
776 Set IRQ line state
777 ***************************************************************************/
778
tms34010_set_irq_line(int irqline,int linestate)779 void tms34010_set_irq_line(int irqline, int linestate)
780 {
781 //bprintf(0, _T("TMS34010 set irq %x state %x\n"), irqline, linestate);
782 /* set the pending interrupt */
783
784 switch (irqline)
785 {
786 case 0:
787 if (linestate != CLEAR_LINE) {
788 IOREG(REG_INTPEND) |= TMS34010_INT1;
789
790 if (linestate == CPU_IRQSTATUS_HOLD) {
791 state.irqhold[0] = 1;
792 }
793 } else {
794 IOREG(REG_INTPEND) &= ~TMS34010_INT1;
795 }
796 break;
797
798 case 1:
799 if (linestate != CLEAR_LINE) {
800 IOREG(REG_INTPEND) |= TMS34010_INT2;
801
802 if (linestate == CPU_IRQSTATUS_HOLD) {
803 state.irqhold[1] = 1;
804 }
805 } else {
806 IOREG(REG_INTPEND) &= ~TMS34010_INT2;
807 }
808 break;
809 }
810 }
811
812
813
814 /***************************************************************************
815 Generate internal interrupt
816 ***************************************************************************/
817
internal_interrupt_callback(INT32 type)818 static void internal_interrupt_callback(INT32 type)
819 {
820 //bprintf(0, _T("TMS34010#%d set internal interrupt $%04x\n"), cpu_getactivecpu(), type);
821 IOREG(REG_INTPEND) |= type;
822 }
823
824
825
826 /***************************************************************************
827 Execute
828 ***************************************************************************/
829
tms34010_run(int cycles)830 int tms34010_run(int cycles)
831 {
832 /* Get out if CPU is halted. Absolutely no interrupts must be taken!!! */
833 if (IOREG(REG_HSTCTLH) & 0x8000)
834 return cycles;
835
836 /* if the CPU's reset was deferred, do it now */
837 if (state.reset_deferred)
838 {
839 state.reset_deferred = 0;
840 PC = RLONG(0xffffffe0);
841 }
842
843 /* execute starting now */
844 state.cycles_start = cycles;
845 tms34010_ICount = cycles;
846 state.stop = 0;
847
848 change_pc(TOBYTE(PC));
849
850 /* check interrupts first */
851 check_timer(0);
852 do
853 {
854 check_interrupt();
855 state.op = ROPCODE();
856 (*opcode_table[state.op >> 4])();
857
858 } while (tms34010_ICount > 0 && !state.stop);
859
860 cycles = cycles - tms34010_ICount;
861 state.total_cycles += cycles;
862
863 state.cycles_start = 0;
864 tms34010_ICount = 0;
865
866 return cycles;
867 }
868
tms34010_stop()869 void tms34010_stop()
870 {
871 state.stop = 1;
872 }
873
tms34010_modify_timeslice(int cycles)874 void tms34010_modify_timeslice(int cycles)
875 { // only call this from a read/write handler while cpu is running!
876 tms34010_ICount += cycles;
877 }
878
tms34010_idle(int cycles)879 int tms34010_idle(int cycles)
880 {
881 state.total_cycles += cycles;
882
883 return cycles;
884 }
885
tms34010_total_cycles()886 INT64 tms34010_total_cycles()
887 {
888 return state.total_cycles + (state.cycles_start - tms34010_ICount);
889 }
890
tms34010_new_frame()891 void tms34010_new_frame()
892 {
893 state.total_cycles = 0;
894 }
895
tms34010_get_pc()896 UINT32 tms34010_get_pc()
897 {
898 return state.pc;
899 }
900
901
902
903 /***************************************************************************
904 PIXEL OPS
905 ***************************************************************************/
906
907 static void (*const pixel_write_ops[4][6])(offs_t offset, UINT32 data) =
908 {
909 { write_pixel_1, write_pixel_2, write_pixel_4, write_pixel_8, write_pixel_16, write_pixel_32 },
910 { write_pixel_r_1, write_pixel_r_2, write_pixel_r_4, write_pixel_r_8, write_pixel_r_16, write_pixel_r_32 },
911 { write_pixel_t_1, write_pixel_t_2, write_pixel_t_4, write_pixel_t_8, write_pixel_t_16, write_pixel_t_32 },
912 { 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, write_pixel_r_t_32 }
913 };
914
915 static UINT32 (*const pixel_read_ops[6])(offs_t offset) =
916 {
917 read_pixel_1, read_pixel_2, read_pixel_4, read_pixel_8, read_pixel_16, read_pixel_32
918 };
919
920
set_pixel_function(void)921 static void set_pixel_function(void)
922 {
923 UINT32 i1,i2;
924
925 if (IOREG(REG_DPYCTL) & 0x0800)
926 {
927 /* Shift Register Transfer */
928 state.pixel_write = write_pixel_shiftreg;
929 state.pixel_read = read_pixel_shiftreg;
930 return;
931 }
932
933 switch (IOREG(REG_PSIZE))
934 {
935 default:
936 case 0x01: i2 = 0; break;
937 case 0x02: i2 = 1; break;
938 case 0x04: i2 = 2; break;
939 case 0x08: i2 = 3; break;
940 case 0x10: i2 = 4; break;
941 case 0x20: i2 = 5; break;
942 }
943
944 if (IOREG(REG_CONTROL) & 0x20)
945 i1 = state.raster_op ? 3 : 2;
946 else
947 i1 = state.raster_op ? 1 : 0;
948
949 state.pixel_write = pixel_write_ops[i1][i2];
950 state.pixel_read = pixel_read_ops [i2];
951 }
952
953
954
955 /***************************************************************************
956 RASTER OPS
957 ***************************************************************************/
958
959 static UINT32 (*const raster_ops[32]) (UINT32 newpix, UINT32 oldpix) =
960 {
961 0, raster_op_1 , raster_op_2 , raster_op_3,
962 raster_op_4 , raster_op_5 , raster_op_6 , raster_op_7,
963 raster_op_8 , raster_op_9 , raster_op_10, raster_op_11,
964 raster_op_12, raster_op_13, raster_op_14, raster_op_15,
965 raster_op_16, raster_op_17, raster_op_18, raster_op_19,
966 raster_op_20, raster_op_21, 0, 0,
967 0, 0, 0, 0,
968 0, 0, 0, 0,
969 };
970
971
set_raster_op(void)972 static void set_raster_op(void)
973 {
974 state.raster_op = raster_ops[(IOREG(REG_CONTROL) >> 10) & 0x1f];
975 }
976
977
978
979 /***************************************************************************
980 VIDEO TIMING HELPERS
981 ***************************************************************************/
982
tms34010_generate_scanline(INT32 line,scanline_render_t render)983 void tms34010_generate_scanline(INT32 line, scanline_render_t render)
984 {
985 int vsblnk, veblnk, vtotal;
986 int vcount = line;
987 int enabled;
988 int master;
989
990 /* fetch the core timing parameters */
991 enabled = SMART_IOREG(DPYCTL) & 0x8000;
992 master = (state.is_34020 || (SMART_IOREG(DPYCTL) & 0x2000));
993 vsblnk = SMART_IOREG(VSBLNK);
994 veblnk = SMART_IOREG(VEBLNK);
995 vtotal = SMART_IOREG(VTOTAL);
996
997 #if 0 // for driver debug -dink
998 if (line == 1) {
999 bprintf(0, _T("vsblnk %x\n"), vsblnk);
1000 bprintf(0, _T("veblnk %x\n"), veblnk);
1001 bprintf(0, _T("vtotal %x\n"), vtotal);
1002 bprintf(0, _T("enabled: %x master %x\n"), enabled, master);
1003 }
1004 #endif
1005
1006 if (!master)
1007 {
1008 vtotal = MIN(nScreenHeight - 1, vtotal);
1009 vcount = line;
1010 }
1011
1012 /* update the VCOUNT */
1013 SMART_IOREG(VCOUNT) = vcount;
1014
1015 /* if we match the display interrupt scanline, signal an interrupt */
1016 if (enabled && vcount == SMART_IOREG(DPYINT))
1017 {
1018 /* generate the display interrupt signal */
1019 internal_interrupt_callback(TMS34010_DI);
1020 }
1021
1022 /* at the start of VBLANK, load the starting display address */
1023 if (vcount == vsblnk)
1024 {
1025 /* 34010 loads DPYADR with DPYSTRT, and inverts if the origin is 0 */
1026 if (!state.is_34020)
1027 {
1028 IOREG(REG_DPYADR) = IOREG(REG_DPYSTRT);
1029 LOG(("Start of VBLANK, DPYADR = %04X\n", IOREG(REG_DPYADR)));
1030 }
1031
1032 /* 34020 loads DPYNXx with DPYSTx */
1033 else
1034 {
1035 IOREG(REG020_DPYNXL) = IOREG(REG020_DPYSTL) & 0xffe0;
1036 IOREG(REG020_DPYNXH) = IOREG(REG020_DPYSTH);
1037 }
1038 }
1039
1040 /* at the end of the screen, update the display parameters */
1041 #if 0
1042 if (vcount == vtotal)
1043 {
1044 /* only do this if we have an incoming pixel clock */
1045 /* also, only do it if the HEBLNK/HSBLNK values are stable */
1046 if (master && state.config.scanline_callback != NULL)
1047 {
1048 int htotal = SMART_IOREG(HTOTAL);
1049 if (htotal > 0 && vtotal > 0)
1050 {
1051 attoseconds_t refresh = HZ_TO_ATTOSECONDS(state.config.pixclock) * (htotal + 1) * (vtotal + 1);
1052 int width = (htotal + 1) * state.config.pixperclock;
1053 int height = vtotal + 1;
1054 rectangle visarea;
1055
1056 /* extract the visible area */
1057 visarea.min_x = SMART_IOREG(HEBLNK) * state.config.pixperclock;
1058 visarea.max_x = SMART_IOREG(HSBLNK) * state.config.pixperclock - 1;
1059 visarea.min_y = veblnk;
1060 visarea.max_y = vsblnk - 1;
1061
1062 /* if everything looks good, set the info */
1063 if (visarea.min_x < visarea.max_x && visarea.max_x <= width && visarea.min_y < visarea.max_y && visarea.max_y <= height)
1064 {
1065 /* because many games play with the HEBLNK/HSBLNK for effects, we don't change
1066 if they are the only thing that has changed, unless they are stable for a couple
1067 of frames */
1068 int current_width = video_screen_get_width(state.screen);
1069 int current_height = video_screen_get_height(state.screen);
1070
1071 if (width != current_width || height != current_height || visarea.min_y != current_visarea->min_y || visarea.max_y != current_visarea->max_y ||
1072 (state.hblank_stable > 2 && (visarea.min_x != current_visarea->min_x || visarea.max_x != current_visarea->max_x)))
1073 {
1074 video_screen_configure(state.screen, width, height, &visarea, refresh);
1075 }
1076 state.hblank_stable++;
1077 }
1078
1079 LOG(("Configuring screen: HTOTAL=%3d BLANK=%3d-%3d VTOTAL=%3d BLANK=%3d-%3d refresh=%f\n",
1080 htotal, SMART_IOREG(HEBLNK), SMART_IOREG(HSBLNK), vtotal, veblnk, vsblnk, ATTOSECONDS_TO_HZ(refresh)));
1081
1082 /* interlaced timing not supported */
1083 if ((SMART_IOREG(DPYCTL) & 0x4000) == 0)
1084 fatalerror("Interlaced video configured on the TMS34010 (unsupported)");
1085 }
1086 }
1087 }
1088 #endif
1089
1090 if (vcount >= 0 && vcount <= vsblnk) {
1091 tms34010_display_params params;
1092
1093 tms34010_get_display_params(¶ms);
1094
1095 // screen update callback - clipping is done in the driver -dink
1096 if (render) {
1097 render(line, ¶ms);
1098 }
1099 }
1100
1101 /* if we are in the visible area, increment DPYADR by DUDATE */
1102 if (vcount >= veblnk && vcount < vsblnk)
1103 {
1104 /* 34010 increments by the DUDATE field in DPYCTL */
1105 if (!state.is_34020)
1106 {
1107 UINT16 dpyadr = IOREG(REG_DPYADR);
1108 if ((dpyadr & 3) == 0)
1109 dpyadr = ((dpyadr & 0xfffc) - (IOREG(REG_DPYCTL) & 0x03fc)) | (IOREG(REG_DPYSTRT) & 0x0003);
1110 else
1111 dpyadr = (dpyadr & 0xfffc) | ((dpyadr - 1) & 3);
1112 IOREG(REG_DPYADR) = dpyadr;
1113 }
1114
1115 /* 34020 updates based on the DINC register, including zoom */
1116 else
1117 {
1118 UINT32 dpynx = IOREG(REG020_DPYNXL) | (IOREG(REG020_DPYNXH) << 16);
1119 UINT32 dinc = IOREG(REG020_DINCL) | (IOREG(REG020_DINCH) << 16);
1120 dpynx = (dpynx & 0xffffffe0) | ((dpynx + dinc) & 0x1f);
1121 if ((dpynx & 0x1f) == 0)
1122 dpynx += dinc & 0xffffffe0;
1123 IOREG(REG020_DPYNXL) = dpynx;
1124 IOREG(REG020_DPYNXH) = dpynx >> 16;
1125 }
1126 }
1127
1128 /* adjust for the next callback */
1129 vcount++;
1130 if (vcount > vtotal)
1131 vcount = 0;
1132
1133 /* note that we add !master (0 or 1) as a attoseconds value; this makes no practical difference */
1134 /* but helps ensure that masters are updated first before slaves */
1135 //timer_adjust_oneshot(state.scantimer, attotime_add_attoseconds(video_screen_get_time_until_pos(state.screen, vcount, 0), !master), cpunum | (vcount << 8));
1136 }
1137
1138
tms34010_get_display_params(tms34010_display_params * params)1139 void tms34010_get_display_params(tms34010_display_params *params)
1140 {
1141 params->enabled = ((SMART_IOREG(DPYCTL) & 0x8000) != 0);
1142 params->vcount = SMART_IOREG(VCOUNT);
1143 params->veblnk = SMART_IOREG(VEBLNK);
1144 params->vsblnk = SMART_IOREG(VSBLNK);
1145 params->heblnk = SMART_IOREG(HEBLNK) * state.config.pixperclock;
1146 params->hsblnk = SMART_IOREG(HSBLNK) * state.config.pixperclock;
1147
1148 params->htotal = SMART_IOREG(HTOTAL);
1149 params->vtotal = SMART_IOREG(VTOTAL);
1150
1151 /* 34010 gets its address from DPYADR and DPYTAP */
1152 if (!state.is_34020)
1153 {
1154 UINT16 dpyadr = IOREG(REG_DPYADR);
1155 if (!(IOREG(REG_DPYCTL) & 0x0400))
1156 dpyadr ^= 0xfffc;
1157 params->rowaddr = dpyadr >> 4;
1158 params->coladdr = ((dpyadr & 0x007c) << 4) | (IOREG(REG_DPYTAP) & 0x3fff);
1159 params->yoffset = (IOREG(REG_DPYSTRT) - IOREG(REG_DPYADR)) & 3;
1160 }
1161
1162 /* 34020 gets its address from DPYNX */
1163 else
1164 {
1165 params->rowaddr = IOREG(REG020_DPYNXH);
1166 params->coladdr = IOREG(REG020_DPYNXL) & 0xffe0;
1167 params->yoffset = 0;
1168 if ((IOREG(REG020_DINCL) & 0x1f) != 0)
1169 params->yoffset = (IOREG(REG020_DPYNXL) & 0x1f) / (IOREG(REG020_DINCL) & 0x1f);
1170 }
1171 }
1172
1173 #if 0
1174 VIDEO_UPDATE( tms340x0 )
1175 {
1176 pen_t blackpen = get_black_pen(screen->machine);
1177 tms34010_display_params params;
1178 int cpunum = -1;
1179 int x;
1180
1181 /* find the owning CPU */
1182 for (cpunum = 0; cpunum < MAX_CPU; cpunum++)
1183 if (screen_to_cpu[cpunum] == screen)
1184 break;
1185
1186 assert(cpunum >= 0);
1187
1188 /* get the display parameters for the screen */
1189 tms34010_get_display_params(cpunum, ¶ms);
1190
1191 /* if the display is enabled, call the scanline callback */
1192 if (params.enabled)
1193 {
1194 /* call through to the callback */
1195 LOG((" Update: scan=%3d ROW=%04X COL=%04X\n", cliprect->min_y, params.rowaddr, params.coladdr));
1196 (*state.config.scanline_callback)(screen, bitmap, cliprect->min_y, ¶ms);
1197 }
1198
1199 /* otherwise, just blank the current scanline */
1200 else
1201 params.heblnk = params.hsblnk = cliprect->max_x + 1;
1202
1203 /* blank out the blank regions */
1204 if (bitmap->bpp == 16)
1205 {
1206 UINT16 *dest = BITMAP_ADDR16(bitmap, cliprect->min_y, 0);
1207 for (x = cliprect->min_x; x < params.heblnk; x++)
1208 dest[x] = blackpen;
1209 for (x = params.hsblnk; x <= cliprect->max_y; x++)
1210 dest[x] = blackpen;
1211 }
1212 else if (bitmap->bpp == 32)
1213 {
1214 UINT32 *dest = BITMAP_ADDR32(bitmap, cliprect->min_y, 0);
1215 for (x = cliprect->min_x; x < params.heblnk; x++)
1216 dest[x] = blackpen;
1217 for (x = params.hsblnk; x <= cliprect->max_y; x++)
1218 dest[x] = blackpen;
1219 }
1220 return 0;
1221 }
1222 #endif
1223
1224 /***************************************************************************
1225 I/O REGISTER WRITES
1226 ***************************************************************************/
1227
1228 static const char *const ioreg_name[] =
1229 {
1230 "HESYNC", "HEBLNK", "HSBLNK", "HTOTAL",
1231 "VESYNC", "VEBLNK", "VSBLNK", "VTOTAL",
1232 "DPYCTL", "DPYSTART", "DPYINT", "CONTROL",
1233 "HSTDATA", "HSTADRL", "HSTADRH", "HSTCTLL",
1234
1235 "HSTCTLH", "INTENB", "INTPEND", "CONVSP",
1236 "CONVDP", "PSIZE", "PMASK", "RESERVED",
1237 "RESERVED", "RESERVED", "RESERVED", "DPYTAP",
1238 "HCOUNT", "VCOUNT", "DPYADR", "REFCNT"
1239 };
1240
tms34010_io_register_w(INT32 address,UINT32 data)1241 void tms34010_io_register_w(INT32 address, UINT32 data)
1242 {
1243 int oldreg, newreg;
1244 INT32 offset = (address >> 4) & 0x1f;
1245 //bprintf(0, _T("tms34_io_w %x %S -> %x\n"), address, ioreg_name[offset], data);
1246
1247 /* Set register */
1248 oldreg = IOREG(offset);
1249 IOREG(offset) = data;
1250
1251 switch (offset)
1252 {
1253 case REG_CONTROL:
1254 set_raster_op();
1255 set_pixel_function();
1256 break;
1257
1258 case REG_PSIZE:
1259 set_pixel_function();
1260
1261 switch (data)
1262 {
1263 default:
1264 case 0x01: state.pixelshift = 0; break;
1265 case 0x02: state.pixelshift = 1; break;
1266 case 0x04: state.pixelshift = 2; break;
1267 case 0x08: state.pixelshift = 3; break;
1268 case 0x10: state.pixelshift = 4; break;
1269 }
1270 break;
1271
1272 case REG_PMASK:
1273 //if (data) logerror("Plane masking not supported. PC=%08X\n", activecpu_get_pc());
1274 break;
1275
1276 case REG_DPYCTL:
1277 set_pixel_function();
1278 break;
1279
1280 case REG_HSTCTLH:
1281 /* if the CPU is halting itself, stop execution right away */
1282 if ((data & 0x8000) && !state.external_host_access)
1283 tms34010_ICount = 0;
1284 //cpunum_set_input_line(state.screen->machine, cpunum, INPUT_LINE_HALT, (data & 0x8000) ? ASSERT_LINE : CLEAR_LINE);
1285
1286 /* NMI issued? */
1287 if (data & 0x0100) {
1288 //bprintf(0, _T("NMI issued?\n"));
1289 }
1290 break;
1291
1292 case REG_HSTCTLL:
1293 /* the TMS34010 can change MSGOUT, can set INTOUT, and can clear INTIN */
1294 if (!state.external_host_access)
1295 {
1296 newreg = (oldreg & 0xff8f) | (data & 0x0070);
1297 newreg |= data & 0x0080;
1298 newreg &= data | ~0x0008;
1299 }
1300
1301 /* the host can change MSGIN, can set INTIN, and can clear INTOUT */
1302 else
1303 {
1304 newreg = (oldreg & 0xfff8) | (data & 0x0007);
1305 newreg &= data | ~0x0080;
1306 newreg |= data & 0x0008;
1307 }
1308 IOREG(offset) = newreg;
1309
1310 /* the TMS34010 can set output interrupt? */
1311 if (!(oldreg & 0x0080) && (newreg & 0x0080))
1312 {
1313 if (state.config.output_int)
1314 (*state.config.output_int)(1);
1315 }
1316 else if ((oldreg & 0x0080) && !(newreg & 0x0080))
1317 {
1318 if (state.config.output_int)
1319 (*state.config.output_int)(0);
1320 }
1321
1322 /* input interrupt? (should really be state-based, but the functions don't exist!) */
1323 if (!(oldreg & 0x0008) && (newreg & 0x0008))
1324 internal_interrupt_callback(TMS34010_HI);
1325 else if ((oldreg & 0x0008) && !(newreg & 0x0008))
1326 IOREG(REG_INTPEND) &= ~TMS34010_HI;
1327 break;
1328
1329 case REG_CONVSP:
1330 state.convsp = 1 << (~data & 0x1f);
1331 break;
1332
1333 case REG_CONVDP:
1334 state.convdp = 1 << (~data & 0x1f);
1335 break;
1336
1337 case REG_INTENB:
1338 check_interrupt();
1339 break;
1340
1341 case REG_INTPEND:
1342 /* X1P, X2P and HIP are read-only */
1343 /* WVP and DIP can only have 0's written to them */
1344 IOREG(REG_INTPEND) = oldreg;
1345 if (!(data & TMS34010_WV))
1346 IOREG(REG_INTPEND) &= ~TMS34010_WV;
1347 if (!(data & TMS34010_DI))
1348 IOREG(REG_INTPEND) &= ~TMS34010_DI;
1349 break;
1350
1351 case REG_HEBLNK:
1352 case REG_HSBLNK:
1353 if (oldreg != data)
1354 state.hblank_stable = 0;
1355 break;
1356 }
1357
1358 //if (LOG_CONTROL_REGS)
1359 // logerror("CPU#%d@%08X: %s = %04X (%d)\n", cpunum, activecpu_get_pc(), ioreg_name[offset], IOREG(offset), video_screen_get_vpos(state.screen));
1360 }
1361
1362
1363 static const char *const ioreg020_name[] =
1364 {
1365 "VESYNC", "HESYNC", "VEBLNK", "HEBLNK",
1366 "VSBLNK", "HSBLNK", "VTOTAL", "HTOTAL",
1367 "DPYCTL", "DPYSTRT", "DPYINT", "CONTROL",
1368 "HSTDATA", "HSTADRL", "HSTADRH", "HSTCTLL",
1369
1370 "HSTCTLH", "INTENB", "INTPEND", "CONVSP",
1371 "CONVDP", "PSIZE", "PMASKL", "PMASKH",
1372 "CONVMP", "CONTROL2", "CONFIG", "DPYTAP",
1373 "VCOUNT", "HCOUNT", "DPYADR", "REFADR",
1374
1375 "DPYSTL", "DPYSTH", "DPYNXL", "DPYNXH",
1376 "DINCL", "DINCH", "RES0", "HESERR",
1377 "RES1", "RES2", "RES3", "RES4",
1378 "SCOUNT", "BSFLTST", "DPYMSK", "RES5",
1379
1380 "SETVCNT", "SETHCNT", "BSFLTDL", "BSFLTDH",
1381 "RES6", "RES7", "RES8", "RES9",
1382 "IHOST1L", "IHOST1H", "IHOST2L", "IHOST2H",
1383 "IHOST3L", "IHOST3H", "IHOST4L", "IHOST4H"
1384 };
1385
tms34020_io_register_w(INT32 address,UINT32 data)1386 void tms34020_io_register_w(INT32 address, UINT32 data)
1387 {
1388 int oldreg, newreg;
1389
1390 INT32 offset = (address >> 4) & 0x3f;
1391
1392 /* Set register */
1393 oldreg = IOREG(offset);
1394 IOREG(offset) = data;
1395
1396 //if (LOG_CONTROL_REGS)
1397 // logerror("CPU#%d@%08X: %s = %04X (%d)\n", cpunum, activecpu_get_pc(), ioreg020_name[offset], IOREG(offset), video_screen_get_vpos(state.screen));
1398
1399 switch (offset)
1400 {
1401 case REG020_CONTROL:
1402 case REG020_CONTROL2:
1403 IOREG(REG020_CONTROL) = data;
1404 IOREG(REG020_CONTROL2) = data;
1405 set_raster_op();
1406 set_pixel_function();
1407 break;
1408
1409 case REG020_PSIZE:
1410 set_pixel_function();
1411
1412 switch (data)
1413 {
1414 default:
1415 case 0x01: state.pixelshift = 0; break;
1416 case 0x02: state.pixelshift = 1; break;
1417 case 0x04: state.pixelshift = 2; break;
1418 case 0x08: state.pixelshift = 3; break;
1419 case 0x10: state.pixelshift = 4; break;
1420 case 0x20: state.pixelshift = 5; break;
1421 }
1422 break;
1423
1424 case REG020_PMASKL:
1425 case REG020_PMASKH:
1426 //if (data) logerror("Plane masking not supported. PC=%08X\n", activecpu_get_pc());
1427 break;
1428
1429 case REG020_DPYCTL:
1430 set_pixel_function();
1431 break;
1432
1433 case REG020_HSTCTLH:
1434 /* if the CPU is halting itself, stop execution right away */
1435 if ((data & 0x8000) && !state.external_host_access)
1436 tms34010_ICount = 0;
1437 //cpunum_set_input_line(state.screen->machine, cpunum, INPUT_LINE_HALT, (data & 0x8000) ? ASSERT_LINE : CLEAR_LINE);
1438
1439 /* NMI issued? */
1440 //if (data & 0x0100)
1441 // internal_interrupt_callback();
1442 break;
1443
1444 case REG020_HSTCTLL:
1445 /* the TMS34010 can change MSGOUT, can set INTOUT, and can clear INTIN */
1446 if (!state.external_host_access)
1447 {
1448 newreg = (oldreg & 0xff8f) | (data & 0x0070);
1449 newreg |= data & 0x0080;
1450 newreg &= data | ~0x0008;
1451 }
1452
1453 /* the host can change MSGIN, can set INTIN, and can clear INTOUT */
1454 else
1455 {
1456 newreg = (oldreg & 0xfff8) | (data & 0x0007);
1457 newreg &= data | ~0x0080;
1458 newreg |= data & 0x0008;
1459 }
1460 IOREG(offset) = newreg;
1461
1462 /* the TMS34010 can set output interrupt? */
1463 if (!(oldreg & 0x0080) && (newreg & 0x0080))
1464 {
1465 if (state.config.output_int)
1466 (*state.config.output_int)(1);
1467 }
1468 else if ((oldreg & 0x0080) && !(newreg & 0x0080))
1469 {
1470 if (state.config.output_int)
1471 (*state.config.output_int)(0);
1472 }
1473
1474 /* input interrupt? (should really be state-based, but the functions don't exist!) */
1475 if (!(oldreg & 0x0008) && (newreg & 0x0008))
1476 internal_interrupt_callback(TMS34010_HI);
1477 else if ((oldreg & 0x0008) && !(newreg & 0x0008))
1478 IOREG(REG020_INTPEND) &= ~TMS34010_HI;
1479 break;
1480
1481 case REG020_INTENB:
1482 check_interrupt();
1483 break;
1484
1485 case REG020_INTPEND:
1486 /* X1P, X2P and HIP are read-only */
1487 /* WVP and DIP can only have 0's written to them */
1488 IOREG(REG020_INTPEND) = oldreg;
1489 if (!(data & TMS34010_WV))
1490 IOREG(REG020_INTPEND) &= ~TMS34010_WV;
1491 if (!(data & TMS34010_DI))
1492 IOREG(REG020_INTPEND) &= ~TMS34010_DI;
1493 break;
1494
1495 case REG020_CONVSP:
1496 if (data & 0x001f)
1497 {
1498 if (data & 0x1f00)
1499 state.convsp = (1 << (~data & 0x1f)) + (1 << (~(data >> 8) & 0x1f));
1500 else
1501 state.convsp = 1 << (~data & 0x1f);
1502 }
1503 else
1504 state.convsp = data;
1505 break;
1506
1507 case REG020_CONVDP:
1508 if (data & 0x001f)
1509 {
1510 if (data & 0x1f00)
1511 state.convdp = (1 << (~data & 0x1f)) + (1 << (~(data >> 8) & 0x1f));
1512 else
1513 state.convdp = 1 << (~data & 0x1f);
1514 }
1515 else
1516 state.convdp = data;
1517 break;
1518
1519 case REG020_CONVMP:
1520 if (data & 0x001f)
1521 {
1522 if (data & 0x1f00)
1523 state.convmp = (1 << (~data & 0x1f)) + (1 << (~(data >> 8) & 0x1f));
1524 else
1525 state.convmp = 1 << (~data & 0x1f);
1526 }
1527 else
1528 state.convmp = data;
1529 break;
1530
1531 case REG020_DPYSTRT:
1532 case REG020_DPYADR:
1533 case REG020_DPYTAP:
1534 break;
1535
1536 case REG020_HEBLNK:
1537 case REG020_HSBLNK:
1538 if (oldreg != data)
1539 state.hblank_stable = 0;
1540 break;
1541 }
1542 }
1543
1544
1545
1546 /***************************************************************************
1547 I/O REGISTER READS
1548 ***************************************************************************/
1549
tms34010_io_register_r(INT32 address)1550 UINT16 tms34010_io_register_r(INT32 address)
1551 {
1552 int result, total, cyc_per_line;
1553 INT32 offset = (address >> 4) & 0x1f;
1554
1555 //bprintf(0, _T("tms34_io_r %x %S rv: 0x%X (%d)\n"), offset, ioreg_name[offset], IOREG(offset), IOREG(offset));
1556
1557 //if (LOG_CONTROL_REGS)
1558 // logerror("CPU#%d@%08X: read %s\n", cpunum, activecpu_get_pc(), ioreg_name[offset]);
1559
1560 switch (offset)
1561 {
1562 case REG_HCOUNT:
1563 /* scale the horizontal position from screen width to HTOTAL */
1564 cyc_per_line = state.config.cpu_cyc_per_frame / IOREG(REG_VTOTAL);
1565 result = TMS34010TotalCycles() % cyc_per_line;
1566 total = IOREG(REG_HTOTAL) + 1;
1567 result = result * total / cyc_per_line;
1568
1569 /* offset by the HBLANK end */
1570 result += IOREG(REG_HEBLNK);
1571
1572 /* wrap around */
1573 if (result > total)
1574 result -= total;
1575 return result;
1576
1577 case REG_REFCNT:
1578 return (TMS34010TotalCycles() / 16) & 0xfffc;
1579
1580 case REG_INTPEND:
1581 result = IOREG(offset);
1582
1583 /* Cool Pool loops in mainline code on the appearance of the DI, even though they */
1584 /* have an IRQ handler. For this reason, we return it signalled a bit early in order */
1585 /* to make it past these loops. */
1586 //if (SMART_IOREG(VCOUNT) + 1 == SMART_IOREG(DPYINT) &&
1587 // attotime_compare(timer_timeleft(state.scantimer), ATTOTIME_IN_HZ(40000000/8/3)) < 0)
1588 // result |= TMS34010_DI;
1589 return result;
1590 }
1591
1592 return IOREG(offset);
1593 }
1594
1595
tms34020_io_register_r(INT32 address)1596 UINT16 tms34020_io_register_r(INT32 address)
1597 {
1598 int result, total, cyc_per_line;
1599
1600 INT32 offset = (address >> 4) & 0x3f;
1601
1602 //if (LOG_CONTROL_REGS)
1603 // logerror("CPU#%d@%08X: read %s\n", cpunum, activecpu_get_pc(), ioreg_name[offset]);
1604
1605 switch (offset)
1606 {
1607 case REG020_HCOUNT:
1608 /* scale the horizontal position from screen width to HTOTAL */
1609 cyc_per_line = state.config.cpu_cyc_per_frame / IOREG(REG020_VTOTAL);
1610 result = TMS34010TotalCycles() % cyc_per_line;
1611 total = IOREG(REG020_HTOTAL) + 1;
1612 result = result * total / cyc_per_line;
1613
1614 /* offset by the HBLANK end */
1615 result += IOREG(REG020_HEBLNK);
1616
1617 /* wrap around */
1618 if (result > total)
1619 result -= total;
1620 return result;
1621
1622 case REG020_REFADR:
1623 {
1624 int refreshrate = (IOREG(REG020_CONFIG) >> 8) & 7;
1625 if (refreshrate < 6)
1626 return (TMS34010TotalCycles() / refreshrate) & 0xffff;
1627 break;
1628 }
1629 }
1630
1631 return IOREG(offset);
1632 }
1633
1634
1635 #if 0
1636 /***************************************************************************
1637 UTILITY FUNCTIONS
1638 ***************************************************************************/
1639
1640 int tms34010_io_display_blanked(int cpu)
1641 {
1642 int result;
1643 cpuintrf_push_context(cpu);
1644 result = !(IOREG(REG_DPYCTL) & 0x8000);
1645 cpuintrf_pop_context();
1646 return result;
1647 }
1648
1649
1650 int tms34020_io_display_blanked(int cpu)
1651 {
1652 int result;
1653 cpuintrf_push_context(cpu);
1654 result = !(IOREG(REG020_DPYCTL) & 0x8000);
1655 cpuintrf_pop_context();
1656 return result;
1657 }
1658
1659
1660 int tms34010_get_DPYSTRT(int cpu)
1661 {
1662 int result;
1663 cpuintrf_push_context(cpu);
1664 result = IOREG(REG_DPYSTRT);
1665 cpuintrf_pop_context();
1666 return result;
1667 }
1668
1669
1670 int tms34020_get_DPYSTRT(int cpu)
1671 {
1672 int result;
1673 cpuintrf_push_context(cpu);
1674 result = (IOREG(REG020_DPYSTH) << 16) | (IOREG(REG020_DPYSTL) & ~0x1f);
1675 cpuintrf_pop_context();
1676 return result;
1677 }
1678
1679
1680
1681 /***************************************************************************
1682 SAVE STATE
1683 ***************************************************************************/
1684
1685 static STATE_POSTLOAD( tms34010_state_postload )
1686 {
1687 change_pc(TOBYTE(PC));
1688 set_raster_op();
1689 set_pixel_function();
1690 }
1691
1692 #endif
1693
1694 /***************************************************************************
1695 HOST INTERFACE WRITES
1696 ***************************************************************************/
1697
tms34010_host_w(INT32 reg,UINT16 data)1698 void tms34010_host_w(INT32 reg, UINT16 data)
1699 {
1700 unsigned int addr;
1701
1702 switch (reg)
1703 {
1704 /* upper 16 bits of the address */
1705 case TMS34010_HOST_ADDRESS_H:
1706 IOREG(REG_HSTADRH) = data;
1707 break;
1708
1709 /* lower 16 bits of the address */
1710 case TMS34010_HOST_ADDRESS_L:
1711 IOREG(REG_HSTADRL) = data;
1712 break;
1713
1714 /* actual data */
1715 case TMS34010_HOST_DATA:
1716
1717 /* write to the address */
1718 addr = (IOREG(REG_HSTADRH) << 16) | IOREG(REG_HSTADRL);
1719 TMS34010_WRMEM_WORD(TOBYTE(addr & 0xfffffff0), data);
1720
1721 /* optional postincrement */
1722 if (IOREG(REG_HSTCTLH) & 0x0800)
1723 {
1724 addr += 0x10;
1725 IOREG(REG_HSTADRH) = addr >> 16;
1726 IOREG(REG_HSTADRL) = (UINT16)addr;
1727 }
1728 break;
1729
1730 /* control register */
1731 case TMS34010_HOST_CONTROL:
1732 state.external_host_access = 1;
1733 tms34010_io_register_w(REG_HSTCTLH << 4, data & 0xff00);
1734 tms34010_io_register_w(REG_HSTCTLL << 4, data & 0x00ff);
1735 state.external_host_access = 0;
1736 break;
1737
1738 /* error case */
1739 default:
1740 //logerror("tms34010_host_control_w called on invalid register %d\n", reg);
1741 break;
1742 }
1743 }
1744
1745
1746
1747 /***************************************************************************
1748 HOST INTERFACE READS
1749 ***************************************************************************/
1750
tms34010_host_r(INT32 reg)1751 UINT16 tms34010_host_r(INT32 reg)
1752 {
1753 unsigned int addr;
1754 int result = 0;
1755
1756 switch (reg)
1757 {
1758 /* upper 16 bits of the address */
1759 case TMS34010_HOST_ADDRESS_H:
1760 result = IOREG(REG_HSTADRH);
1761 break;
1762
1763 /* lower 16 bits of the address */
1764 case TMS34010_HOST_ADDRESS_L:
1765 result = IOREG(REG_HSTADRL);
1766 break;
1767
1768 /* actual data */
1769 case TMS34010_HOST_DATA:
1770
1771 /* read from the address */
1772 addr = (IOREG(REG_HSTADRH) << 16) | IOREG(REG_HSTADRL);
1773 result = TMS34010_RDMEM_WORD(TOBYTE(addr & 0xfffffff0));
1774
1775 /* optional postincrement (it says preincrement, but data is preloaded, so it
1776 is effectively a postincrement */
1777 if (IOREG(REG_HSTCTLH) & 0x1000)
1778 {
1779 addr += 0x10;
1780 IOREG(REG_HSTADRH) = addr >> 16;
1781 IOREG(REG_HSTADRL) = (UINT16)addr;
1782 }
1783 break;
1784
1785 /* control register */
1786 case TMS34010_HOST_CONTROL:
1787 result = (IOREG(REG_HSTCTLH) & 0xff00) | (IOREG(REG_HSTCTLL) & 0x00ff);
1788 break;
1789
1790 /* error case */
1791 default:
1792 //logerror("tms34010_host_control_r called on invalid register %d\n", reg);
1793 break;
1794 }
1795
1796 return result;
1797 }
1798
1799 #if 0
1800
1801 /**************************************************************************
1802 * Generic set_info
1803 **************************************************************************/
1804
1805 static void tms34010_set_info(UINT32 _state, cpuinfo *info)
1806 {
1807 switch (_state)
1808 {
1809 /* --- the following bits of info are set as 64-bit signed integers --- */
1810 case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break;
1811 case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break;
1812
1813 case CPUINFO_INT_PC: PC = info->i; change_pc(TOBYTE(PC)); break;
1814 case CPUINFO_INT_REGISTER + TMS34010_PC: PC = info->i; break;
1815 case CPUINFO_INT_SP:
1816 case CPUINFO_INT_REGISTER + TMS34010_SP: SP = info->i; break;
1817 case CPUINFO_INT_REGISTER + TMS34010_ST: ST = info->i; break;
1818 case CPUINFO_INT_REGISTER + TMS34010_A0: AREG(0) = info->i; break;
1819 case CPUINFO_INT_REGISTER + TMS34010_A1: AREG(1) = info->i; break;
1820 case CPUINFO_INT_REGISTER + TMS34010_A2: AREG(2) = info->i; break;
1821 case CPUINFO_INT_REGISTER + TMS34010_A3: AREG(3) = info->i; break;
1822 case CPUINFO_INT_REGISTER + TMS34010_A4: AREG(4) = info->i; break;
1823 case CPUINFO_INT_REGISTER + TMS34010_A5: AREG(5) = info->i; break;
1824 case CPUINFO_INT_REGISTER + TMS34010_A6: AREG(6) = info->i; break;
1825 case CPUINFO_INT_REGISTER + TMS34010_A7: AREG(7) = info->i; break;
1826 case CPUINFO_INT_REGISTER + TMS34010_A8: AREG(8) = info->i; break;
1827 case CPUINFO_INT_REGISTER + TMS34010_A9: AREG(9) = info->i; break;
1828 case CPUINFO_INT_REGISTER + TMS34010_A10: AREG(10) = info->i; break;
1829 case CPUINFO_INT_REGISTER + TMS34010_A11: AREG(11) = info->i; break;
1830 case CPUINFO_INT_REGISTER + TMS34010_A12: AREG(12) = info->i; break;
1831 case CPUINFO_INT_REGISTER + TMS34010_A13: AREG(13) = info->i; break;
1832 case CPUINFO_INT_REGISTER + TMS34010_A14: AREG(14) = info->i; break;
1833 case CPUINFO_INT_REGISTER + TMS34010_B0: BREG(0) = info->i; break;
1834 case CPUINFO_INT_REGISTER + TMS34010_B1: BREG(1) = info->i; break;
1835 case CPUINFO_INT_REGISTER + TMS34010_B2: BREG(2) = info->i; break;
1836 case CPUINFO_INT_REGISTER + TMS34010_B3: BREG(3) = info->i; break;
1837 case CPUINFO_INT_REGISTER + TMS34010_B4: BREG(4) = info->i; break;
1838 case CPUINFO_INT_REGISTER + TMS34010_B5: BREG(5) = info->i; break;
1839 case CPUINFO_INT_REGISTER + TMS34010_B6: BREG(6) = info->i; break;
1840 case CPUINFO_INT_REGISTER + TMS34010_B7: BREG(7) = info->i; break;
1841 case CPUINFO_INT_REGISTER + TMS34010_B8: BREG(8) = info->i; break;
1842 case CPUINFO_INT_REGISTER + TMS34010_B9: BREG(9) = info->i; break;
1843 case CPUINFO_INT_REGISTER + TMS34010_B10: BREG(10) = info->i; break;
1844 case CPUINFO_INT_REGISTER + TMS34010_B11: BREG(11) = info->i; break;
1845 case CPUINFO_INT_REGISTER + TMS34010_B12: BREG(12) = info->i; break;
1846 case CPUINFO_INT_REGISTER + TMS34010_B13: BREG(13) = info->i; break;
1847 case CPUINFO_INT_REGISTER + TMS34010_B14: BREG(14) = info->i; break;
1848 }
1849 }
1850
1851
1852
1853 /**************************************************************************
1854 * Generic get_info
1855 **************************************************************************/
1856
1857 void tms34010_get_info(UINT32 _state, cpuinfo *info)
1858 {
1859 switch (_state)
1860 {
1861 /* --- the following bits of info are returned as 64-bit signed integers --- */
1862 case CPUINFO_INT_CONTEXT_SIZE: info->i = TMS34010_STATE_SIZE; break;
1863 case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
1864 case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
1865 case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
1866 case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
1867 case CPUINFO_INT_CLOCK_DIVIDER: info->i = 8; break;
1868 case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
1869 case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
1870 case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
1871 case CPUINFO_INT_MAX_CYCLES: info->i = 10000; break;
1872
1873 case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
1874 case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
1875 case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 3; break;
1876 case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
1877 case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
1878 case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
1879 case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
1880 case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
1881 case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
1882
1883 case CPUINFO_INT_INPUT_STATE + 0: info->i = (IOREG(REG_INTPEND) & TMS34010_INT1) ? ASSERT_LINE : CLEAR_LINE; break;
1884 case CPUINFO_INT_INPUT_STATE + 1: info->i = (IOREG(REG_INTPEND) & TMS34010_INT2) ? ASSERT_LINE : CLEAR_LINE; break;
1885
1886 case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
1887
1888 case CPUINFO_INT_PC:
1889 case CPUINFO_INT_REGISTER + TMS34010_PC: info->i = PC; break;
1890 case CPUINFO_INT_SP:
1891 case CPUINFO_INT_REGISTER + TMS34010_SP: info->i = SP; break;
1892 case CPUINFO_INT_REGISTER + TMS34010_ST: info->i = ST; break;
1893 case CPUINFO_INT_REGISTER + TMS34010_A0: info->i = AREG(0); break;
1894 case CPUINFO_INT_REGISTER + TMS34010_A1: info->i = AREG(1); break;
1895 case CPUINFO_INT_REGISTER + TMS34010_A2: info->i = AREG(2); break;
1896 case CPUINFO_INT_REGISTER + TMS34010_A3: info->i = AREG(3); break;
1897 case CPUINFO_INT_REGISTER + TMS34010_A4: info->i = AREG(4); break;
1898 case CPUINFO_INT_REGISTER + TMS34010_A5: info->i = AREG(5); break;
1899 case CPUINFO_INT_REGISTER + TMS34010_A6: info->i = AREG(6); break;
1900 case CPUINFO_INT_REGISTER + TMS34010_A7: info->i = AREG(7); break;
1901 case CPUINFO_INT_REGISTER + TMS34010_A8: info->i = AREG(8); break;
1902 case CPUINFO_INT_REGISTER + TMS34010_A9: info->i = AREG(9); break;
1903 case CPUINFO_INT_REGISTER + TMS34010_A10: info->i = AREG(10); break;
1904 case CPUINFO_INT_REGISTER + TMS34010_A11: info->i = AREG(11); break;
1905 case CPUINFO_INT_REGISTER + TMS34010_A12: info->i = AREG(12); break;
1906 case CPUINFO_INT_REGISTER + TMS34010_A13: info->i = AREG(13); break;
1907 case CPUINFO_INT_REGISTER + TMS34010_A14: info->i = AREG(14); break;
1908 case CPUINFO_INT_REGISTER + TMS34010_B0: info->i = BREG(0); break;
1909 case CPUINFO_INT_REGISTER + TMS34010_B1: info->i = BREG(1); break;
1910 case CPUINFO_INT_REGISTER + TMS34010_B2: info->i = BREG(2); break;
1911 case CPUINFO_INT_REGISTER + TMS34010_B3: info->i = BREG(3); break;
1912 case CPUINFO_INT_REGISTER + TMS34010_B4: info->i = BREG(4); break;
1913 case CPUINFO_INT_REGISTER + TMS34010_B5: info->i = BREG(5); break;
1914 case CPUINFO_INT_REGISTER + TMS34010_B6: info->i = BREG(6); break;
1915 case CPUINFO_INT_REGISTER + TMS34010_B7: info->i = BREG(7); break;
1916 case CPUINFO_INT_REGISTER + TMS34010_B8: info->i = BREG(8); break;
1917 case CPUINFO_INT_REGISTER + TMS34010_B9: info->i = BREG(9); break;
1918 case CPUINFO_INT_REGISTER + TMS34010_B10: info->i = BREG(10); break;
1919 case CPUINFO_INT_REGISTER + TMS34010_B11: info->i = BREG(11); break;
1920 case CPUINFO_INT_REGISTER + TMS34010_B12: info->i = BREG(12); break;
1921 case CPUINFO_INT_REGISTER + TMS34010_B13: info->i = BREG(13); break;
1922 case CPUINFO_INT_REGISTER + TMS34010_B14: info->i = BREG(14); break;
1923
1924 /* --- the following bits of info are returned as pointers to data or functions --- */
1925 case CPUINFO_PTR_SET_INFO: info->setinfo = tms34010_set_info; break;
1926 case CPUINFO_PTR_GET_CONTEXT: info->getcontext = tms34010_get_context; break;
1927 case CPUINFO_PTR_SET_CONTEXT: info->setcontext = tms34010_set_context; break;
1928 case CPUINFO_PTR_INIT: info->init = tms34010_init; break;
1929 case CPUINFO_PTR_RESET: info->reset = tms34010_reset; break;
1930 case CPUINFO_PTR_EXIT: info->exit = tms34010_exit; break;
1931 case CPUINFO_PTR_EXECUTE: info->execute = tms34010_execute; break;
1932 case CPUINFO_PTR_BURN: info->burn = NULL; break;
1933 case CPUINFO_PTR_DISASSEMBLE: info->disassemble = tms34010_dasm; break;
1934 case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &tms34010_ICount; break;
1935
1936 /* --- the following bits of info are returned as NULL-terminated strings --- */
1937 case CPUINFO_STR_NAME: strcpy(info->s, "TMS34010"); break;
1938 case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Texas Instruments 340x0"); break;
1939 case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
1940 case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
1941 case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Alex Pasadyn/Zsolt Vasvari\nParts based on code by Aaron Giles"); break;
1942
1943 case CPUINFO_STR_FLAGS:
1944 sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
1945 state.st & 0x80000000 ? 'N':'.',
1946 state.st & 0x40000000 ? 'C':'.',
1947 state.st & 0x20000000 ? 'Z':'.',
1948 state.st & 0x10000000 ? 'V':'.',
1949 state.st & 0x02000000 ? 'P':'.',
1950 state.st & 0x00200000 ? 'I':'.',
1951 state.st & 0x00000800 ? 'E':'.',
1952 state.st & 0x00000400 ? 'F':'.',
1953 state.st & 0x00000200 ? 'F':'.',
1954 state.st & 0x00000100 ? 'F':'.',
1955 state.st & 0x00000080 ? 'F':'.',
1956 state.st & 0x00000040 ? 'F':'.',
1957 state.st & 0x00000020 ? 'E':'.',
1958 state.st & 0x00000010 ? 'F':'.',
1959 state.st & 0x00000008 ? 'F':'.',
1960 state.st & 0x00000004 ? 'F':'.',
1961 state.st & 0x00000002 ? 'F':'.',
1962 state.st & 0x00000001 ? 'F':'.');
1963 break;
1964
1965 case CPUINFO_STR_REGISTER + TMS34010_PC: sprintf(info->s, "PC :%08X", state.pc); break;
1966 case CPUINFO_STR_REGISTER + TMS34010_SP: sprintf(info->s, "SP :%08X", AREG(15)); break;
1967 case CPUINFO_STR_REGISTER + TMS34010_ST: sprintf(info->s, "ST :%08X", state.st); break;
1968 case CPUINFO_STR_REGISTER + TMS34010_A0: sprintf(info->s, "A0 :%08X", AREG( 0)); break;
1969 case CPUINFO_STR_REGISTER + TMS34010_A1: sprintf(info->s, "A1 :%08X", AREG( 1)); break;
1970 case CPUINFO_STR_REGISTER + TMS34010_A2: sprintf(info->s, "A2 :%08X", AREG( 2)); break;
1971 case CPUINFO_STR_REGISTER + TMS34010_A3: sprintf(info->s, "A3 :%08X", AREG( 3)); break;
1972 case CPUINFO_STR_REGISTER + TMS34010_A4: sprintf(info->s, "A4 :%08X", AREG( 4)); break;
1973 case CPUINFO_STR_REGISTER + TMS34010_A5: sprintf(info->s, "A5 :%08X", AREG( 5)); break;
1974 case CPUINFO_STR_REGISTER + TMS34010_A6: sprintf(info->s, "A6 :%08X", AREG( 6)); break;
1975 case CPUINFO_STR_REGISTER + TMS34010_A7: sprintf(info->s, "A7 :%08X", AREG( 7)); break;
1976 case CPUINFO_STR_REGISTER + TMS34010_A8: sprintf(info->s, "A8 :%08X", AREG( 8)); break;
1977 case CPUINFO_STR_REGISTER + TMS34010_A9: sprintf(info->s, "A9 :%08X", AREG( 9)); break;
1978 case CPUINFO_STR_REGISTER + TMS34010_A10: sprintf(info->s,"A10:%08X", AREG(10)); break;
1979 case CPUINFO_STR_REGISTER + TMS34010_A11: sprintf(info->s,"A11:%08X", AREG(11)); break;
1980 case CPUINFO_STR_REGISTER + TMS34010_A12: sprintf(info->s,"A12:%08X", AREG(12)); break;
1981 case CPUINFO_STR_REGISTER + TMS34010_A13: sprintf(info->s,"A13:%08X", AREG(13)); break;
1982 case CPUINFO_STR_REGISTER + TMS34010_A14: sprintf(info->s,"A14:%08X", AREG(14)); break;
1983 case CPUINFO_STR_REGISTER + TMS34010_B0: sprintf(info->s, "B0 :%08X", BREG( 0)); break;
1984 case CPUINFO_STR_REGISTER + TMS34010_B1: sprintf(info->s, "B1 :%08X", BREG( 1)); break;
1985 case CPUINFO_STR_REGISTER + TMS34010_B2: sprintf(info->s, "B2 :%08X", BREG( 2)); break;
1986 case CPUINFO_STR_REGISTER + TMS34010_B3: sprintf(info->s, "B3 :%08X", BREG( 3)); break;
1987 case CPUINFO_STR_REGISTER + TMS34010_B4: sprintf(info->s, "B4 :%08X", BREG( 4)); break;
1988 case CPUINFO_STR_REGISTER + TMS34010_B5: sprintf(info->s, "B5 :%08X", BREG( 5)); break;
1989 case CPUINFO_STR_REGISTER + TMS34010_B6: sprintf(info->s, "B6 :%08X", BREG( 6)); break;
1990 case CPUINFO_STR_REGISTER + TMS34010_B7: sprintf(info->s, "B7 :%08X", BREG( 7)); break;
1991 case CPUINFO_STR_REGISTER + TMS34010_B8: sprintf(info->s, "B8 :%08X", BREG( 8)); break;
1992 case CPUINFO_STR_REGISTER + TMS34010_B9: sprintf(info->s, "B9 :%08X", BREG( 9)); break;
1993 case CPUINFO_STR_REGISTER + TMS34010_B10: sprintf(info->s,"B10:%08X", BREG(10)); break;
1994 case CPUINFO_STR_REGISTER + TMS34010_B11: sprintf(info->s,"B11:%08X", BREG(11)); break;
1995 case CPUINFO_STR_REGISTER + TMS34010_B12: sprintf(info->s,"B12:%08X", BREG(12)); break;
1996 case CPUINFO_STR_REGISTER + TMS34010_B13: sprintf(info->s,"B13:%08X", BREG(13)); break;
1997 case CPUINFO_STR_REGISTER + TMS34010_B14: sprintf(info->s,"B14:%08X", BREG(14)); break;
1998 }
1999 }
2000
2001
2002 #if (HAS_TMS34020)
2003 /**************************************************************************
2004 * CPU-specific set_info
2005 **************************************************************************/
2006
2007 void tms34020_get_info(UINT32 _state, cpuinfo *info)
2008 {
2009 switch (_state)
2010 {
2011 /* --- the following bits of info are returned as 64-bit signed integers --- */
2012 case CPUINFO_INT_CONTEXT_SIZE: info->i = TMS34020_STATE_SIZE; break;
2013 case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
2014 case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
2015
2016 /* --- the following bits of info are returned as pointers to data or functions --- */
2017 case CPUINFO_PTR_GET_CONTEXT: info->getcontext = tms34020_get_context; break;
2018 case CPUINFO_PTR_SET_CONTEXT: info->setcontext = tms34020_set_context; break;
2019 case CPUINFO_PTR_RESET: info->reset = tms34020_reset; break;
2020 case CPUINFO_PTR_DISASSEMBLE: info->disassemble = tms34020_dasm; break;
2021
2022 /* --- the following bits of info are returned as NULL-terminated strings --- */
2023 case CPUINFO_STR_NAME: strcpy(info->s, "TMS34020"); break;
2024
2025 default: tms34010_get_info(_state, info); break;
2026 }
2027 }
2028 #endif
2029
2030 #endif
2031