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