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(&params);
1094 
1095 		// screen update callback - clipping is done in the driver -dink
1096 		if (render) {
1097 			render(line, &params);
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, &params);
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, &params);
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