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