1 // V60.C
2 // Undiscover the beast!
3 // Main hacking and coding by Farfetch'd
4 // Portability fixes by Richter Belmont
5 
6 #include "burnint.h"
7 #include "bitswap.h" // ...xor_le
8 #include "driver.h"
9 #include "v60_intf.h"
10 
11 #define offs_t			UINT32
12 #define INPUT_LINE_NMI		CPU_IRQLINE_NMI
13 
14 #define change_pc(x)		v60.reg[32] = (x)
15 
16 // convert a series of 32 bits into a float
u2f(UINT32 v)17 inline float u2f(UINT32 v)
18 {
19 	union {
20 		float ff;
21 		UINT32 vv;
22 	} u;
23 	u.vv = v;
24 	return u.ff;
25 }
26 
27 
28 // convert a float into a series of 32 bits
f2u(float f)29 inline UINT32 f2u(float f)
30 {
31 	union {
32 		float ff;
33 		UINT32 vv;
34 	} u;
35 	u.ff = f;
36 	return u.vv;
37 }
38 
39 
40 //#define LOG_MEM
41 
42 #define address_range	0x1000000
43 #define address_mask	0xffffff
44 #define page_size	0x800
45 #define page_mask	0x7ff
46 
47 static UINT8 *mem[3][(address_mask + 1) / page_size];
48 
49 static UINT8  (*v60_read8)(UINT32) = NULL;
50 static UINT16 (*v60_read16)(UINT32) = NULL;
51 static UINT32 (*v60_read32)(UINT32) = NULL;
52 static void (*v60_write8)(UINT32,UINT8) = NULL;
53 static void (*v60_write16)(UINT32,UINT16) = NULL;
54 static void (*v60_write32)(UINT32,UINT32) = NULL;
55 
56 static UINT8  (*v60_ioread8)(UINT32) = NULL;
57 static UINT16 (*v60_ioread16)(UINT32) = NULL;
58 static UINT32 (*v60_ioread32)(UINT32) = NULL;
59 static void (*v60_iowrite8)(UINT32,UINT8) = NULL;
60 static void (*v60_iowrite16)(UINT32,UINT16) = NULL;
61 static void (*v60_iowrite32)(UINT32,UINT32) = NULL;
62 
63 
v60SetWriteByteHandler(void (* write)(UINT32,UINT8))64 void v60SetWriteByteHandler(void (*write)(UINT32,UINT8))
65 {
66 	v60_write8 = write;
67 }
68 
v60SetWriteWordHandler(void (* write)(UINT32,UINT16))69 void v60SetWriteWordHandler(void (*write)(UINT32,UINT16))
70 {
71 	v60_write16 = write;
72 }
73 
v60SetReadByteHandler(UINT8 (* read)(UINT32))74 void v60SetReadByteHandler(UINT8  (*read)(UINT32))
75 {
76 	v60_read8 = read;
77 }
78 
v60SetReadWordHandler(UINT16 (* read)(UINT32))79 void v60SetReadWordHandler(UINT16 (*read)(UINT32))
80 {
81 	v60_read16 = read;
82 }
83 
84 
v60MapMemory(UINT8 * ptr,UINT32 start,UINT32 end,UINT32 flags)85 void v60MapMemory(UINT8 *ptr, UINT32 start, UINT32 end, UINT32 flags)
86 {
87 	// error check here!
88 
89 	for (UINT32 i = start; i < end; i+= page_size)
90 	{
91 		if (flags & 1) mem[0][i/page_size] = ptr + (i - start);
92 		if (flags & 2) mem[1][i/page_size] = ptr + (i - start);
93 		if (flags & 4) mem[2][i/page_size] = ptr + (i - start);
94 	}
95 }
96 
cpu_readop(UINT32 a)97 static UINT8 cpu_readop(UINT32 a)
98 {
99 	a &= address_mask;
100 
101 	if (mem[2][a / page_size]) {
102 #ifdef LOG_MEM
103 //		bprintf (0, _T("OP8: %6.6x %2.2x\n"), a, mem[2][a / page_size][a & page_mask]);
104 #endif
105 		return mem[2][a / page_size][a & page_mask];
106 	}
107 
108 	if (v60_read8) {
109 #ifdef LOG_MEM
110 		bprintf (0, _T("OP8: %6.6x %2.2x\n"), a, v60_read8(a));
111 #endif
112 		return v60_read8(a);
113 	}
114 
115 	return 0;
116 }
117 
cpu_readop16(UINT32 a)118 static UINT16 cpu_readop16(UINT32 a)
119 {
120 	a &= address_mask;
121 
122 	UINT8 *p = mem[2][a / page_size];
123 
124 	if (p) {
125 		UINT16 *z = (UINT16*)(p + (a & page_mask));
126 #ifdef LOG_MEM
127 //		bprintf (0, _T("OP16: %6.6x %4.4x\n"), a, *z);
128 #endif
129 		return *z;
130 	}
131 
132 	if (v60_read16) {
133 #ifdef LOG_MEM
134 		bprintf (0, _T("OP16: %6.6x %4.4x\n"), a, v60_read16(a));
135 #endif
136 
137 		return v60_read16(a);
138 	}
139 
140 	return 0;
141 }
142 
cpu_readop32(UINT32 a)143 static UINT32 cpu_readop32(UINT32 a)
144 {
145 	a &= address_mask;
146 
147 	UINT8 *p = mem[2][a / page_size];
148 
149 	if (p) {
150 		UINT32 *z = (UINT32*)(p + (a & page_mask));
151 
152 #ifdef LOG_MEM
153 //		bprintf (0, _T("OP32: %6.6x %8.8x\n"), a, *z);
154 #endif
155 
156 		return *z;
157 	}
158 
159 	if (v60_read32) {
160 #ifdef LOG_MEM
161 		bprintf (0, _T("OP32: %6.6x %8.8x\n"), a, v60_read32(a));
162 #endif
163 
164 		return v60_read32(a);
165 	}
166 
167 	return 0;
168 }
169 
program_read_word_16le(UINT32 a)170 static UINT16 program_read_word_16le(UINT32 a)
171 {
172 	a &= address_mask;
173 
174 	UINT8 *p = mem[0][a / page_size];
175 
176 	if (p) {
177 		UINT16 *z = (UINT16*)(p + (a & page_mask));
178 #ifdef LOG_MEM
179 		bprintf (0, _T("PRW: %6.6x %4.4x\n"), a, *z);
180 #endif
181 
182 		return *z;
183 	}
184 
185 	if (v60_read16) {
186 #ifdef LOG_MEM
187 		bprintf (0, _T("PRW: %6.6x %4.4x\n"), a, v60_read16(a));
188 #endif
189 		return v60_read16(a);
190 	}
191 
192 	return 0;
193 }
194 
program_read_byte_16le(UINT32 a)195 static UINT8 program_read_byte_16le(UINT32 a)
196 {
197 	a &= address_mask;
198 
199 #ifdef LOG_MEM
200 	bprintf (0, _T("PRB: %6.6x\n"), a);
201 #endif
202 
203 	if (mem[0][a / page_size]) {
204 		return mem[0][a / page_size][a & page_mask];
205 	}
206 
207 	if (v60_read8) {
208 		return v60_read8(a);
209 	}
210 
211 	return 0;
212 }
213 
program_write_word_16le(UINT32 a,UINT16 d)214 static void program_write_word_16le(UINT32 a, UINT16 d)
215 {
216 	a &= address_mask;
217 #ifdef LOG_MEM
218 	bprintf (0, _T("PWW: %6.6x %4.4x\n"), a,d);
219 #endif
220 
221 	UINT8 *p = mem[1][a / page_size];
222 
223 	if (p) {
224 		UINT16 *z = (UINT16*)(p + (a & page_mask));
225 		*z = d;
226 		return;
227 	}
228 
229 	if (v60_write16) {
230 		v60_write16(a,d);
231 		return;
232 	}
233 }
234 
program_write_byte_16le(UINT32 a,UINT8 d)235 static void program_write_byte_16le(UINT32 a, UINT8 d)
236 {
237 	a &= address_mask;
238 #ifdef LOG_MEM
239 	bprintf (0, _T("PWB: %6.6x %2.2x\n"), a,d);
240 #endif
241 
242 	if (mem[1][a / page_size]) {
243 		mem[1][a / page_size][a & page_mask] = d;
244 		return;
245 	}
246 
247 	if (v60_write8) {
248 		return v60_write8(a,d);
249 	}
250 }
251 
io_read_word_16le(UINT32 a)252 static UINT16 io_read_word_16le(UINT32 a)
253 {
254 	if (v60_ioread16) {
255 		return v60_ioread16(a);
256 	}
257 
258 	return 0;
259 }
260 
io_read_byte_16le(UINT32 a)261 static UINT8 io_read_byte_16le(UINT32 a)
262 {
263 	if (v60_ioread8) {
264 		return v60_ioread8(a);
265 	}
266 
267 	return 0;
268 }
269 
io_write_word_16le(UINT32 a,UINT16 d)270 static void io_write_word_16le(UINT32 a, UINT16 d)
271 {
272 	if (v60_iowrite16) {
273 		return v60_iowrite16(a,d);
274 	}
275 }
276 
io_write_byte_16le(UINT32 a,UINT8 d)277 static void io_write_byte_16le(UINT32 a, UINT8 d)
278 {
279 	if (v60_iowrite8) {
280 		return v60_iowrite8(a,d);
281 	}
282 }
283 
io_read_dword_32le(UINT32 a)284 static UINT32 io_read_dword_32le(UINT32 a)
285 {
286 	if (v60_ioread32) {
287 		return v60_ioread32(a);
288 	}
289 
290 	return 0;
291 }
292 
io_read_word_32le(UINT32 a)293 static UINT16 io_read_word_32le(UINT32 a)
294 {
295 	if (v60_ioread16) {
296 		return v60_ioread16(a);
297 	}
298 
299 	return 0;
300 }
301 
io_read_byte_32le(UINT32 a)302 static UINT8 io_read_byte_32le(UINT32 a)
303 {
304 	if (v60_ioread8) {
305 		return v60_ioread8(a);
306 	}
307 
308 	return 0;
309 }
310 
io_write_dword_32le(UINT32 a,UINT32 d)311 static void io_write_dword_32le(UINT32 a, UINT32 d)
312 {
313 	if (v60_iowrite32) {
314 		return v60_iowrite32(a,d);
315 	}
316 }
317 
io_write_word_32le(UINT32 a,UINT16 d)318 static void io_write_word_32le(UINT32 a, UINT16 d)
319 {
320 	if (v60_iowrite16) {
321 		return v60_iowrite16(a,d);
322 	}
323 }
324 
io_write_byte_32le(UINT32 a,UINT8 d)325 static void io_write_byte_32le(UINT32 a, UINT8 d)
326 {
327 	if (v60_iowrite8) {
328 		return v60_iowrite8(a,d);
329 	}
330 }
331 
program_read_dword_32le(UINT32 a)332 static UINT32 program_read_dword_32le(UINT32 a)
333 {
334 	UINT32 *p = (UINT32*)mem[0][a / page_size];
335 
336 	if (p) {
337 		return p[(a & page_mask)/4];
338 	}
339 
340 	if (v60_read32) {
341 		return v60_read32(a);
342 	}
343 
344 	return 0;
345 }
346 
program_read_word_32le(UINT32 a)347 static UINT16 program_read_word_32le(UINT32 a)
348 {
349 	UINT16 *p = (UINT16*)mem[0][a / page_size];
350 
351 	if (p) {
352 		return p[(a & page_mask)/2];
353 	}
354 
355 	if (v60_read16) {
356 		return v60_read16(a);
357 	}
358 
359 	return 0;
360 }
361 
program_read_byte_32le(UINT32 a)362 static UINT8 program_read_byte_32le(UINT32 a)
363 {
364 	if (mem[0][a / page_size]) {
365 		return mem[0][a / page_size][a & page_mask];
366 	}
367 
368 	if (v60_read8) {
369 		return v60_read8(a);
370 	}
371 
372 	return 0;
373 }
374 
program_write_dword_32le(UINT32 a,UINT32 d)375 static void program_write_dword_32le(UINT32 a, UINT32 d)
376 {
377 	UINT32 *p = (UINT32*)mem[1][a / page_size];
378 
379 	if (p) {
380 		p[(a & page_mask)/4] = d;
381 		return;
382 	}
383 
384 	if (v60_write32) {
385 		v60_write32(a,d);
386 		return;
387 	}
388 }
389 
program_write_word_32le(UINT32 a,UINT16 d)390 static void program_write_word_32le(UINT32 a, UINT16 d)
391 {
392 	UINT16 *p = (UINT16*)mem[1][a / page_size];
393 
394 	if (p) {
395 		p[(a & page_mask)/2] = d;
396 		return;
397 	}
398 
399 	if (v60_write16) {
400 		v60_write16(a,d);
401 		return;
402 	}
403 }
404 
program_write_byte_32le(UINT32 a,UINT8 d)405 static void program_write_byte_32le(UINT32 a, UINT8 d)
406 {
407 	if (mem[1][a / page_size]) {
408 		mem[1][a / page_size][a & page_mask] = d;
409 		return;
410 	}
411 
412 	if (v60_write8) {
413 		return v60_write8(a,d);
414 	}
415 }
416 
417 cpu_core_config v60Config =
418 {
419 	v60Open,
420 	v60Close,
421 	v60CheatRead,
422 	v60WriteROM,
423 	v60GetActive,
424 	v60TotalCycles,
425 	v60NewFrame,
426 	v60Run,
427 	v60RunEnd,
428 	v60Reset,
429 	0x1000000,
430 	0
431 };
432 
433 struct cpu_info {
434 	UINT8  (*mr8) (offs_t address);
435 	void   (*mw8) (offs_t address, UINT8  data);
436 	UINT16 (*mr16)(offs_t address);
437 	void   (*mw16)(offs_t address, UINT16 data);
438 	UINT32 (*mr32)(offs_t address);
439 	void   (*mw32)(offs_t address, UINT32 data);
440 	UINT8  (*pr8) (offs_t address);
441 	void   (*pw8) (offs_t address, UINT8  data);
442 	UINT16 (*pr16)(offs_t address);
443 	void   (*pw16)(offs_t address, UINT16 data);
444 	UINT32 (*pr32)(offs_t address);
445 	void   (*pw32)(offs_t address, UINT32 data);
446 	UINT8  (*or8) (offs_t address);
447 	UINT16 (*or16)(offs_t address);
448 	UINT32 (*or32)(offs_t address);
449 	void   (*chpc)(offs_t newpc);
450 	UINT32 start_pc;
451 };
452 
453 typedef struct
454 {
455 	UINT8 CY;
456 	UINT8 OV;
457 	UINT8 S;
458 	UINT8 Z;
459 } Flags;
460 
461 // v60 Register Inside (Hm... It's not a pentium inside :-))) )
462 static struct v60info {
463 	struct cpu_info info;
464 	UINT32 reg[68];
465 	Flags flags;
466 	UINT8 irq_line;
467 	UINT8 nmi_line;
468 	int (*irq_cb)(int irqline);
469 	UINT32 PPC;
470 	UINT32 current_cycles;
471 	UINT32 cycles;
472 } v60;
473 
474 
475 static int v60_ICount;
476 
477 
478 // memory accessors
479 #include "v60mem.c"
480 
481 
482 // macros stolen from MAME for flags calc
483 // note that these types are in x86 naming:
484 // byte = 8 bit, word = 16 bit, long = 32 bit
485 
486 // parameter x = result, y = source 1, z = source 2
487 
488 #define SetOFL_Add(x,y,z)	(_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x80000000) ? 1: 0)
489 #define SetOFW_Add(x,y,z)	(_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x8000) ? 1 : 0)
490 #define SetOFB_Add(x,y,z)	(_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x80) ? 1 : 0)
491 
492 #define SetOFL_Sub(x,y,z)	(_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x80000000) ? 1 : 0)
493 #define SetOFW_Sub(x,y,z)	(_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x8000) ? 1 : 0)
494 #define SetOFB_Sub(x,y,z)	(_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x80) ? 1 : 0)
495 
496 #define SetCFB(x)		{_CY = ((x) & 0x100) ? 1 : 0; }
497 #define SetCFW(x)		{_CY = ((x) & 0x10000) ? 1 : 0; }
498 #define SetCFL(x)		{_CY = ((x) & (((UINT64)1) << 32)) ? 1 : 0; }
499 
500 #define SetSF(x)		(_S = (x))
501 #define SetZF(x)		(_Z = (x))
502 
503 #define SetSZPF_Byte(x) 	{_Z = ((UINT8)(x)==0);  _S = ((x)&0x80) ? 1 : 0; }
504 #define SetSZPF_Word(x) 	{_Z = ((UINT16)(x)==0);  _S = ((x)&0x8000) ? 1 : 0; }
505 #define SetSZPF_Long(x) 	{_Z = ((UINT32)(x)==0);  _S = ((x)&0x80000000) ? 1 : 0; }
506 
507 #define ORB(dst,src)		{ (dst) |= (src); _CY = _OV = 0; SetSZPF_Byte(dst); }
508 #define ORW(dst,src)		{ (dst) |= (src); _CY = _OV = 0; SetSZPF_Word(dst); }
509 #define ORL(dst,src)		{ (dst) |= (src); _CY = _OV = 0; SetSZPF_Long(dst); }
510 
511 #define ANDB(dst,src)		{ (dst) &= (src); _CY = _OV = 0; SetSZPF_Byte(dst); }
512 #define ANDW(dst,src)		{ (dst) &= (src); _CY = _OV = 0; SetSZPF_Word(dst); }
513 #define ANDL(dst,src)		{ (dst) &= (src); _CY = _OV = 0; SetSZPF_Long(dst); }
514 
515 #define XORB(dst,src)		{ (dst) ^= (src); _CY = _OV = 0; SetSZPF_Byte(dst); }
516 #define XORW(dst,src)		{ (dst) ^= (src); _CY = _OV = 0; SetSZPF_Word(dst); }
517 #define XORL(dst,src)		{ (dst) ^= (src); _CY = _OV = 0; SetSZPF_Long(dst); }
518 
519 #define SUBB(dst, src)		{ unsigned res=(dst)-(src); SetCFB(res); SetOFB_Sub(res,src,dst); SetSZPF_Byte(res); dst=(UINT8)res; }
520 #define SUBW(dst, src)		{ unsigned res=(dst)-(src); SetCFW(res); SetOFW_Sub(res,src,dst); SetSZPF_Word(res); dst=(UINT16)res; }
521 #define SUBL(dst, src)		{ UINT64 res=(UINT64)(dst)-(INT64)(src); SetCFL(res); SetOFL_Sub(res,src,dst); SetSZPF_Long(res); dst=(UINT32)res; }
522 
523 #define ADDB(dst, src)		{ unsigned res=(dst)+(src); SetCFB(res); SetOFB_Add(res,src,dst); SetSZPF_Byte(res); dst=(UINT8)res; }
524 #define ADDW(dst, src)		{ unsigned res=(dst)+(src); SetCFW(res); SetOFW_Add(res,src,dst); SetSZPF_Word(res); dst=(UINT16)res; }
525 #define ADDL(dst, src)		{ UINT64 res=(UINT64)(dst)+(UINT64)(src); SetCFL(res); SetOFL_Add(res,src,dst); SetSZPF_Long(res); dst=(UINT32)res; }
526 
527 #define SETREG8(a, b)  (a) = ((a) & ~0xff) | ((b) & 0xff)
528 #define SETREG16(a, b) (a) = ((a) & ~0xffff) | ((b) & 0xffff)
529 
530 
531 /*
532  * Prevent warnings on NetBSD.  All identifiers beginning with an underscore
533  * followed by an uppercase letter are reserved by the C standard (ISO/IEC
534  * 9899:1999, 7.1.3) to be used by the implementation.  It'd be best to rename
535  * all such instances, but this is less intrusive and error-prone.
536  */
537 #undef _S
538 
539 #define _CY v60.flags.CY
540 #define _OV v60.flags.OV
541 #define _S v60.flags.S
542 #define _Z v60.flags.Z
543 
544 
545 // Defines of all v60 register...
546 #define R0 v60.reg[0]
547 #define R1 v60.reg[1]
548 #define R2 v60.reg[2]
549 #define R3 v60.reg[3]
550 #define R4 v60.reg[4]
551 #define R5 v60.reg[5]
552 #define R6 v60.reg[6]
553 #define R7 v60.reg[7]
554 #define R8 v60.reg[8]
555 #define R9 v60.reg[9]
556 #define R10 v60.reg[10]
557 #define R11 v60.reg[11]
558 #define R12 v60.reg[12]
559 #define R13 v60.reg[13]
560 #define R14 v60.reg[14]
561 #define R15 v60.reg[15]
562 #define R16 v60.reg[16]
563 #define R17 v60.reg[17]
564 #define R18 v60.reg[18]
565 #define R19 v60.reg[19]
566 #define R20 v60.reg[20]
567 #define R21 v60.reg[21]
568 #define R22 v60.reg[22]
569 #define R23 v60.reg[23]
570 #define R24 v60.reg[24]
571 #define R25 v60.reg[25]
572 #define R26 v60.reg[26]
573 #define R27 v60.reg[27]
574 #define R28 v60.reg[28]
575 #define AP v60.reg[29]
576 #define FP v60.reg[30]
577 #define SP v60.reg[31]
578 
579 #define PC		v60.reg[32]
580 #define PSW		v60.reg[33]
581 
582 // Privileged registers
583 #define ISP		v60.reg[36]
584 #define L0SP	v60.reg[37]
585 #define L1SP	v60.reg[38]
586 #define L2SP	v60.reg[39]
587 #define L3SP	v60.reg[40]
588 #define SBR		v60.reg[41]
589 #define TR		v60.reg[42]
590 #define SYCW	v60.reg[43]
591 #define TKCW	v60.reg[44]
592 #define PIR		v60.reg[45]
593 //10-14 reserved
594 #define PSW2	v60.reg[51]
595 #define ATBR0	v60.reg[52]
596 #define ATLR0	v60.reg[53]
597 #define ATBR1	v60.reg[54]
598 #define ATLR1	v60.reg[55]
599 #define ATBR2	v60.reg[56]
600 #define ATLR2	v60.reg[57]
601 #define ATBR3	v60.reg[58]
602 #define ATLR3	v60.reg[59]
603 #define TRMODE v60.reg[60]
604 #define ADTR0	v60.reg[61]
605 #define ADTR1	v60.reg[62]
606 #define ADTMR0	v60.reg[63]
607 #define ADTMR1	v60.reg[64]
608 //29-31 reserved
609 
610 // Register names
611 const char *v60_reg_names[69] = {
612 	"R0", "R1", "R2", "R3",
613 	"R4", "R5", "R6", "R7",
614 	"R8", "R9", "R10", "R11",
615 	"R12", "R13", "R14", "R15",
616 	"R16", "R17", "R18", "R19",
617 	"R20", "R21", "R22", "R23",
618 	"R24", "R25", "R26", "R27",
619 	"R28", "AP", "FP", "SP",
620 	"PC", "PSW","Unk","Unk",
621 	"ISP", "L0SP", "L1SP", "L2SP",
622 	"L3SP", "SBR","TR","SYCW",
623 	"TKCW", "PIR", "Reserved","Reserved",
624 	"Reserved","Reserved","Reserved","PSW2",
625 	"ATBR0", "ATLR0", "ATBR1", "ATLR1",
626 	"ATBR2", "ATLR2", "ATBR3", "ATLR3",
627 	"TRMODE", "ADTR0", "ADTR1","ADTMR0",
628 	"ADTMR1","Reserved","Reserved","Reserved"
629 };
630 
631 // Defines...
632 #define NORMALIZEFLAGS() \
633 { \
634 	_S	= _S  ? 1 : 0; \
635 	_OV	= _OV ? 1 : 0; \
636 	_Z	= _Z  ? 1 : 0; \
637 	_CY	= _CY ? 1 : 0; \
638 }
639 
640 static void v60_try_irq(void);
641 
642 
v60SaveStack(void)643 INLINE void v60SaveStack(void)
644 {
645 	if (PSW & 0x10000000)
646 		ISP = SP;
647 	else
648 		v60.reg[37 + ((PSW >> 24) & 3)] = SP;
649 }
650 
v60ReloadStack(void)651 INLINE void v60ReloadStack(void)
652 {
653 	if (PSW & 0x10000000)
654 		SP = ISP;
655 	else
656 		SP = v60.reg[37 + ((PSW >> 24) & 3)];
657 }
658 
v60ReadPSW(void)659 INLINE UINT32 v60ReadPSW(void)
660 {
661 	PSW &= 0xfffffff0;
662 	PSW |= (_Z?1:0) | (_S?2:0) | (_OV?4:0) | (_CY?8:0);
663 	return PSW;
664 }
665 
v60WritePSW(UINT32 newval)666 INLINE void v60WritePSW(UINT32 newval)
667 {
668 	/* determine if we need to save/restore the stacks */
669 	int updateStack = 0;
670 
671 	/* if the interrupt state is changing, we definitely need to update */
672 	if ((newval ^ PSW) & 0x10000000)
673 		updateStack = 1;
674 
675 	/* if we are not in interrupt mode and the level is changing, we also must update */
676 	else if (!(PSW & 0x10000000) && ((newval ^ PSW) & 0x03000000))
677 		updateStack = 1;
678 
679 	/* save the previous stack value */
680 	if (updateStack)
681 		v60SaveStack();
682 
683 	/* set the new value and update the flags */
684 	PSW = newval;
685 	_Z =  (UINT8)(PSW & 1);
686 	_S =  (UINT8)(PSW & 2);
687 	_OV = (UINT8)(PSW & 4);
688 	_CY = (UINT8)(PSW & 8);
689 
690 	/* fetch the new stack value */
691 	if (updateStack)
692 		v60ReloadStack();
693 }
694 
695 
v60_update_psw_for_exception(int is_interrupt,int target_level)696 INLINE UINT32 v60_update_psw_for_exception(int is_interrupt, int target_level)
697 {
698 	UINT32 oldPSW = v60ReadPSW();
699 	UINT32 newPSW = oldPSW;
700 
701 	// Change to interrupt context
702 	newPSW &= ~(3 << 24);  // PSW.EL = 0
703 	newPSW |= target_level << 24; // set target level
704 	newPSW &= ~(1 << 18);  // PSW.IE = 0
705 	newPSW &= ~(1 << 16);  // PSW.TE = 0
706 	newPSW &= ~(1 << 27);  // PSW.TP = 0
707 	newPSW &= ~(1 << 17);  // PSW.AE = 0
708 	newPSW &= ~(1 << 29);  // PSW.EM = 0
709 	if (is_interrupt)
710 		newPSW |=  (1 << 28);// PSW.IS = 1
711 	newPSW |=  (1 << 31);  // PSW.ASA = 1
712 	v60WritePSW(newPSW);
713 
714 	return oldPSW;
715 }
716 
717 
718 #define GETINTVECT(nint)	MemRead32((SBR & ~0xfff) + (nint)*4)
719 #define EXCEPTION_CODE_AND_SIZE(code, size)	(((code) << 16) | (size))
720 
721 
722 // Addressing mode decoding functions
723 #include "am.c"
724 
725 // Opcode functions
726 #include "op12.c"
727 #include "op2.c"
728 #include "op3.c"
729 #include "op4.c"
730 #include "op5.c"
731 #include "op6.c"
732 #include "op7a.c"
733 
opUNHANDLED(void)734 static UINT32 opUNHANDLED(void)
735 {
736 	//fatalerror("Unhandled OpCode found : %02x at %08x", OpRead16(PC), PC);
737 	return 0; /* never reached, fatalerror won't return */
738 }
739 
740 // Opcode jump table
741 #include "optable.c"
742 
v60_default_irq_cb(int)743 static int v60_default_irq_cb(int )
744 {
745 	return 0;
746 }
747 
v60GetActive()748 INT32 v60GetActive()
749 {
750 	return 0;
751 }
752 
v60CheatRead(UINT32 a)753 UINT8 v60CheatRead(UINT32 a)
754 {
755 	return program_read_byte_16le(a);
756 }
757 
v60WriteROM(UINT32 a,UINT8 d)758 void v60WriteROM(UINT32 a, UINT8 d)
759 {
760 	if (mem[0][a / page_size]) {
761 		mem[0][a / page_size][a & page_mask] = d;
762 		return;
763 	}
764 
765 	if (mem[1][a / page_size]) {
766 		mem[1][a / page_size][a & page_mask] = d;
767 		return;
768 	}
769 
770 	if (mem[2][a / page_size]) {
771 		mem[2][a / page_size][a & page_mask] = d;
772 		return;
773 	}
774 
775 	if (v60_write8) {
776 		return v60_write8(a,d);
777 	}
778 }
779 
base_init()780 static void base_init()
781 {
782 	v60.irq_cb = v60_default_irq_cb;
783 	v60.irq_line = CLEAR_LINE;
784 	v60.nmi_line = CLEAR_LINE;
785 
786 #if 0
787 	state_save_register_item_array(type, index, v60.reg);
788 	state_save_register_item(type, index, v60.irq_line);
789 	state_save_register_item(type, index, v60.nmi_line);
790 	state_save_register_item(type, index, v60.PPC);
791 	state_save_register_item(type, index, _CY);
792 	state_save_register_item(type, index, _OV);
793 	state_save_register_item(type, index, _S);
794 	state_save_register_item(type, index, _Z);
795 #endif
796 }
797 
v60Init()798 void v60Init()
799 {
800 	memset (mem, 0, 3 * ((address_mask + 1) / page_size) * sizeof(UINT8*));
801 
802 	base_init();
803 	// Set PIR (Processor ID) for NEC v60. LSB is reserved to NEC,
804 	// so I don't know what it contains.
805 	PIR = 0x00006000;
806 	v60.info = v60_i;
807 
808 	CpuCheatRegister(0, &v60Config);
809 }
810 
v70Init()811 void v70Init()
812 {
813 	base_init();
814 	// Set PIR (Processor ID) for NEC v70. LSB is reserved to NEC,
815 	// so I don't know what it contains.
816 	PIR = 0x00007000;
817 	v60.info = v70_i;
818 }
819 
v60Scan(INT32 nAction)820 INT32 v60Scan(INT32 nAction)
821 {
822 	struct BurnArea ba;
823 
824 	if ((nAction & ACB_DRIVER_DATA) == 0) {
825 		return 1;
826 	}
827 
828 	ba.Data = &v60.reg;
829 	ba.nLen = sizeof(v60.reg);
830 	ba.szName = "V60 Regs";
831 	BurnAcb(&ba);
832 
833 	SCAN_VAR(v60.flags);
834 	SCAN_VAR(v60.irq_line);
835 	SCAN_VAR(v60.nmi_line);
836 	SCAN_VAR(v60.PPC);
837 	SCAN_VAR(v60.current_cycles);
838 	SCAN_VAR(v60.cycles);
839 
840 	return 0;
841 }
842 
v60SetIRQCallback(int (* callback)(int irqline))843 void v60SetIRQCallback(int (*callback)(int irqline))
844 {
845 	v60.irq_cb = callback;
846 }
847 
v60Reset()848 void v60Reset()
849 {
850 	v60.current_cycles = 0;
851 	PSW		= 0x10000000;
852 	PC		= v60.info.start_pc;
853 	SBR		= 0x00000000;
854 	SYCW	= 0x00000070;
855 	TKCW	= 0x0000e000;
856 	PSW2	= 0x0000f002;
857 	ChangePC(PC);
858 
859 	_CY	= 0;
860 	_OV	= 0;
861 	_S	= 0;
862 	_Z	= 0;
863 }
864 
v60Open(int)865 void v60Open(int)
866 {
867 
868 }
869 
v60Close()870 void v60Close()
871 {
872 
873 }
874 
v60Exit()875 void v60Exit()
876 {
877 
878 }
879 
880 
v60_do_irq(int vector)881 static void v60_do_irq(int vector)
882 {
883 	UINT32 oldPSW = v60_update_psw_for_exception(1, 0);
884 
885 	// Push PC and PSW onto the stack
886 	SP-=4;
887 	MemWrite32(SP, oldPSW);
888 	SP-=4;
889 	MemWrite32(SP, PC);
890 
891 	// Jump to vector for user interrupt
892 	PC = GETINTVECT(vector);
893 }
894 
v60_try_irq(void)895 static void v60_try_irq(void)
896 {
897 	if(v60.irq_line == CLEAR_LINE)
898 		return;
899 	if((PSW & (1<<18)) != 0) {
900 		int vector;
901 		if(v60.irq_line != ASSERT_LINE)
902 			v60.irq_line = CLEAR_LINE;
903 
904 		vector = v60.irq_cb(0);
905 
906 		v60_do_irq(vector + 0x40);
907 	} else if(v60.irq_line == PULSE_LINE)
908 		v60.irq_line = CLEAR_LINE;
909 }
910 
set_irq_line(int irqline,int state)911 static void set_irq_line(int irqline, int state)
912 {
913 	if(irqline == INPUT_LINE_NMI) {
914 		switch(state) {
915 		case ASSERT_LINE:
916 			if(v60.nmi_line == CLEAR_LINE) {
917 				v60.nmi_line = ASSERT_LINE;
918 				v60_do_irq(2);
919 			}
920 			break;
921 		case CLEAR_LINE:
922 			v60.nmi_line = CLEAR_LINE;
923 			break;
924 		case HOLD_LINE:
925 		case PULSE_LINE:
926 			v60.nmi_line = CLEAR_LINE;
927 			v60_do_irq(2);
928 			break;
929 		}
930 	} else {
931 		v60.irq_line = state;
932 		v60_try_irq();
933 	}
934 }
935 
936 // Actual cycles/instruction is unknown
937 
v60Run(int cycles)938 INT32 v60Run(int cycles)
939 {
940 	UINT32 inc;
941 
942 	v60.cycles = cycles;
943 
944 	v60_ICount = cycles;
945 	if(v60.irq_line != CLEAR_LINE)
946 		v60_try_irq();
947 	while(v60_ICount >= 0) {
948 		v60.PPC = PC;
949 	//	CALL_MAME_DEBUG;
950 		v60_ICount -= 8;	/* fix me -- this is just an average */
951 		inc = OpCodeTable[OpRead8(PC)]();
952 		PC += inc;
953 		if(v60.irq_line != CLEAR_LINE)
954 			v60_try_irq();
955 	}
956 
957 	cycles = cycles - v60_ICount;
958 
959 	v60.cycles = v60_ICount = 0;
960 
961 	v60.current_cycles += cycles;
962 
963 	return cycles;
964 }
965 
v60SetIRQLine(INT32 irqline,INT32 state)966 void v60SetIRQLine(INT32 irqline, INT32 state)
967 {
968 	if (state == CPU_IRQSTATUS_AUTO) {
969 	//	INT32 tmp0 = v60.current_cycles;
970 	//	INT32 tmp1 = v60.cycles;
971 		set_irq_line(irqline,1);
972 		v60Run(100);
973 	//	if (tmp1) tmp1 -= 100;
974 		set_irq_line(irqline,0);
975 		v60Run(100);
976 	}
977 	else
978 	{
979 		set_irq_line(irqline,state);
980 	}
981 }
982 
v60TotalCycles()983 INT32 v60TotalCycles()
984 {
985 	return v60.current_cycles + (v60.cycles - v60_ICount);
986 }
987 
v60RunEnd()988 void v60RunEnd()
989 {
990 	v60_ICount = 0;
991 }
992 
v60NewFrame()993 void v60NewFrame()
994 {
995 	v60.current_cycles = 0;
996 }
997 
998 #if 0
999 static void v60_get_context(void *dst)
1000 {
1001 	if(dst)
1002 		*(struct v60info *)dst = v60;
1003 }
1004 
1005 static void v60_set_context(void *src)
1006 {
1007 	if(src)
1008 	{
1009 		v60 = *(struct v60info *)src;
1010 		ChangePC(PC);
1011 	}
1012 }
1013 #endif
1014 
1015 #ifdef MAME_DEBUG
1016 offs_t v60_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
1017 offs_t v70_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
1018 #endif /* MAME_DEBUG */
1019 
1020 
1021 /**************************************************************************
1022  * Generic set_info
1023  **************************************************************************/
1024 
1025 #if 0
1026 static void v60_set_info(UINT32 state, union cpuinfo *info)
1027 {
1028 	switch (state)
1029 	{
1030 		/* --- the following bits of info are set as 64-bit signed integers --- */
1031 		case CPUINFO_INT_INPUT_STATE + 0:				set_irq_line(0, info->i);				break;
1032 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	set_irq_line(INPUT_LINE_NMI, info->i);	break;
1033 
1034 		case CPUINFO_INT_PC:							PC = info->i; ChangePC(PC);				break;
1035 		case CPUINFO_INT_SP:							SP = info->i;							break;
1036 
1037 		case CPUINFO_INT_REGISTER + V60_R0:				R0 = info->i;							break;
1038 		case CPUINFO_INT_REGISTER + V60_R1:				R1 = info->i;							break;
1039 		case CPUINFO_INT_REGISTER + V60_R2:				R2 = info->i;							break;
1040 		case CPUINFO_INT_REGISTER + V60_R3:				R3 = info->i;							break;
1041 		case CPUINFO_INT_REGISTER + V60_R4:				R4 = info->i;							break;
1042 		case CPUINFO_INT_REGISTER + V60_R5:				R5 = info->i;							break;
1043 		case CPUINFO_INT_REGISTER + V60_R6:				R6 = info->i;							break;
1044 		case CPUINFO_INT_REGISTER + V60_R7:				R7 = info->i;							break;
1045 		case CPUINFO_INT_REGISTER + V60_R8:				R8 = info->i;							break;
1046 		case CPUINFO_INT_REGISTER + V60_R9:				R9 = info->i;							break;
1047 		case CPUINFO_INT_REGISTER + V60_R10:			R10 = info->i;							break;
1048 		case CPUINFO_INT_REGISTER + V60_R11:			R11 = info->i;							break;
1049 		case CPUINFO_INT_REGISTER + V60_R12:			R12 = info->i;							break;
1050 		case CPUINFO_INT_REGISTER + V60_R13:			R13 = info->i;							break;
1051 		case CPUINFO_INT_REGISTER + V60_R14:			R14 = info->i;							break;
1052 		case CPUINFO_INT_REGISTER + V60_R15:			R15 = info->i;							break;
1053 		case CPUINFO_INT_REGISTER + V60_R16:			R16 = info->i;							break;
1054 		case CPUINFO_INT_REGISTER + V60_R17:			R17 = info->i;							break;
1055 		case CPUINFO_INT_REGISTER + V60_R18:			R18 = info->i;							break;
1056 		case CPUINFO_INT_REGISTER + V60_R19:			R19 = info->i;							break;
1057 		case CPUINFO_INT_REGISTER + V60_R20:			R20 = info->i;							break;
1058 		case CPUINFO_INT_REGISTER + V60_R21:			R21 = info->i;							break;
1059 		case CPUINFO_INT_REGISTER + V60_R22:			R22 = info->i;							break;
1060 		case CPUINFO_INT_REGISTER + V60_R23:			R23 = info->i;							break;
1061 		case CPUINFO_INT_REGISTER + V60_R24:			R24 = info->i;							break;
1062 		case CPUINFO_INT_REGISTER + V60_R25:			R25 = info->i;							break;
1063 		case CPUINFO_INT_REGISTER + V60_R26:			R26 = info->i;							break;
1064 		case CPUINFO_INT_REGISTER + V60_R27:			R27 = info->i;							break;
1065 		case CPUINFO_INT_REGISTER + V60_R28:			R28 = info->i;							break;
1066 		case CPUINFO_INT_REGISTER + V60_AP:				AP = info->i;							break;
1067 		case CPUINFO_INT_REGISTER + V60_FP:				FP = info->i;							break;
1068 		case CPUINFO_INT_REGISTER + V60_SP:				SP = info->i;							break;
1069 		case CPUINFO_INT_REGISTER + V60_PC:				PC = info->i;							break;
1070 		case CPUINFO_INT_REGISTER + V60_PSW:			v60WritePSW(info->i);					break;
1071 		case CPUINFO_INT_REGISTER + V60_ISP:			ISP = info->i;							break;
1072 		case CPUINFO_INT_REGISTER + V60_L0SP:			L0SP = info->i;							break;
1073 		case CPUINFO_INT_REGISTER + V60_L1SP:			L1SP = info->i;							break;
1074 		case CPUINFO_INT_REGISTER + V60_L2SP:			L2SP = info->i;							break;
1075 		case CPUINFO_INT_REGISTER + V60_L3SP:			L3SP = info->i;							break;
1076 		case CPUINFO_INT_REGISTER + V60_SBR:			SBR = info->i;							break;
1077 		case CPUINFO_INT_REGISTER + V60_TR:				TR = info->i;							break;
1078 		case CPUINFO_INT_REGISTER + V60_SYCW:			SYCW = info->i;							break;
1079 		case CPUINFO_INT_REGISTER + V60_TKCW:			TKCW = info->i;							break;
1080 		case CPUINFO_INT_REGISTER + V60_PIR:			PIR = info->i;							break;
1081 		case CPUINFO_INT_REGISTER + V60_PSW2:			PSW2 = info->i;							break;
1082 		case CPUINFO_INT_REGISTER + V60_ATBR0:			ATBR0 = info->i;						break;
1083 		case CPUINFO_INT_REGISTER + V60_ATLR0:			ATLR0 = info->i;						break;
1084 		case CPUINFO_INT_REGISTER + V60_ATBR1:			ATBR1 = info->i;						break;
1085 		case CPUINFO_INT_REGISTER + V60_ATLR1:			ATLR1 = info->i;						break;
1086 		case CPUINFO_INT_REGISTER + V60_ATBR2:			ATBR2 = info->i;						break;
1087 		case CPUINFO_INT_REGISTER + V60_ATLR2:			ATLR2 = info->i;						break;
1088 		case CPUINFO_INT_REGISTER + V60_ATBR3:			ATBR3 = info->i;						break;
1089 		case CPUINFO_INT_REGISTER + V60_ATLR3:			ATLR3 = info->i;						break;
1090 		case CPUINFO_INT_REGISTER + V60_TRMODE:			TRMODE = info->i;						break;
1091 		case CPUINFO_INT_REGISTER + V60_ADTR0:			ADTR0 = info->i;						break;
1092 		case CPUINFO_INT_REGISTER + V60_ADTR1:			ADTR1 = info->i;						break;
1093 		case CPUINFO_INT_REGISTER + V60_ADTMR0:			ADTMR0 = info->i;						break;
1094 		case CPUINFO_INT_REGISTER + V60_ADTMR1:			ADTMR1 = info->i;						break;
1095 	}
1096 }
1097 
1098 
1099 
1100 /**************************************************************************
1101  * Generic get_info
1102  **************************************************************************/
1103 
1104 void v60_get_info(UINT32 state, union cpuinfo *info)
1105 {
1106 	switch (state)
1107 	{
1108 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1109 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(v60);					break;
1110 		case CPUINFO_INT_INPUT_LINES:					info->i = 1;							break;
1111 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
1112 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
1113 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
1114 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
1115 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 22;							break;
1116 		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
1117 		case CPUINFO_INT_MAX_CYCLES:					info->i = 1;							break;
1118 
1119 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 16;					break;
1120 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 24;					break;
1121 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
1122 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
1123 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1124 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1125 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 16;					break;
1126 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 24;					break;
1127 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
1128 
1129 		case CPUINFO_INT_INPUT_STATE + 0:				info->i = v60.irq_line;					break;
1130 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	info->i = v60.nmi_line;					break;
1131 
1132 		case CPUINFO_INT_PREVIOUSPC:					info->i = v60.PPC;							break;
1133 
1134 		case CPUINFO_INT_REGISTER + V60_R0:				info->i = R0;							break;
1135 		case CPUINFO_INT_REGISTER + V60_R1:				info->i = R1;							break;
1136 		case CPUINFO_INT_REGISTER + V60_R2:				info->i = R2;							break;
1137 		case CPUINFO_INT_REGISTER + V60_R3:				info->i = R3;							break;
1138 		case CPUINFO_INT_REGISTER + V60_R4:				info->i = R4;							break;
1139 		case CPUINFO_INT_REGISTER + V60_R5:				info->i = R5;							break;
1140 		case CPUINFO_INT_REGISTER + V60_R6:				info->i = R6;							break;
1141 		case CPUINFO_INT_REGISTER + V60_R7:				info->i = R7;							break;
1142 		case CPUINFO_INT_REGISTER + V60_R8:				info->i = R8;							break;
1143 		case CPUINFO_INT_REGISTER + V60_R9:				info->i = R9;							break;
1144 		case CPUINFO_INT_REGISTER + V60_R10:			info->i = R10;							break;
1145 		case CPUINFO_INT_REGISTER + V60_R11:			info->i = R11;							break;
1146 		case CPUINFO_INT_REGISTER + V60_R12:			info->i = R12;							break;
1147 		case CPUINFO_INT_REGISTER + V60_R13:			info->i = R13;							break;
1148 		case CPUINFO_INT_REGISTER + V60_R14:			info->i = R14;							break;
1149 		case CPUINFO_INT_REGISTER + V60_R15:			info->i = R15;							break;
1150 		case CPUINFO_INT_REGISTER + V60_R16:			info->i = R16;							break;
1151 		case CPUINFO_INT_REGISTER + V60_R17:			info->i = R17;							break;
1152 		case CPUINFO_INT_REGISTER + V60_R18:			info->i = R18;							break;
1153 		case CPUINFO_INT_REGISTER + V60_R19:			info->i = R19;							break;
1154 		case CPUINFO_INT_REGISTER + V60_R20:			info->i = R20;							break;
1155 		case CPUINFO_INT_REGISTER + V60_R21:			info->i = R21;							break;
1156 		case CPUINFO_INT_REGISTER + V60_R22:			info->i = R22;							break;
1157 		case CPUINFO_INT_REGISTER + V60_R23:			info->i = R23;							break;
1158 		case CPUINFO_INT_REGISTER + V60_R24:			info->i = R24;							break;
1159 		case CPUINFO_INT_REGISTER + V60_R25:			info->i = R25;							break;
1160 		case CPUINFO_INT_REGISTER + V60_R26:			info->i = R26;							break;
1161 		case CPUINFO_INT_REGISTER + V60_R27:			info->i = R27;							break;
1162 		case CPUINFO_INT_REGISTER + V60_R28:			info->i = R28;							break;
1163 		case CPUINFO_INT_REGISTER + V60_AP:				info->i = AP;							break;
1164 		case CPUINFO_INT_REGISTER + V60_FP:				info->i = FP;							break;
1165 		case CPUINFO_INT_SP:
1166 		case CPUINFO_INT_REGISTER + V60_SP:				info->i = SP;							break;
1167 		case CPUINFO_INT_PC:
1168 		case CPUINFO_INT_REGISTER + V60_PC:				info->i = PC;							break;
1169 		case CPUINFO_INT_REGISTER + V60_PSW:			info->i = v60ReadPSW();					break;
1170 		case CPUINFO_INT_REGISTER + V60_ISP:			info->i = ISP;							break;
1171 		case CPUINFO_INT_REGISTER + V60_L0SP:			info->i = L0SP;							break;
1172 		case CPUINFO_INT_REGISTER + V60_L1SP:			info->i = L1SP;							break;
1173 		case CPUINFO_INT_REGISTER + V60_L2SP:			info->i = L2SP;							break;
1174 		case CPUINFO_INT_REGISTER + V60_L3SP:			info->i = L3SP;							break;
1175 		case CPUINFO_INT_REGISTER + V60_SBR:			info->i = SBR;							break;
1176 		case CPUINFO_INT_REGISTER + V60_TR:				info->i = TR;							break;
1177 		case CPUINFO_INT_REGISTER + V60_SYCW:			info->i = SYCW;							break;
1178 		case CPUINFO_INT_REGISTER + V60_TKCW:			info->i = TKCW;							break;
1179 		case CPUINFO_INT_REGISTER + V60_PIR:			info->i = PIR;							break;
1180 		case CPUINFO_INT_REGISTER + V60_PSW2:			info->i = PSW2;							break;
1181 		case CPUINFO_INT_REGISTER + V60_ATBR0:			info->i = ATBR0;						break;
1182 		case CPUINFO_INT_REGISTER + V60_ATLR0:			info->i = ATLR0;						break;
1183 		case CPUINFO_INT_REGISTER + V60_ATBR1:			info->i = ATBR1;						break;
1184 		case CPUINFO_INT_REGISTER + V60_ATLR1:			info->i = ATLR1;						break;
1185 		case CPUINFO_INT_REGISTER + V60_ATBR2:			info->i = ATBR2;						break;
1186 		case CPUINFO_INT_REGISTER + V60_ATLR2:			info->i = ATLR2;						break;
1187 		case CPUINFO_INT_REGISTER + V60_ATBR3:			info->i = ATBR3;						break;
1188 		case CPUINFO_INT_REGISTER + V60_ATLR3:			info->i = ATLR3;						break;
1189 		case CPUINFO_INT_REGISTER + V60_TRMODE:			info->i = TRMODE;						break;
1190 		case CPUINFO_INT_REGISTER + V60_ADTR0:			info->i = ADTR0;						break;
1191 		case CPUINFO_INT_REGISTER + V60_ADTR1:			info->i = ADTR1;						break;
1192 		case CPUINFO_INT_REGISTER + V60_ADTMR0:			info->i = ADTMR0;						break;
1193 		case CPUINFO_INT_REGISTER + V60_ADTMR1:			info->i = ADTMR1;						break;
1194 
1195 		/* --- the following bits of info are returned as pointers to data or functions --- */
1196 		case CPUINFO_PTR_SET_INFO:						info->setinfo = v60_set_info;			break;
1197 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = v60_get_context;		break;
1198 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = v60_set_context;		break;
1199 		case CPUINFO_PTR_INIT:							info->init = v60_init;					break;
1200 		case CPUINFO_PTR_RESET:							info->reset = v60_reset;				break;
1201 		case CPUINFO_PTR_EXIT:							info->exit = v60_exit;					break;
1202 		case CPUINFO_PTR_EXECUTE:						info->execute = v60_execute;			break;
1203 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
1204 #ifdef MAME_DEBUG
1205 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = v60_dasm;			break;
1206 #endif /* MAME_DEBUG */
1207 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &v60_ICount;				break;
1208 
1209 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1210 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "V60"); break;
1211 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "NEC V60"); break;
1212 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s = cpuintrf_temp_str(), "1.0"); break;
1213 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s = cpuintrf_temp_str(), __FILE__); break;
1214 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s = cpuintrf_temp_str(), "Farfetch'd and R.Belmont"); break;
1215 
1216 		case CPUINFO_STR_FLAGS:							strcpy(info->s = cpuintrf_temp_str(), " "); break;
1217 
1218 		case CPUINFO_STR_REGISTER + V60_R0:				sprintf(info->s = cpuintrf_temp_str(), "R0:%08X", R0);	break;
1219 		case CPUINFO_STR_REGISTER + V60_R1:				sprintf(info->s = cpuintrf_temp_str(), "R1:%08X", R1);	break;
1220 		case CPUINFO_STR_REGISTER + V60_R2:				sprintf(info->s = cpuintrf_temp_str(), "R2:%08X", R2);	break;
1221 		case CPUINFO_STR_REGISTER + V60_R3:				sprintf(info->s = cpuintrf_temp_str(), "R3:%08X", R3);	break;
1222 		case CPUINFO_STR_REGISTER + V60_R4:				sprintf(info->s = cpuintrf_temp_str(), "R4:%08X", R4);	break;
1223 		case CPUINFO_STR_REGISTER + V60_R5:				sprintf(info->s = cpuintrf_temp_str(), "R5:%08X", R5);	break;
1224 		case CPUINFO_STR_REGISTER + V60_R6:				sprintf(info->s = cpuintrf_temp_str(), "R6:%08X", R6);	break;
1225 		case CPUINFO_STR_REGISTER + V60_R7:				sprintf(info->s = cpuintrf_temp_str(), "R7:%08X", R7);	break;
1226 		case CPUINFO_STR_REGISTER + V60_R8:				sprintf(info->s = cpuintrf_temp_str(), "R8:%08X", R8);	break;
1227 		case CPUINFO_STR_REGISTER + V60_R9:				sprintf(info->s = cpuintrf_temp_str(), "R9:%08X", R9);	break;
1228 		case CPUINFO_STR_REGISTER + V60_R10:			sprintf(info->s = cpuintrf_temp_str(), "R10:%08X", R10); break;
1229 		case CPUINFO_STR_REGISTER + V60_R11:			sprintf(info->s = cpuintrf_temp_str(), "R11:%08X", R11); break;
1230 		case CPUINFO_STR_REGISTER + V60_R12:			sprintf(info->s = cpuintrf_temp_str(), "R12:%08X", R12); break;
1231 		case CPUINFO_STR_REGISTER + V60_R13:			sprintf(info->s = cpuintrf_temp_str(), "R13:%08X", R13); break;
1232 		case CPUINFO_STR_REGISTER + V60_R14:			sprintf(info->s = cpuintrf_temp_str(), "R14:%08X", R14); break;
1233 		case CPUINFO_STR_REGISTER + V60_R15:			sprintf(info->s = cpuintrf_temp_str(), "R15:%08X", R15); break;
1234 		case CPUINFO_STR_REGISTER + V60_R16:			sprintf(info->s = cpuintrf_temp_str(), "R16:%08X", R16); break;
1235 		case CPUINFO_STR_REGISTER + V60_R17:			sprintf(info->s = cpuintrf_temp_str(), "R17:%08X", R17); break;
1236 		case CPUINFO_STR_REGISTER + V60_R18:			sprintf(info->s = cpuintrf_temp_str(), "R18:%08X", R18); break;
1237 		case CPUINFO_STR_REGISTER + V60_R19:			sprintf(info->s = cpuintrf_temp_str(), "R19:%08X", R19); break;
1238 		case CPUINFO_STR_REGISTER + V60_R20:			sprintf(info->s = cpuintrf_temp_str(), "R20:%08X", R20); break;
1239 		case CPUINFO_STR_REGISTER + V60_R21:			sprintf(info->s = cpuintrf_temp_str(), "R21:%08X", R21); break;
1240 		case CPUINFO_STR_REGISTER + V60_R22:			sprintf(info->s = cpuintrf_temp_str(), "R22:%08X", R22); break;
1241 		case CPUINFO_STR_REGISTER + V60_R23:			sprintf(info->s = cpuintrf_temp_str(), "R23:%08X", R23); break;
1242 		case CPUINFO_STR_REGISTER + V60_R24:			sprintf(info->s = cpuintrf_temp_str(), "R24:%08X", R24); break;
1243 		case CPUINFO_STR_REGISTER + V60_R25:			sprintf(info->s = cpuintrf_temp_str(), "R25:%08X", R25); break;
1244 		case CPUINFO_STR_REGISTER + V60_R26:			sprintf(info->s = cpuintrf_temp_str(), "R26:%08X", R26); break;
1245 		case CPUINFO_STR_REGISTER + V60_R27:			sprintf(info->s = cpuintrf_temp_str(), "R27:%08X", R27); break;
1246 		case CPUINFO_STR_REGISTER + V60_R28:			sprintf(info->s = cpuintrf_temp_str(), "R28:%08X", R28); break;
1247 		case CPUINFO_STR_REGISTER + V60_AP:				sprintf(info->s = cpuintrf_temp_str(), "AP:%08X", AP); break;
1248 		case CPUINFO_STR_REGISTER + V60_FP:				sprintf(info->s = cpuintrf_temp_str(), "FP:%08X", FP); break;
1249 		case CPUINFO_STR_REGISTER + V60_SP:				sprintf(info->s = cpuintrf_temp_str(), "SP:%08X", SP); break;
1250 		case CPUINFO_STR_REGISTER + V60_PC:				sprintf(info->s = cpuintrf_temp_str(), "PC:%08X", PC); break;
1251 		case CPUINFO_STR_REGISTER + V60_PSW:			sprintf(info->s = cpuintrf_temp_str(), "PSW:%08X", v60ReadPSW()); break;
1252 		case CPUINFO_STR_REGISTER + V60_ISP:			sprintf(info->s = cpuintrf_temp_str(), "ISP:%08X", ISP); break;
1253 		case CPUINFO_STR_REGISTER + V60_L0SP:			sprintf(info->s = cpuintrf_temp_str(), "L0SP:%08X", L0SP); break;
1254 		case CPUINFO_STR_REGISTER + V60_L1SP:			sprintf(info->s = cpuintrf_temp_str(), "L1SP:%08X", L1SP); break;
1255 		case CPUINFO_STR_REGISTER + V60_L2SP:			sprintf(info->s = cpuintrf_temp_str(), "L2SP:%08X", L2SP); break;
1256 		case CPUINFO_STR_REGISTER + V60_L3SP:			sprintf(info->s = cpuintrf_temp_str(), "L3SP:%08X", L3SP); break;
1257 		case CPUINFO_STR_REGISTER + V60_SBR:			sprintf(info->s = cpuintrf_temp_str(), "SBR:%08X", SBR); break;
1258 		case CPUINFO_STR_REGISTER + V60_TR:				sprintf(info->s = cpuintrf_temp_str(), "TR:%08X", TR); break;
1259 		case CPUINFO_STR_REGISTER + V60_SYCW:			sprintf(info->s = cpuintrf_temp_str(), "SYCW:%08X", SYCW); break;
1260 		case CPUINFO_STR_REGISTER + V60_TKCW:			sprintf(info->s = cpuintrf_temp_str(), "TKCW:%08X", TKCW); break;
1261 		case CPUINFO_STR_REGISTER + V60_PIR:			sprintf(info->s = cpuintrf_temp_str(), "PIR:%08X", PIR); break;
1262 		case CPUINFO_STR_REGISTER + V60_PSW2:			sprintf(info->s = cpuintrf_temp_str(), "PSW2:%08X", PSW2); break;
1263 		case CPUINFO_STR_REGISTER + V60_ATBR0:			sprintf(info->s = cpuintrf_temp_str(), "ATBR0:%08X", ATBR0); break;
1264 		case CPUINFO_STR_REGISTER + V60_ATLR0:			sprintf(info->s = cpuintrf_temp_str(), "ATLR0:%08X", ATLR0); break;
1265 		case CPUINFO_STR_REGISTER + V60_ATBR1:			sprintf(info->s = cpuintrf_temp_str(), "ATBR1:%08X", ATBR1); break;
1266 		case CPUINFO_STR_REGISTER + V60_ATLR1:			sprintf(info->s = cpuintrf_temp_str(), "ATLR1:%08X", ATLR1); break;
1267 		case CPUINFO_STR_REGISTER + V60_ATBR2:			sprintf(info->s = cpuintrf_temp_str(), "ATBR2:%08X", ATBR2); break;
1268 		case CPUINFO_STR_REGISTER + V60_ATLR2:			sprintf(info->s = cpuintrf_temp_str(), "ATLR2:%08X", ATLR2); break;
1269 		case CPUINFO_STR_REGISTER + V60_ATBR3:			sprintf(info->s = cpuintrf_temp_str(), "ATBR3:%08X", ATBR3); break;
1270 		case CPUINFO_STR_REGISTER + V60_ATLR3:			sprintf(info->s = cpuintrf_temp_str(), "ATLR3:%08X", ATLR3); break;
1271 		case CPUINFO_STR_REGISTER + V60_TRMODE:			sprintf(info->s = cpuintrf_temp_str(), "TRMODE:%08X", TRMODE); break;
1272 		case CPUINFO_STR_REGISTER + V60_ADTR0:			sprintf(info->s = cpuintrf_temp_str(), "ADTR0:%08X", ADTR0); break;
1273 		case CPUINFO_STR_REGISTER + V60_ADTR1:			sprintf(info->s = cpuintrf_temp_str(), "ADTR1:%08X", ADTR1); break;
1274 		case CPUINFO_STR_REGISTER + V60_ADTMR0:			sprintf(info->s = cpuintrf_temp_str(), "ADTMR0:%08X", ADTMR0); break;
1275 		case CPUINFO_STR_REGISTER + V60_ADTMR1:			sprintf(info->s = cpuintrf_temp_str(), "ADTMR1:%08X", ADTMR1); break;
1276 	}
1277 }
1278 
1279 
1280 /**************************************************************************
1281  * CPU-specific set_info
1282  **************************************************************************/
1283 
1284 void v70_get_info(UINT32 state, union cpuinfo *info)
1285 {
1286 	switch (state)
1287 	{
1288 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1289 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 32;					break;
1290 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32;					break;
1291 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
1292 
1293 		/* --- the following bits of info are returned as pointers to data or functions --- */
1294 		case CPUINFO_PTR_INIT:							info->init = v70_init;					break;
1295 #ifdef MAME_DEBUG
1296 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = v70_dasm;			break;
1297 #endif /* MAME_DEBUG */
1298 
1299 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1300 		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "V70"); break;
1301 
1302 		default:
1303 			v60_get_info(state, info);
1304 			break;
1305 	}
1306 }
1307 #endif
1308