1 /*****************************************************************************
2  *
3  *   m6502.c
4  *   Portable 6502/65c02/65sc02/6510/n2a03 emulator V1.2
5  *
6  *   Copyright Juergen Buchmueller, all rights reserved.
7  *   65sc02 core Copyright Peter Trauner.
8  *   Deco16 portions Copyright Bryan McPhail.
9  *
10  *   - This source code is released as freeware for non-commercial purposes.
11  *   - You are free to use and redistribute this code in modified or
12  *     unmodified form, provided you list me in the credits.
13  *   - If you modify this source code, you must add a notice to each modified
14  *     source file that it has been changed.  If you're a nice person, you
15  *     will clearly mark each change too.  :)
16  *   - If you wish to use this for commercial purposes, please contact me at
17  *     pullmoll@t-online.de
18  *   - The author of this copywritten work reserves the right to change the
19  *     terms of its usage and license at any time, including retroactively
20  *   - This entire notice must remain in the source code.
21  *
22  *****************************************************************************/
23 /* 2.February 2000 PeT added 65sc02 subtype */
24 /* 10.March   2000 PeT added 6502 set overflow input line */
25 /* 13.September 2000 PeT N2A03 jmp indirect */
26 
27 #include "burnint.h"
28 #include "m6502.h"
29 
30 #define M6502_INLINE
31 
32 #if ((HAS_M65SC02 || HAS_DECO16) && !HAS_M65C02)
33 #undef HAS_M65C02
34 #define HAS_M65C02 1
35 #endif
36 
37 #define change_pc(newpc)	m6502.pc.d = (newpc)
38 
39 void	(*const *insnActive)(void);
40 
41 
42 typedef UINT8 (*deco_function)(UINT16 address, UINT8 opcode);
43 
44 static deco_function Cpu7Write[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
45 
46 extern INT32 M6502GetActive();
47 
48 #include "ops02.h"
49 #include "ill02.h"
50 
51 
52 #define M6502_NMI_VEC	0xfffa
53 #define M6502_RST_VEC	0xfffc
54 #define M6502_IRQ_VEC	0xfffe
55 
56 #define DECO16_RST_VEC	0xfff0
57 #define DECO16_IRQ_VEC	0xfff2
58 #define DECO16_NMI_VEC	0xfff4
59 
60 #define VERBOSE 0
61 
62 #define LOG(x)	do { if (VERBOSE) logerror x; } while (0)
63 
64 /****************************************************************************
65  * The 6502 registers.
66  ****************************************************************************/
67 
68 static int m6502_IntOccured = 0;
69 static int m6502_ICount = 0;
70 
71 static m6502_Regs m6502;
72 
DecoCpu7SetDecode(UINT8 (* write)(UINT16,UINT8))73 void DecoCpu7SetDecode(UINT8 (*write)(UINT16,UINT8))
74 {
75 	Cpu7Write[M6502GetActive()] = write;
76 }
77 
78 
79 //static READ8_HANDLER( default_rdmem_id ) { return program_read_byte_8le(offset); }
80 //static WRITE8_HANDLER( default_wdmem_id ) { program_write_byte_8le(offset, data); }
81 
82 /***************************************************************
83  * include the opcode macros, functions and tables
84  ***************************************************************/
85 #include "t6502.c"
86 
87 #if (HAS_M6510)
88 //#include "t6510.c"
89 #define insn6510 insn6502
90 #endif
91 
92 #include "opsn2a03.h"
93 
94 #if (HAS_N2A03)
95 #include "tn2a03.c"
96 #endif
97 
98 #include "opsc02.h"
99 
100 #if (HAS_M65C02)
101 #include "t65c02.c"
102 #endif
103 
104 #if (HAS_M65SC02)
105 #include "t65sc02.c"
106 #endif
107 
108 #if (HAS_DECO16)
109 #include "tdeco16.c"
110 #endif
111 
112 /*****************************************************************************
113  *
114  *      6502 CPU interface functions
115  *
116  *****************************************************************************/
117 
m6502_core_exit()118 void m6502_core_exit()
119 {
120 	for (INT32 i = 0; i < 8; i++) {
121 		Cpu7Write[i] = NULL;
122 	}
123 }
124 
m6502_common_init(UINT8 subtype,void (* const * insn)(void))125 static void m6502_common_init(UINT8 subtype, void (*const *insn)(void)/*, const char *type*/)
126 {
127 	memset(&m6502, 0, sizeof(m6502));
128 //	m6502.irq_callback = irqcallback;
129 	m6502.subtype = subtype;
130 	//m6502.insn = insn;
131 	insnActive = insn;
132 //	m6502.rdmem_id = default_rdmem_id;
133 //	m6502.wrmem_id = default_wdmem_id;
134 
135 //	state_save_register_item(type, index, m6502.pc.w.l);
136 //	state_save_register_item(type, index, m6502.sp.w.l);
137 //	state_save_register_item(type, index, m6502.p);
138 //	state_save_register_item(type, index, m6502.a);
139 //	state_save_register_item(type, index, m6502.x);
140 //	state_save_register_item(type, index, m6502.y);
141 //	state_save_register_item(type, index, m6502.pending_irq);
142 //	state_save_register_item(type, index, m6502.after_cli);
143 //	state_save_register_item(type, index, m6502.nmi_state);
144 //	state_save_register_item(type, index, m6502.irq_state);
145 //	state_save_register_item(type, index, m6502.so_state);
146 
147 #if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501)
148 	if (subtype == SUBTYPE_6510)
149 	{
150 //		state_save_register_item(type, index, m6502.port);
151 //		state_save_register_item(type, index, m6502.ddr);
152 	}
153 #endif
154 }
155 
m6502_init()156 void m6502_init()
157 {
158 	m6502_common_init(SUBTYPE_6502, insn6502/*, "m6502"*/);
159 }
160 
m6502_reset(void)161 void m6502_reset(void)
162 {
163 	/* wipe out the rest of the m6502 structure */
164 	/* read the reset vector into PC */
165 	PCL = RDMEM(M6502_RST_VEC);
166 	PCH = RDMEM(M6502_RST_VEC+1);
167 
168 	m6502.sp.d = 0x01ff;	/* stack pointer starts at page 1 offset FF */
169 	m6502.p = F_T|F_I|F_Z|F_B|(P&F_D);	/* set T, I and Z flags */
170 	m6502.pending_irq = 0;	/* nonzero if an IRQ is pending */
171 	m6502.after_cli = 0;	/* pending IRQ and last insn cleared I */
172 	m6502.irq_state = 0;
173 	m6502.nmi_state = 0;
174 	m6502.cpu7written = 0;
175 
176 	change_pc(PCD);
177 }
178 
m6502_exit(void)179 void m6502_exit(void)
180 {
181 	/* nothing to do yet */
182 }
183 
m6502_get_context(void * dst)184 void m6502_get_context (void *dst)
185 {
186 	if( dst )
187 		*(m6502_Regs*)dst = m6502;
188 }
189 
m6502_set_context(void * src)190 void m6502_set_context (void *src)
191 {
192 	if( src )
193 	{
194 		m6502 = *(m6502_Regs*)src;
195 		if (m6502.subtype == SUBTYPE_6502)  insnActive = insn6502;
196 		if (m6502.subtype == SUBTYPE_65C02) insnActive = insn65c02;
197 		if (m6502.subtype == SUBTYPE_2A03)  insnActive = insn2a03;
198 		if (m6502.subtype == SUBTYPE_65SC02)insnActive = insn65sc02;
199 		if (m6502.subtype == SUBTYPE_DECO16)insnActive = insndeco16;
200 		if (m6502.subtype == SUBTYPE_6510)  insnActive = insn6510;
201 		change_pc(PCD);
202 	}
203 }
204 
m6502_set_irq_hold()205 void m6502_set_irq_hold()
206 {
207 	m6502.hold_irq = 1;
208 }
209 
m6502_take_irq(void)210 M6502_INLINE void m6502_take_irq(void)
211 {
212 	if( !(P & F_I) )
213 	{
214 		EAD = M6502_IRQ_VEC;
215 		m6502_ICount -= 2;
216 		PUSH(PCH);
217 		PUSH(PCL);
218 		PUSH(P & ~F_B);
219 		P |= F_I;		/* set I flag */
220 		PCL = RDMEM(EAD);
221 		PCH = RDMEM(EAD+1);
222 //		LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
223 		/* call back the cpuintrf to let it clear the line */
224 
225 		if (m6502.hold_irq) {
226 			m6502.hold_irq = 0;
227 			m6502.irq_state = M6502_CLEAR_LINE;
228 		}
229 
230 		if (m6502.irq_callback) (*m6502.irq_callback)(0);
231 		change_pc(PCD);
232 
233 		m6502.cpu7written = 0;
234 	}
235 	m6502.pending_irq = 0;
236 }
237 
m6502_releaseslice()238 int m6502_releaseslice()
239 {
240 	m6502_ICount = 0;
241 
242 	return 0;
243 }
244 
245 static int segmentcycles = 0;
246 
m6502_get_segmentcycles()247 int m6502_get_segmentcycles()
248 {
249 	return segmentcycles - m6502_ICount;
250 }
251 
m6502_execute(int cycles)252 int m6502_execute(int cycles)
253 {
254 	segmentcycles = cycles;
255 	m6502_ICount = cycles;
256 
257 	change_pc(PCD);
258 
259 	do
260 	{
261 		UINT8 op;
262 		PPC = PCD;
263 
264 //		debugger_instruction_hook(Machine, PCD);
265 
266 		/* if an irq is pending, take it now */
267 		if( m6502.pending_irq )
268 			m6502_take_irq();
269 
270 		op = RDOP();
271 
272 		//(*m6502.insn[op])();
273 		(*insnActive[op])();
274 
275 		/* check if the I flag was just reset (interrupts enabled) */
276 		if( m6502.after_cli )
277 		{
278 //			LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
279 			m6502.after_cli = 0;
280 			if (m6502.irq_state != M6502_CLEAR_LINE)
281 			{
282 //				LOG((": irq line is asserted: set pending IRQ\n"));
283 				m6502.pending_irq = 1;
284 			}
285 			else
286 			{
287 //				LOG((": irq line is clear\n"));
288 			}
289 		}
290 		else {
291 			if ( m6502.pending_irq == 2 ) {
292 				if ( m6502_IntOccured - m6502_ICount > 1 ) {
293 					m6502.pending_irq = 1;
294 				}
295 			}
296 			if( m6502.pending_irq == 1 )
297 				m6502_take_irq();
298 			if ( m6502.pending_irq == 2 ) {
299 				m6502.pending_irq = 1;
300 			}
301 		}
302 
303 	} while (m6502_ICount > 0);
304 
305 	cycles = cycles - m6502_ICount;
306 
307 	segmentcycles = m6502_ICount = 0;
308 
309 	return cycles;
310 }
311 
decocpu7_execute(int cycles)312 int decocpu7_execute(int cycles)
313 {
314 	segmentcycles = cycles;
315 	m6502_ICount = cycles;
316 
317 	change_pc(PCD);
318 
319 	do
320 	{
321 		UINT8 op;
322 		PPC = PCD;
323 
324 //		debugger_instruction_hook(Machine, PCD);
325 
326 		/* if an irq is pending, take it now */
327 		if( m6502.pending_irq )
328 			m6502_take_irq();
329 
330 		op = RDOP();
331 
332 		if (m6502.cpu7written) {
333 			if ((PPC & 0x0104) == 0x0104) {
334 				op = Cpu7Write[M6502GetActive()](PPC,op);
335 			}
336 			m6502.cpu7written = 0;
337 		}
338 
339 		//(*m6502.insn[op])();
340 		(*insnActive[op])();
341 
342 		/* check if the I flag was just reset (interrupts enabled) */
343 		if( m6502.after_cli )
344 		{
345 //			LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
346 			m6502.after_cli = 0;
347 			if (m6502.irq_state != M6502_CLEAR_LINE)
348 			{
349 //				LOG((": irq line is asserted: set pending IRQ\n"));
350 				m6502.pending_irq = 1;
351 			}
352 			else
353 			{
354 //				LOG((": irq line is clear\n"));
355 			}
356 		}
357 		else {
358 			if ( m6502.pending_irq == 2 ) {
359 				if ( m6502_IntOccured - m6502_ICount > 1 ) {
360 					m6502.pending_irq = 1;
361 				}
362 			}
363 			if( m6502.pending_irq == 1 )
364 				m6502_take_irq();
365 			if ( m6502.pending_irq == 2 ) {
366 				m6502.pending_irq = 1;
367 			}
368 		}
369 
370 	} while (m6502_ICount > 0);
371 
372 	cycles = cycles - m6502_ICount;
373 
374 	segmentcycles = m6502_ICount = 0;
375 
376 	return cycles;
377 }
378 
m6502_set_irq_line(int irqline,int state)379 void m6502_set_irq_line(int irqline, int state)
380 {
381 	if (irqline == M6502_INPUT_LINE_NMI)
382 	{
383 		if (m6502.nmi_state == state) return;
384 		m6502.nmi_state = state;
385 		if( state != M6502_CLEAR_LINE )
386 		{
387 //			LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
388 			EAD = M6502_NMI_VEC;
389 			m6502_ICount -= 2;
390 			PUSH(PCH);
391 			PUSH(PCL);
392 			PUSH(P & ~F_B);
393 			P |= F_I;		/* set I flag */
394 			PCL = RDMEM(EAD);
395 			PCH = RDMEM(EAD+1);
396 //			LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
397 			change_pc(PCD);
398 		}
399 	}
400 	else
401 	{
402 		if( irqline == M6502_SET_OVERFLOW )
403 		{
404 			if( m6502.so_state && !state )
405 			{
406 //				LOG(( "M6502#%d set overflow\n", cpu_getactivecpu()));
407 				P|=F_V;
408 			}
409 			m6502.so_state=state;
410 			return;
411 		}
412 		m6502.irq_state = state;
413 		if( state != M6502_CLEAR_LINE )
414 		{
415 //			LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
416 			m6502.pending_irq = 1;
417 //          m6502.pending_irq = 2;
418 			m6502_IntOccured = m6502_ICount;
419 		}
420 	}
421 }
422 
m6502_get_pc()423 UINT32 m6502_get_pc()
424 {
425 	return m6502.pc.d;
426 }
427 
m6502_get_prev_pc()428 UINT32 m6502_get_prev_pc()
429 {
430 	return m6502.ppc.d;
431 }
432 
433 /****************************************************************************
434  * 2A03 section
435  ****************************************************************************/
436 #if (HAS_N2A03)
437 
n2a03_init()438 void n2a03_init()
439 {
440 	m6502_common_init(SUBTYPE_2A03, insn2a03);
441 }
442 
443 /* The N2A03 is integrally tied to its PSG (they're on the same die).
444    Bit 7 of address $4011 (the PSG's DPCM control register), when set,
445    causes an IRQ to be generated.  This function allows the IRQ to be called
446    from the PSG core when such an occasion arises. */
n2a03_irq(void)447 void n2a03_irq(void)
448 {
449   m6502_take_irq();
450 }
451 
452 
453 /****************************************************************************
454  * 6510 section
455  ****************************************************************************/
456 #if (HAS_M6510)
457 
m6510_init()458 void m6510_init ()
459 {
460 	m6502_common_init(SUBTYPE_6510, insn6510);
461 }
462 
m6510_reset(void)463 void m6510_reset(void)
464 {
465 	m6502_reset();
466 	m6502.port = 0xff;
467 	m6502.ddr = 0x00;
468 }
469 
470 //static UINT8 m6510_get_port(void)
471 //{
472 //	return (m6502.port & m6502.ddr) | (m6502.ddr ^ 0xff);
473 //}
474 
m6510_read_0000(unsigned short address)475 unsigned char m6510_read_0000(unsigned short address)
476 {
477 	UINT8 result = 0x00;
478 
479 	switch (address)
480 	{
481 		case 0x0000:	/* DDR */
482 			result = m6502.ddr;
483 			break;
484 		case 0x0001:	/* Data Port */
485 			if (m6502.port_read)
486 				result = M6502ReadPort( m6502.ddr );
487 			result = (m6502.ddr & m6502.port) | (~m6502.ddr & result);
488 			break;
489 	}
490 	return result;
491 }
492 
m6510_write_0000(unsigned short address,unsigned char data)493 void m6510_write_0000(unsigned short address, unsigned char data)
494 {
495 	switch (address)
496 	{
497 		case 0x0000:	/* DDR */
498 			m6502.ddr = data;
499 			break;
500 		case 0x0001:	/* Data Port */
501 			m6502.port = data;
502 			break;
503 	}
504 
505 	M6502WritePort( m6502.ddr, m6502.port & m6502.ddr );
506 }
507 
508 //static ADDRESS_MAP_START(m6510_mem, ADDRESS_SPACE_PROGRAM, 8)
509 //	AM_RANGE(0x0000, 0x0001) AM_READWRITE(m6510_read_0000, m6510_write_0000)
510 //ADDRESS_MAP_END
511 
512 #endif
513 
514 #endif
515 
516 /****************************************************************************
517  * 65C02 section
518  ****************************************************************************/
519 #if (HAS_M65C02)
520 
m65c02_init()521 void m65c02_init()
522 {
523 	m6502_common_init(SUBTYPE_65C02, insn65c02);
524 }
525 
m65c02_reset()526 void m65c02_reset()
527 {
528 	m6502_reset();
529 	P &=~F_D;
530 }
531 
m65c02_take_irq(void)532 M6502_INLINE void m65c02_take_irq(void)
533 {
534 	if( !(P & F_I) )
535 	{
536 		EAD = M6502_IRQ_VEC;
537 		m6502_ICount -= 2;
538 		PUSH(PCH);
539 		PUSH(PCL);
540 		PUSH(P & ~F_B);
541 		P = (P & ~F_D) | F_I;		/* knock out D and set I flag */
542 		PCL = RDMEM(EAD);
543 		PCH = RDMEM(EAD+1);
544 		//LOG(("M65c02#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
545 		/* call back the cpuintrf to let it clear the line */
546 		if (m6502.irq_callback) (*m6502.irq_callback)(0);
547 
548 		if (m6502.hold_irq) {
549 			m6502.hold_irq = 0;
550 			m6502.irq_state = M6502_CLEAR_LINE;
551 		}
552 
553 		change_pc(PCD);
554 	}
555 	m6502.pending_irq = 0;
556 }
557 
m65c02_execute(int cycles)558 int m65c02_execute(int cycles)
559 {
560 	segmentcycles = cycles;
561 	m6502_ICount = cycles;
562 
563 	change_pc(PCD);
564 
565 	do
566 	{
567 		UINT8 op;
568 		PPC = PCD;
569 
570 		//debugger_instruction_hook(Machine, PCD);
571 
572 		op = RDOP();
573 
574 		//(*m6502.insn[op])();
575 		(*insnActive[op])();
576 
577 		/* if an irq is pending, take it now */
578 		if( m6502.pending_irq )
579 			m65c02_take_irq();
580 
581 
582 		/* check if the I flag was just reset (interrupts enabled) */
583 		if( m6502.after_cli )
584 		{
585 			//LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
586 			m6502.after_cli = 0;
587 			if (m6502.irq_state != M6502_CLEAR_LINE)
588 			{
589 			//	LOG((": irq line is asserted: set pending IRQ\n"));
590 				m6502.pending_irq = 1;
591 			}
592 			//else
593 			//{
594 			//	LOG((": irq line is clear\n"));
595 			//}
596 		}
597 		else
598 		if( m6502.pending_irq )
599 			m65c02_take_irq();
600 
601 	} while (m6502_ICount > 0);
602 
603 	cycles = cycles - m6502_ICount;
604 
605 	segmentcycles = m6502_ICount = 0;
606 
607 	return cycles;
608 }
609 
m65c02_set_irq_line(int irqline,int state)610 void m65c02_set_irq_line(int irqline, int state)
611 {
612 	if (irqline == M6502_INPUT_LINE_NMI)
613 	{
614 		if (m6502.nmi_state == state) return;
615 		m6502.nmi_state = state;
616 		if( state != M6502_CLEAR_LINE )
617 		{
618 		//	LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
619 			EAD = M6502_NMI_VEC;
620 			m6502_ICount -= 2;
621 			PUSH(PCH);
622 			PUSH(PCL);
623 			PUSH(P & ~F_B);
624 			P = (P & ~F_D) | F_I;		/* knock out D and set I flag */
625 			PCL = RDMEM(EAD);
626 			PCH = RDMEM(EAD+1);
627 		//	LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
628 			change_pc(PCD);
629 		}
630 	}
631 	else
632 		m6502_set_irq_line(irqline,state);
633 }
634 #endif
635 
636 /****************************************************************************
637  * 65SC02 section
638  ****************************************************************************/
639 #if (HAS_M65SC02)
m65sc02_init()640 void m65sc02_init()
641 {
642 	m6502_common_init(SUBTYPE_65SC02, insn65sc02);
643 }
644 #endif
645 
646 /****************************************************************************
647  * DECO16 section
648  ****************************************************************************/
649 #if (HAS_DECO16)
650 
deco16_init()651 void deco16_init()
652 {
653 	m6502_common_init(SUBTYPE_DECO16, insndeco16);
654 }
655 
656 
deco16_reset(void)657 void deco16_reset (void)
658 {
659 	m6502_reset();
660 	m6502.subtype = SUBTYPE_DECO16;
661 	insnActive = insndeco16;
662 
663     PCL = RDMEM(DECO16_RST_VEC+1);
664     PCH = RDMEM(DECO16_RST_VEC);
665 
666 	m6502.sp.d = 0x01ff;	/* stack pointer starts at page 1 offset FF */
667 	m6502.p = F_T|F_I|F_Z|F_B|(P&F_D);	/* set T, I and Z flags */
668 	m6502.pending_irq = 0;	/* nonzero if an IRQ is pending */
669 	m6502.after_cli = 0;	/* pending IRQ and last insn cleared I */
670 
671 	change_pc(PCD);
672 }
673 
deco16_take_irq(void)674 M6502_INLINE void deco16_take_irq(void)
675 {
676 	if( !(P & F_I) )
677 	{
678 		EAD = DECO16_IRQ_VEC;
679 		m6502_ICount -= 2;
680 		PUSH(PCH);
681 		PUSH(PCL);
682 		PUSH(P & ~F_B);
683 		P |= F_I;		/* set I flag */
684 		PCL = RDMEM(EAD+1);
685 		PCH = RDMEM(EAD);
686 		//LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
687 		/* call back the cpuintrf to let it clear the line */
688 		if (m6502.irq_callback) (*m6502.irq_callback)(0);
689 
690 		if (m6502.hold_irq) {
691 			m6502.hold_irq = 0;
692 			m6502.irq_state = M6502_CLEAR_LINE;
693 		}
694 
695 		change_pc(PCD);
696 	}
697 	m6502.pending_irq = 0;
698 }
699 
deco16_set_irq_line(int irqline,int state)700 void deco16_set_irq_line(int irqline, int state)
701 {
702 	if (irqline == M6502_INPUT_LINE_NMI)
703 	{
704 		if (m6502.nmi_state == state) return;
705 		m6502.nmi_state = state;
706 		if( state != M6502_CLEAR_LINE )
707 		{
708 			//LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
709 			EAD = DECO16_NMI_VEC;
710 			m6502_ICount -= 7;
711 			PUSH(PCH);
712 			PUSH(PCL);
713 			PUSH(P & ~F_B);
714 			P |= F_I;		/* set I flag */
715 			PCL = RDMEM(EAD+1);
716 			PCH = RDMEM(EAD);
717 			//LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
718 			change_pc(PCD);
719 		}
720 	}
721 	else
722 	{
723 		if( irqline == M6502_SET_OVERFLOW )
724 		{
725 			if( m6502.so_state && !state )
726 			{
727 			//	LOG(( "M6502#%d set overflow\n", cpu_getactivecpu()));
728 				P|=F_V;
729 			}
730 			m6502.so_state=state;
731 			return;
732 		}
733 		m6502.irq_state = state;
734 		if( state != M6502_CLEAR_LINE )
735 		{
736 			//LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
737 			m6502.pending_irq = 1;
738 		}
739 	}
740 }
741 
deco16_execute(int cycles)742 int deco16_execute(int cycles)
743 {
744 	segmentcycles = cycles;
745 	m6502_ICount = cycles;
746 
747 	change_pc(PCD);
748 
749 	do
750 	{
751 		UINT8 op;
752 		PPC = PCD;
753 
754 		//debugger_instruction_hook(Machine, PCD);
755 
756 		op = RDOP();
757 		//(*m6502.insn[op])();
758 		(*insnActive[op])();
759 
760 		/* if an irq is pending, take it now */
761 		if( m6502.pending_irq )
762 			deco16_take_irq();
763 
764 
765 		/* check if the I flag was just reset (interrupts enabled) */
766 		if( m6502.after_cli )
767 		{
768 			//LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
769 			m6502.after_cli = 0;
770 			if (m6502.irq_state != M6502_CLEAR_LINE)
771 			{
772 			//	LOG((": irq line is asserted: set pending IRQ\n"));
773 				m6502.pending_irq = 1;
774 			}
775 			//else
776 			//{
777 			//	LOG((": irq line is clear\n"));
778 			//}
779 		}
780 		else
781 		if( m6502.pending_irq )
782 			deco16_take_irq();
783 
784 	} while (m6502_ICount > 0);
785 
786 	cycles = cycles - m6502_ICount;
787 
788 	segmentcycles = m6502_ICount = 0;
789 
790 	return cycles;
791 }
792 
793 #endif
794 
795 
796 #if 0
797 
798 /**************************************************************************
799  * Generic set_info
800  **************************************************************************/
801 
802 static void m6502_set_info(UINT32 state, cpuinfo *info)
803 {
804 	switch (state)
805 	{
806 		/* --- the following bits of info are set as 64-bit signed integers --- */
807 		case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE:		m6502_set_irq_line(M6502_IRQ_LINE, info->i); break;
808 		case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW:	m6502_set_irq_line(M6502_SET_OVERFLOW, info->i); break;
809 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:		m6502_set_irq_line(INPUT_LINE_NMI, info->i); break;
810 
811 		case CPUINFO_INT_PC:							PCW = info->i; change_pc(PCD);			break;
812 		case CPUINFO_INT_REGISTER + M6502_PC:			m6502.pc.w.l = info->i;					break;
813 		case CPUINFO_INT_SP:							S = info->i;							break;
814 		case CPUINFO_INT_REGISTER + M6502_S:			m6502.sp.b.l = info->i;					break;
815 		case CPUINFO_INT_REGISTER + M6502_P:			m6502.p = info->i;						break;
816 		case CPUINFO_INT_REGISTER + M6502_A:			m6502.a = info->i;						break;
817 		case CPUINFO_INT_REGISTER + M6502_X:			m6502.x = info->i;						break;
818 		case CPUINFO_INT_REGISTER + M6502_Y:			m6502.y = info->i;						break;
819 		case CPUINFO_INT_REGISTER + M6502_EA:			m6502.ea.w.l = info->i;					break;
820 		case CPUINFO_INT_REGISTER + M6502_ZP:			m6502.zp.w.l = info->i;					break;
821 
822 		/* --- the following bits of info are set as pointers to data or functions --- */
823 		case CPUINFO_PTR_M6502_READINDEXED_CALLBACK:	m6502.rdmem_id = (read8_machine_func) info->f; break;
824 		case CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK:	m6502.wrmem_id = (write8_machine_func) info->f; break;
825 	}
826 }
827 
828 
829 
830 /**************************************************************************
831  * Generic get_info
832  **************************************************************************/
833 
834 void m6502_get_info(UINT32 state, cpuinfo *info)
835 {
836 	switch (state)
837 	{
838 		/* --- the following bits of info are returned as 64-bit signed integers --- */
839 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(m6502);				break;
840 		case CPUINFO_INT_INPUT_LINES:					info->i = 2;							break;
841 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
842 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
843 		case CPUINFO_INT_CLOCK_MULTIPLIER:				info->i = 1;							break;
844 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
845 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
846 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 4;							break;
847 		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
848 		case CPUINFO_INT_MAX_CYCLES:					info->i = 10;							break;
849 
850 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
851 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16;					break;
852 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
853 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
854 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
855 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
856 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 0;					break;
857 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 0;					break;
858 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
859 
860 		case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE:		info->i = m6502.irq_state;			break;
861 		case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW:	info->i = m6502.so_state;			break;
862 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:		info->i = m6502.nmi_state;			break;
863 
864 		case CPUINFO_INT_PREVIOUSPC:					info->i = m6502.ppc.w.l;				break;
865 
866 		case CPUINFO_INT_PC:							info->i = PCD;							break;
867 		case CPUINFO_INT_REGISTER + M6502_PC:			info->i = m6502.pc.w.l;					break;
868 		case CPUINFO_INT_SP:							info->i = S;							break;
869 		case CPUINFO_INT_REGISTER + M6502_S:			info->i = m6502.sp.b.l;					break;
870 		case CPUINFO_INT_REGISTER + M6502_P:			info->i = m6502.p;						break;
871 		case CPUINFO_INT_REGISTER + M6502_A:			info->i = m6502.a;						break;
872 		case CPUINFO_INT_REGISTER + M6502_X:			info->i = m6502.x;						break;
873 		case CPUINFO_INT_REGISTER + M6502_Y:			info->i = m6502.y;						break;
874 		case CPUINFO_INT_REGISTER + M6502_EA:			info->i = m6502.ea.w.l;					break;
875 		case CPUINFO_INT_REGISTER + M6502_ZP:			info->i = m6502.zp.w.l;					break;
876 		case CPUINFO_INT_REGISTER + M6502_SUBTYPE:		info->i = m6502.subtype;				break;
877 
878 		/* --- the following bits of info are returned as pointers to data or functions --- */
879 		case CPUINFO_PTR_SET_INFO:						info->setinfo = m6502_set_info;			break;
880 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = m6502_get_context;	break;
881 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = m6502_set_context;	break;
882 		case CPUINFO_PTR_INIT:							info->init = m6502_init;				break;
883 		case CPUINFO_PTR_RESET:							info->reset = m6502_reset;				break;
884 		case CPUINFO_PTR_EXIT:							info->exit = m6502_exit;				break;
885 		case CPUINFO_PTR_EXECUTE:						info->execute = m6502_execute;			break;
886 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
887 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6502_dasm;			break;
888 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &m6502_ICount;			break;
889 		case CPUINFO_PTR_M6502_READINDEXED_CALLBACK:	info->f = (genf *) m6502.rdmem_id;		break;
890 		case CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK:	info->f = (genf *) m6502.wrmem_id;		break;
891 
892 		/* --- the following bits of info are returned as NULL-terminated strings --- */
893 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6502");				break;
894 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "Mostek 6502");			break;
895 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "1.2");					break;
896 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
897 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break;
898 
899 		case CPUINFO_STR_FLAGS:
900 			sprintf(info->s, "%c%c%c%c%c%c%c%c",
901 				m6502.p & 0x80 ? 'N':'.',
902 				m6502.p & 0x40 ? 'V':'.',
903 				m6502.p & 0x20 ? 'R':'.',
904 				m6502.p & 0x10 ? 'B':'.',
905 				m6502.p & 0x08 ? 'D':'.',
906 				m6502.p & 0x04 ? 'I':'.',
907 				m6502.p & 0x02 ? 'Z':'.',
908 				m6502.p & 0x01 ? 'C':'.');
909 			break;
910 
911 		case CPUINFO_STR_REGISTER + M6502_PC:			sprintf(info->s, "PC:%04X", m6502.pc.w.l); break;
912 		case CPUINFO_STR_REGISTER + M6502_S:			sprintf(info->s, "S:%02X", m6502.sp.b.l); break;
913 		case CPUINFO_STR_REGISTER + M6502_P:			sprintf(info->s, "P:%02X", m6502.p); break;
914 		case CPUINFO_STR_REGISTER + M6502_A:			sprintf(info->s, "A:%02X", m6502.a); break;
915 		case CPUINFO_STR_REGISTER + M6502_X:			sprintf(info->s, "X:%02X", m6502.x); break;
916 		case CPUINFO_STR_REGISTER + M6502_Y:			sprintf(info->s, "Y:%02X", m6502.y); break;
917 		case CPUINFO_STR_REGISTER + M6502_EA:			sprintf(info->s, "EA:%04X", m6502.ea.w.l); break;
918 		case CPUINFO_STR_REGISTER + M6502_ZP:			sprintf(info->s, "ZP:%03X", m6502.zp.w.l); break;
919 	}
920 }
921 
922 
923 #if (HAS_N2A03)
924 /**************************************************************************
925  * CPU-specific set_info
926  **************************************************************************/
927 
928 void n2a03_get_info(UINT32 state, cpuinfo *info)
929 {
930 	switch (state)
931 	{
932 		/* --- the following bits of info are returned as pointers to data or functions --- */
933 		case CPUINFO_PTR_INIT:							info->init = n2a03_init;				break;
934 
935 		/* --- the following bits of info are returned as NULL-terminated strings --- */
936 		case CPUINFO_STR_NAME:							strcpy(info->s, "N2A03");				break;
937 
938 		default:										m6502_get_info(state, info);			break;
939 	}
940 }
941 #endif
942 
943 
944 #if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501)
945 /**************************************************************************
946  * CPU-specific set_info
947  **************************************************************************/
948 
949 static void m6510_set_info(UINT32 state, cpuinfo *info)
950 {
951 	switch (state)
952 	{
953 		/* --- the following bits of info are set as pointers to data or functions --- */
954 		case CPUINFO_PTR_M6510_PORTREAD:	m6502.port_read = (UINT8 (*)(UINT8)) info->f;	break;
955 		case CPUINFO_PTR_M6510_PORTWRITE:	m6502.port_write = (void (*)(UINT8,UINT8)) info->f;	break;
956 
957 		default:							m6502_set_info(state, info);						break;
958 	}
959 }
960 
961 void m6510_get_info(UINT32 state, cpuinfo *info)
962 {
963 	switch (state)
964 	{
965 		/* --- the following bits of info are returned as pointers to data or functions --- */
966 		case CPUINFO_PTR_SET_INFO:						info->setinfo = m6510_set_info;			break;
967 		case CPUINFO_PTR_INIT:							info->init = m6510_init;				break;
968 		case CPUINFO_PTR_RESET:							info->reset = m6510_reset;				break;
969 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m6510_dasm;			break;
970 		case CPUINFO_PTR_INTERNAL_MEMORY_MAP:			info->internal_map8 = address_map_m6510_mem; break;
971 		case CPUINFO_PTR_M6510_PORTREAD:				info->f = (genf *) m6502.port_read;		break;
972 		case CPUINFO_PTR_M6510_PORTWRITE:				info->f = (genf *) m6502.port_write;	break;
973 
974 		/* --- the following bits of info are returned as NULL-terminated strings --- */
975 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6510");				break;
976 
977 		/* --- the following bits of info are set as 64-bit signed integers --- */
978 		case CPUINFO_INT_M6510_PORT:					info->i = m6510_get_port();				break;
979 
980 		default:										m6502_get_info(state, info);			break;
981 	}
982 }
983 #endif
984 
985 
986 #if (HAS_M6510T)
987 /**************************************************************************
988  * CPU-specific set_info
989  **************************************************************************/
990 
991 void m6510t_get_info(UINT32 state, cpuinfo *info)
992 {
993 	switch (state)
994 	{
995 		/* --- the following bits of info are returned as NULL-terminated strings --- */
996 		case CPUINFO_STR_NAME:							strcpy(info->s, "M6510T");				break;
997 
998 		default:										m6510_get_info(state, info);			break;
999 	}
1000 }
1001 #endif
1002 
1003 
1004 #if (HAS_M7501)
1005 /**************************************************************************
1006  * CPU-specific set_info
1007  **************************************************************************/
1008 
1009 void m7501_get_info(UINT32 state, cpuinfo *info)
1010 {
1011 	switch (state)
1012 	{
1013 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1014 		case CPUINFO_STR_NAME:							strcpy(info->s, "M7501");				break;
1015 
1016 		default:										m6510_get_info(state, info);			break;
1017 	}
1018 }
1019 #endif
1020 
1021 
1022 #if (HAS_M8502)
1023 /**************************************************************************
1024  * CPU-specific set_info
1025  **************************************************************************/
1026 
1027 void m8502_get_info(UINT32 state, cpuinfo *info)
1028 {
1029 	switch (state)
1030 	{
1031 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1032 		case CPUINFO_STR_NAME:							strcpy(info->s, "M8502");				break;
1033 
1034 		default:										m6510_get_info(state, info);			break;
1035 	}
1036 }
1037 #endif
1038 
1039 
1040 #if (HAS_M65C02)
1041 /**************************************************************************
1042  * CPU-specific set_info
1043  **************************************************************************/
1044 
1045 static void m65c02_set_info(UINT32 state, cpuinfo *info)
1046 {
1047 	switch (state)
1048 	{
1049 		/* --- the following bits of info are set as 64-bit signed integers --- */
1050 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:	m65c02_set_irq_line(INPUT_LINE_NMI, info->i); break;
1051 
1052 		default:										m6502_set_info(state, info);			break;
1053 	}
1054 }
1055 
1056 void m65c02_get_info(UINT32 state, cpuinfo *info)
1057 {
1058 	switch (state)
1059 	{
1060 		/* --- the following bits of info are returned as pointers to data or functions --- */
1061 		case CPUINFO_PTR_SET_INFO:						info->setinfo = m65c02_set_info;		break;
1062 		case CPUINFO_PTR_INIT:							info->init = m65c02_init;				break;
1063 		case CPUINFO_PTR_RESET:							info->reset = m65c02_reset;				break;
1064 		case CPUINFO_PTR_EXECUTE:						info->execute = m65c02_execute;			break;
1065 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m65c02_dasm;		break;
1066 
1067 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1068 		case CPUINFO_STR_NAME:							strcpy(info->s, "M65C02");				break;
1069 
1070 		default:										m6502_get_info(state, info);			break;
1071 	}
1072 }
1073 #endif
1074 
1075 
1076 #if (HAS_M65SC02)
1077 /**************************************************************************
1078  * CPU-specific set_info
1079  **************************************************************************/
1080 
1081 void m65sc02_get_info(UINT32 state, cpuinfo *info)
1082 {
1083 	switch (state)
1084 	{
1085 		/* --- the following bits of info are returned as pointers to data or functions --- */
1086 		case CPUINFO_PTR_INIT:							info->init = m65sc02_init;				break;
1087 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = m65sc02_dasm;		break;
1088 
1089 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1090 		case CPUINFO_STR_NAME:							strcpy(info->s, "M65SC02");				break;
1091 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "Metal Oxid Semiconductor MOS 6502"); break;
1092 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "1.0beta");				break;
1093 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
1094 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Peter Trauner\nall rights reserved."); break;
1095 
1096 		default:										m65c02_get_info(state, info);			break;
1097 	}
1098 }
1099 #endif
1100 
1101 
1102 #if (HAS_DECO16)
1103 /**************************************************************************
1104  * CPU-specific set_info
1105  **************************************************************************/
1106 
1107 static void deco16_set_info(UINT32 state, cpuinfo *info)
1108 {
1109 	switch (state)
1110 	{
1111 		/* --- the following bits of info are set as 64-bit signed integers --- */
1112 		case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE:		deco16_set_irq_line(M6502_IRQ_LINE, info->i); break;
1113 		case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW:	deco16_set_irq_line(M6502_SET_OVERFLOW, info->i); break;
1114 		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:		deco16_set_irq_line(INPUT_LINE_NMI, info->i); break;
1115 
1116 		default:										m6502_set_info(state, info);			break;
1117 	}
1118 }
1119 
1120 void deco16_get_info(UINT32 state, cpuinfo *info)
1121 {
1122 	switch (state)
1123 	{
1124 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1125 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
1126 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 8;					break;
1127 
1128 		/* --- the following bits of info are returned as pointers to data or functions --- */
1129 		case CPUINFO_PTR_SET_INFO:						info->setinfo = deco16_set_info;		break;
1130 		case CPUINFO_PTR_INIT:							info->init = deco16_init;				break;
1131 		case CPUINFO_PTR_RESET:							info->reset = deco16_reset;				break;
1132 		case CPUINFO_PTR_EXECUTE:						info->execute = deco16_execute;			break;
1133 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = deco16_dasm;		break;
1134 
1135 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1136 		case CPUINFO_STR_NAME:							strcpy(info->s, "DECO CPU16");			break;
1137 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "DECO");				break;
1138 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "0.1");					break;
1139 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
1140 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Bryan McPhail\nall rights reserved."); break;
1141 
1142 		default:										m6502_get_info(state, info);			break;
1143 	}
1144 }
1145 #endif
1146 
1147 #endif
1148