OSDN Git Service

ppu core temporary commit
[motonesemu/motonesemu.git] / emulator / 6502core.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <libio.h>
4 #include "tools.h"
5
6 struct status_reg {
7     unsigned int negative       :1;
8     unsigned int overflow       :1;
9     unsigned int researved      :1;
10     unsigned int break_mode     :1;
11     unsigned int decimal        :1;
12     unsigned int irq_disable    :1;
13     unsigned int zero           :1;
14     unsigned int carry          :1;
15 } __attribute__ ((packed));
16
17 struct cpu_6502 {
18     unsigned char acc;
19     unsigned char x;
20     unsigned char y;
21     unsigned char sp;
22     struct status_reg status;
23     unsigned short pc;
24 };
25
26
27 typedef int (handler_6502_t) (void);
28
29 /*
30  * 6502 instructions
31  * adressing mode        instruction length
32  * 0:Zero Page           2
33  * 1:Zero Page, X        2
34  * 2:Zero Page, Y        2
35  * 3:Absolute            3
36  * 4:Absolute, X         3
37  * 5:Absolute, Y         3
38  * 6:Indirect            3
39  * 7:Implied             1
40  * 8:Accumulator         1
41  * 9:Immediate           2
42  * 10:Relative           2
43  * 11:(Indirect, X)      2
44  * 12:(Indirect), Y      2
45  * 
46  **/
47
48 #define ADDR_MODE_ZP        0
49 #define ADDR_MODE_ZP_X      1
50 #define ADDR_MODE_ZP_Y      2
51 #define ADDR_MODE_ABS       3
52 #define ADDR_MODE_ABS_X     4
53 #define ADDR_MODE_ABS_Y     5
54 #define ADDR_MODE_IND       6
55 #define ADDR_MODE_IMP       7
56 #define ADDR_MODE_ACC       8
57 #define ADDR_MODE_IMM       9
58 #define ADDR_MODE_REL       10
59 #define ADDR_MODE_INDEX_INDIR       11
60 #define ADDR_MODE_INDIR_INDEX       12
61
62 #define N_BIT      0x80
63
64
65 /* cycle check must be cleared on release  */
66 #define cycle_check
67
68 struct opcode_map {
69     unsigned char   opcode;
70     char            mnemonic[4];
71     handler_6502_t  *func;
72     int             addr_mode;
73     int             cycle;
74     int             cycle_aux;  /*Add one cycle if indexing across page boundary*/
75     int             inst_len;
76 };
77
78 static struct cpu_6502 cpu_reg;
79 static struct opcode_map *current_inst;
80 static int current_exec_index;
81 static int exec_done;
82
83 unsigned char load_memory(unsigned short addr);
84 unsigned short load_addr(unsigned short addr, int cycle);
85 void store_memory(unsigned short addr, unsigned char data);
86
87 unsigned char get_cpu_data_buf(void);
88 void set_cpu_data_buf(unsigned char data);
89 unsigned short get_cpu_addr_buf(void);
90 void set_cpu_addr_buf(unsigned short addr);
91
92 int func_ADC(void);
93 int func_AND(void);
94 int func_ASL(void);
95 int func_BCC(void);
96 int func_BCS(void);
97 int func_BEQ(void);
98 int func_BIT(void);
99 int func_BMI(void);
100 int func_BNE(void);
101 int func_BPL(void);
102 int func_BRK(void);
103 int func_BVC(void);
104 int func_BVS(void);
105 int func_CLC(void);
106 int func_CLD(void);
107 int func_CLI(void);
108 int func_CLV(void);
109 int func_CMP(void);
110 int func_CPX(void);
111 int func_CPY(void);
112 int func_DEC(void);
113 int func_DEX(void);
114 int func_DEY(void);
115 int func_EOR(void);
116 int func_INC(void);
117 int func_INX(void);
118 int func_INY(void);
119 int func_JMP(void);
120 int func_JSR(void);
121 int func_LDA(void);
122 int func_LDX(void);
123 int func_LDY(void);
124 int func_LSR(void);
125 int func_NOP(void);
126 int func_ORA(void);
127 int func_PHA(void);
128 int func_PHP(void);
129 int func_PLA(void);
130 int func_PLP(void);
131 int func_ROL(void);
132 int func_ROR(void);
133 int func_RTI(void);
134 int func_RTS(void);
135 int func_SBC(void);
136 int func_SEC(void);
137 int func_SED(void);
138 int func_SEI(void);
139 int func_STA(void);
140 int func_STX(void);
141 int func_STY(void);
142 int func_TAX(void);
143 int func_TAY(void);
144 int func_TSX(void);
145 int func_TXA(void);
146 int func_TXS(void);
147 int func_TYA(void);
148
149 struct opcode_map opcode_list [255] = {
150 #include "opcode"
151 };
152
153
154 /*
155  * awk '{print "int func_" $2 "(void) {\n\n}"}' < opcode-6502 | sort | uniq
156  *
157  * */
158
159
160
161 /*
162  * load from memory in various addressing mode.
163  * cpu_data_buf has the output value.
164  * */
165 static int load_addr_mode(int *done) {
166     switch (current_inst->addr_mode) {
167         case ADDR_MODE_ACC:
168         case ADDR_MODE_IMP:
169             //not supported.
170             return FALSE;
171
172         case ADDR_MODE_IMM:
173         case ADDR_MODE_REL:
174             //load immediate/relative value takes 1 cycle.
175             if (current_exec_index == 0) {
176                 load_memory(cpu_reg.pc);
177                 cpu_reg.pc++;
178                 goto addr_mode_done;
179             }
180             break;
181
182         case ADDR_MODE_ZP:
183             //zp takes two cycles.
184             if (current_exec_index == 0) {
185                 load_memory(cpu_reg.pc);
186                 cpu_reg.pc++;
187                 return TRUE;
188             }
189             else if (current_exec_index == 1) {
190                 unsigned short zp = get_cpu_data_buf();
191                 load_memory(zp);
192                 goto addr_mode_done;
193             }
194             break;
195
196         case ADDR_MODE_ZP_X:
197             //zp indexed with x takes three cycles.
198             if (current_exec_index == 0) {
199                 load_memory(cpu_reg.pc);
200                 cpu_reg.pc++;
201                 return TRUE;
202             }
203             else if (current_exec_index == 1) {
204                 unsigned char imm = get_cpu_data_buf();
205                 set_cpu_data_buf(imm + cpu_reg.x);
206                 return TRUE;
207             }
208             else if (current_exec_index == 2) {
209                 unsigned short zp = get_cpu_data_buf();
210                 load_memory(zp);
211                 goto addr_mode_done;
212             }
213             break;
214
215         case ADDR_MODE_ZP_Y:
216             //zp indexed with y takes three cycles.
217             if (current_exec_index == 0) {
218                 load_memory(cpu_reg.pc);
219                 cpu_reg.pc++;
220                 return TRUE;
221             }
222             else if (current_exec_index == 1) {
223                 unsigned char imm = get_cpu_data_buf();
224                 set_cpu_data_buf(imm + cpu_reg.y);
225                 return TRUE;
226             }
227             else if (current_exec_index == 2) {
228                 unsigned short zp = get_cpu_data_buf();
229                 load_memory(zp);
230                 goto addr_mode_done;
231             }
232             break;
233
234         case ADDR_MODE_ABS:
235             //takes three cycles.
236             if (current_exec_index == 0) {
237                 load_addr(cpu_reg.pc, 1);
238                 cpu_reg.pc++;
239                 return TRUE;
240             }
241             else if (current_exec_index == 1) {
242                 load_addr(cpu_reg.pc, 2);
243                 cpu_reg.pc++;
244                 return TRUE;
245             }
246             else if (current_exec_index == 2) {
247                 unsigned short addr = get_cpu_addr_buf();
248                 load_memory(addr);
249                 goto addr_mode_done;
250             }
251             break;
252
253         case ADDR_MODE_ABS_X:
254             //abs indexed with x takes three cycles.
255             if (current_exec_index == 0) {
256                 load_addr(cpu_reg.pc, 1);
257                 cpu_reg.pc++;
258                 return TRUE;
259             }
260             else if (current_exec_index == 1) {
261                 load_addr(cpu_reg.pc, 2);
262                 cpu_reg.pc++;
263                 return TRUE;
264             }
265             else if (current_exec_index == 2) {
266                 if (current_inst->cycle_aux) {
267                     //Add one cycle if indexing across page boundary
268                     unsigned short addr = get_cpu_addr_buf();
269                     unsigned short hi_8, added_hi_8;
270
271                     hi_8 = addr >> 8;
272                     addr += cpu_reg.x;
273                     added_hi_8 = addr >> 8;
274
275                     if (hi_8 == added_hi_8) {
276                         load_memory(addr);
277                         goto addr_mode_done;
278                     }
279
280                     //load value in the next cycle.
281                     set_cpu_data_buf(addr);
282                     return TRUE;
283                 }
284                 else {
285                     unsigned short addr = get_cpu_addr_buf();
286                     addr += cpu_reg.x;
287                     load_memory(addr);
288                     goto addr_mode_done;
289                 }
290             }
291             else if (current_exec_index == 3) {
292                 if (current_inst->cycle_aux) {
293                     unsigned short addr = get_cpu_data_buf();
294                     load_memory(addr);
295                     goto addr_mode_done;
296                 }
297             }
298
299             break;
300
301         case ADDR_MODE_ABS_Y:
302             //abs indexed with y takes three cycles.
303             if (current_exec_index == 0) {
304                 load_addr(cpu_reg.pc, 1);
305                 cpu_reg.pc++;
306                 return TRUE;
307             }
308             else if (current_exec_index == 1) {
309                 load_addr(cpu_reg.pc, 2);
310                 cpu_reg.pc++;
311                 return TRUE;
312             }
313             else if (current_exec_index == 2) {
314                 if (current_inst->cycle_aux) {
315                     //Add one cycle if indexing across page boundary
316                     unsigned short addr = get_cpu_addr_buf();
317                     unsigned short hi_8, added_hi_8;
318
319                     hi_8 = addr >> 8;
320                     addr += cpu_reg.y;
321                     added_hi_8 = addr >> 8;
322
323                     if (hi_8 == added_hi_8) {
324                         load_memory(addr);
325                         goto addr_mode_done;
326                     }
327
328                     //load value in the next cycle.
329                     set_cpu_data_buf(addr);
330                     return TRUE;
331                 }
332                 else {
333                     unsigned short addr = get_cpu_addr_buf();
334                     addr += cpu_reg.y;
335                     load_memory(addr);
336                     goto addr_mode_done;
337                 }
338             }
339             else if (current_exec_index == 3) {
340                 if (current_inst->cycle_aux) {
341                     unsigned short addr = get_cpu_data_buf();
342                     load_memory(addr);
343                     goto addr_mode_done;
344                 }
345             }
346             break;
347
348         case ADDR_MODE_INDEX_INDIR:
349             //Zero Page Indexed Indirect: (zp,x) takes 5 cycles
350             if (current_exec_index == 0) {
351                 load_memory(cpu_reg.pc);
352                 cpu_reg.pc++;
353                 return TRUE;
354             }
355             else if (current_exec_index == 1) {
356                 unsigned char zp = get_cpu_data_buf();
357                 zp += cpu_reg.x;
358                 set_cpu_data_buf(zp);
359                 return TRUE;
360             }
361             else if (current_exec_index == 2) {
362                 unsigned short addr = get_cpu_data_buf();
363                 load_addr(addr, 1);
364                 return TRUE;
365             }
366             else if (current_exec_index == 3) {
367                 unsigned short addr = get_cpu_data_buf();
368                 load_addr(addr + 1, 2);
369                 return TRUE;
370             }
371             else if (current_exec_index == 4) {
372                 load_memory(get_cpu_addr_buf());
373                 goto addr_mode_done;
374             }
375             break;
376
377         case ADDR_MODE_INDIR_INDEX:
378             //Zero Page Indirect Indexed with Y: (zp),y takes 4 cycles.
379             if (current_exec_index == 0) {
380                 load_memory(cpu_reg.pc);
381                 cpu_reg.pc++;
382                 return TRUE;
383             }
384             else if (current_exec_index == 1) {
385                 unsigned short addr = get_cpu_data_buf();
386                 load_addr(addr, 1);
387                 return TRUE;
388             }
389             else if (current_exec_index == 2) {
390                 unsigned short addr = get_cpu_data_buf();
391                 load_addr(addr + 1, 2);
392                 return TRUE;
393             }
394             else if (current_exec_index == 3) {
395                 if (current_inst->cycle_aux) {
396                     //Add one cycle if indexing across page boundary
397                     unsigned short addr = get_cpu_data_buf();
398                     unsigned short hi_8, added_hi_8;
399
400                     hi_8 = addr >> 8;
401                     addr += cpu_reg.y;
402                     added_hi_8 = addr >> 8;
403
404                     if (hi_8 == added_hi_8) {
405                         load_memory(addr);
406                         goto addr_mode_done;
407                     }
408
409                     //load value in the next cycle.
410                     set_cpu_data_buf(addr);
411                     return TRUE;
412                 }
413                 else {
414                     unsigned short addr = get_cpu_data_buf();
415                     addr += cpu_reg.y;
416                     load_memory(addr);
417                     goto addr_mode_done;
418                 }
419             }
420             else if (current_exec_index == 4) {
421                 if (current_inst->cycle_aux) {
422                     unsigned short addr = get_cpu_data_buf();
423                     load_memory(addr);
424                     goto addr_mode_done;
425                 }
426             }
427             break;
428
429         default:
430             return FALSE;
431     }
432     return FALSE;
433
434 addr_mode_done:
435     *done = TRUE;
436     return TRUE;
437 }
438
439 /*
440  * store into memory in various addressing mode.
441  * */
442 static int store_addr_mode(unsigned char data, int *done) {
443     switch (current_inst->addr_mode) {
444         case ADDR_MODE_ACC:
445         case ADDR_MODE_IMP:
446         case ADDR_MODE_IMM:
447         case ADDR_MODE_REL:
448             //not supported.
449             return FALSE;
450
451         case ADDR_MODE_ZP:
452             //zp takes two cycles.
453             if (current_exec_index == 0) {
454                 load_memory(cpu_reg.pc);
455                 cpu_reg.pc++;
456                 return TRUE;
457             }
458             else if (current_exec_index == 1) {
459                 unsigned short zp = get_cpu_data_buf();
460                 store_memory(zp, data);
461                 goto addr_mode_done;
462             }
463             break;
464
465         case ADDR_MODE_ZP_X:
466             //zp indexed with x takes three cycles.
467             if (current_exec_index == 0) {
468                 load_memory(cpu_reg.pc);
469                 cpu_reg.pc++;
470                 return TRUE;
471             }
472             else if (current_exec_index == 1) {
473                 unsigned char imm = get_cpu_data_buf();
474                 set_cpu_data_buf(imm + cpu_reg.x);
475                 return TRUE;
476             }
477             else if (current_exec_index == 2) {
478                 unsigned short zp = get_cpu_data_buf();
479                 store_memory(zp, data);
480                 goto addr_mode_done;
481             }
482             break;
483
484         case ADDR_MODE_ZP_Y:
485             //zp indexed with y takes three cycles.
486             if (current_exec_index == 0) {
487                 load_memory(cpu_reg.pc);
488                 cpu_reg.pc++;
489                 return TRUE;
490             }
491             else if (current_exec_index == 1) {
492                 unsigned char imm = get_cpu_data_buf();
493                 set_cpu_data_buf(imm + cpu_reg.y);
494                 return TRUE;
495             }
496             else if (current_exec_index == 2) {
497                 unsigned short zp = get_cpu_data_buf();
498                 store_memory(zp, data);
499                 goto addr_mode_done;
500             }
501             break;
502
503         case ADDR_MODE_ABS:
504             //takes three cycles.
505             if (current_exec_index == 0) {
506                 load_addr(cpu_reg.pc, 1);
507                 cpu_reg.pc++;
508                 return TRUE;
509             }
510             else if (current_exec_index == 1) {
511                 load_addr(cpu_reg.pc, 2);
512                 cpu_reg.pc++;
513                 return TRUE;
514             }
515             else if (current_exec_index == 2) {
516                 unsigned short addr = get_cpu_addr_buf();
517                 store_memory(addr, data);
518                 goto addr_mode_done;
519             }
520             break;
521
522         case ADDR_MODE_ABS_X:
523             //abs indexed with x takes 4 cycles.
524             if (current_exec_index == 0) {
525                 load_addr(cpu_reg.pc, 1);
526                 cpu_reg.pc++;
527                 return TRUE;
528             }
529             else if (current_exec_index == 1) {
530                 load_addr(cpu_reg.pc, 2);
531                 cpu_reg.pc++;
532                 return TRUE;
533             }
534             else if (current_exec_index == 2) {
535                 unsigned short addr = get_cpu_addr_buf();
536                 addr += cpu_reg.x;
537                 set_cpu_data_buf(addr);
538                 return TRUE;
539             }
540             else if (current_exec_index == 3) {
541                 unsigned short addr = get_cpu_data_buf();
542                 store_memory(addr, data);
543                 goto addr_mode_done;
544             }
545             break;
546
547         case ADDR_MODE_ABS_Y:
548             if (current_exec_index == 0) {
549                 load_addr(cpu_reg.pc, 1);
550                 cpu_reg.pc++;
551                 return TRUE;
552             }
553             else if (current_exec_index == 1) {
554                 load_addr(cpu_reg.pc, 2);
555                 cpu_reg.pc++;
556                 return TRUE;
557             }
558             else if (current_exec_index == 2) {
559                 unsigned short addr = get_cpu_addr_buf();
560                 addr += cpu_reg.y;
561                 set_cpu_data_buf(addr);
562                 return TRUE;
563             }
564             else if (current_exec_index == 3) {
565                 unsigned short addr = get_cpu_data_buf();
566                 store_memory(addr, data);
567                 goto addr_mode_done;
568             }
569             break;
570
571         case ADDR_MODE_INDEX_INDIR:
572             //Zero Page Indexed Indirect: (zp,x) takes 5 cycles
573             if (current_exec_index == 0) {
574                 load_memory(cpu_reg.pc);
575                 cpu_reg.pc++;
576                 return TRUE;
577             }
578             else if (current_exec_index == 1) {
579                 unsigned char zp = get_cpu_data_buf();
580                 zp += cpu_reg.x;
581                 set_cpu_data_buf(zp);
582                 return TRUE;
583             }
584             else if (current_exec_index == 2) {
585                 unsigned short addr = get_cpu_data_buf();
586                 load_addr(addr, 1);
587                 return TRUE;
588             }
589             else if (current_exec_index == 3) {
590                 unsigned short addr = get_cpu_data_buf();
591                 load_addr(addr + 1, 2);
592                 return TRUE;
593             }
594             else if (current_exec_index == 4) {
595                 store_memory(get_cpu_addr_buf(), data);
596                 goto addr_mode_done;
597             }
598             break;
599
600         case ADDR_MODE_INDIR_INDEX:
601             //Zero Page Indirect Indexed with Y: (zp),y takes 5 cycles.
602             if (current_exec_index == 0) {
603                 load_memory(cpu_reg.pc);
604                 cpu_reg.pc++;
605                 return TRUE;
606             }
607             else if (current_exec_index == 1) {
608                 unsigned short addr = get_cpu_data_buf();
609                 load_addr(addr, 1);
610                 return TRUE;
611             }
612             else if (current_exec_index == 2) {
613                 unsigned short addr = get_cpu_data_buf();
614                 load_addr(addr + 1, 2);
615                 return TRUE;
616             }
617             else if (current_exec_index == 3) {
618                 unsigned short addr = get_cpu_data_buf();
619                 addr += cpu_reg.y;
620                 set_cpu_data_buf(addr);
621                 return TRUE;
622             }
623             else if (current_exec_index == 4) {
624                 unsigned short addr = get_cpu_data_buf();
625                 store_memory(addr, data);
626                 goto addr_mode_done;
627             }
628             break;
629
630         default:
631             return FALSE;
632     }
633     return FALSE;
634
635 addr_mode_done:
636     *done = TRUE;
637     return TRUE;
638 }
639
640
641 /*-------------   flag operation..  ---------------------*/
642
643 static void set_zero(unsigned char data) {
644     if (data == 0)
645         cpu_reg.status.zero = 1;
646     else
647         cpu_reg.status.zero = 0;
648 }
649
650 static void set_negative(unsigned char data) {
651     if (data & N_BIT)
652         cpu_reg.status.negative = 1;
653     else
654         cpu_reg.status.negative = 0;
655 }
656
657 /*-------------   stack operation..  ---------------------*/
658 //stack operation takes two cycles.
659 static void push(unsigned char data) {
660     store_memory(cpu_reg.sp--, data);
661 }
662
663 static unsigned char pop(void) {
664     return load_memory(--cpu_reg.sp);
665 }
666
667 /*---------- instruction implementations.   -----------------*/
668
669 int func_ADC(void) {
670     return FALSE;
671 }
672
673 int func_AND(void) {
674     return FALSE;
675 }
676
677 int func_ASL(void) {
678     return FALSE;
679 }
680
681 static int branch(unsigned char condition) {
682
683     if (current_exec_index == 0) {
684         int done = FALSE;
685         int ret;
686         ret = load_addr_mode(&done);
687         if (!ret)
688             return FALSE;
689
690         if (!condition) {
691             exec_done = TRUE;
692         }
693         return TRUE;
694     }
695     else if (current_exec_index == 1) {
696         //case branch
697         char rel = get_cpu_data_buf();
698         unsigned short addr = cpu_reg.pc;
699         unsigned short br_addr = cpu_reg.pc + rel;
700
701         if (addr >> 8 == br_addr >> 8) {
702             //in page branch.
703             cpu_reg.pc = br_addr;
704             exec_done = TRUE;
705         }
706         else {
707             set_cpu_addr_buf(br_addr);
708         }
709         return TRUE;
710     }
711     else if (current_exec_index == 2) {
712         //cross page branch.
713         unsigned short br_addr = get_cpu_addr_buf();
714         cpu_reg.pc = br_addr;
715         exec_done = TRUE;
716         return TRUE;
717     }
718
719     return FALSE;
720 }
721
722 /*
723  * Branch on Carry Clear: BCC
724  * Branch if C = 0
725  * Flags: none
726  * */
727 int func_BCC(void) {
728     return branch(cpu_reg.status.carry == 0);
729 }
730
731 /*
732  *  Branch on Carry Set: BCS
733  *  Branch if C = 1
734  *  Flags: none
735  * */
736 int func_BCS(void) {
737     return branch(cpu_reg.status.carry == 1);
738 }
739
740 /*
741  *  Branch on Result Zero: BEQ
742  *  Branch if Z = 1
743  *  Flags: none
744  * */
745 int func_BEQ(void) {
746     return branch(cpu_reg.status.zero == 1);
747 }
748
749 int func_BIT(void) {
750     return FALSE;
751 }
752
753 /*
754  *  Branch on Result Minus: BMI
755  *  Branch if N = 1
756  *  Flags: none
757  * */
758 int func_BMI(void) {
759     return branch(cpu_reg.status.negative == 1);
760 }
761
762 /*
763  * Branch on Result not Zero: BNE
764  * Branch if Z = 0
765  * Flags: none
766  * */
767 int func_BNE(void) {
768     return branch(cpu_reg.status.zero == 0);
769 }
770
771 /*
772  * Branch on Result Plus: BPL
773  * Branch if N = 0
774  * Flags: none
775  * */
776 int func_BPL(void) {
777     return branch(cpu_reg.status.negative == 0);
778 }
779
780 int func_BRK(void) {
781     return FALSE;
782 }
783
784 /*
785  * Branch on Overflow Clear: BVC
786  * Branch if V = 0
787  * Flags: none
788  * */
789 int func_BVC(void) {
790     return branch(cpu_reg.status.overflow == 0);
791 }
792
793 /*
794  * Branch on Overflow Set: BVS
795  * Branch if V = 1
796  * Flags: none
797  * */
798 int func_BVS(void) {
799     return branch(cpu_reg.status.overflow == 1);
800 }
801
802 int func_CLC(void) {
803     return FALSE;
804 }
805
806 int func_CLD(void) {
807     return FALSE;
808 }
809
810 int func_CLI(void) {
811     return FALSE;
812 }
813
814 int func_CLV(void) {
815     return FALSE;
816 }
817
818 int func_CMP(void) {
819     return FALSE;
820 }
821
822 int func_CPX(void) {
823     return FALSE;
824 }
825
826 int func_CPY(void) {
827     return FALSE;
828 }
829
830 int func_DEC(void) {
831     return FALSE;
832 }
833
834 /*
835  * Decrement Index X by One: DEX
836  * X - 1 -> X
837  * Flags: N, Z
838  * */
839 int func_DEX(void) {
840     cpu_reg.x--;
841
842     //ldx N/Z flags set.
843     set_negative(cpu_reg.x);
844     set_zero(cpu_reg.x);
845
846     exec_done = TRUE;
847     return TRUE;
848 }
849
850 /*
851  * Decrement Index Y by One: DEY
852  * Y - 1 -> Y
853  * Flags: N, Z
854  * */
855 int func_DEY(void) {
856     cpu_reg.y--;
857
858     //ldx N/Z flags set.
859     set_negative(cpu_reg.y);
860     set_zero(cpu_reg.y);
861
862     exec_done = TRUE;
863     return TRUE;
864 }
865
866 int func_EOR(void) {
867     return FALSE;
868 }
869
870 int func_INC(void) {
871     return FALSE;
872 }
873
874 /*
875  * Increment Index X by One: INX
876  * X + 1 -> X
877  * Flags: N, Z
878  * */
879 int func_INX(void) {
880     cpu_reg.x++;
881
882     //ldx N/Z flags set.
883     set_negative(cpu_reg.x);
884     set_zero(cpu_reg.x);
885
886     exec_done = TRUE;
887     return TRUE;
888 }
889
890 int func_INY(void) {
891     cpu_reg.y++;
892
893     //ldx N/Z flags set.
894     set_negative(cpu_reg.y);
895     set_zero(cpu_reg.y);
896
897     exec_done = TRUE;
898     return TRUE;
899 }
900
901 static int jmp(int cycle, int *done) {
902     switch (current_inst->addr_mode) {
903         case ADDR_MODE_ABS:
904             //takes 2 cycles.
905             if (cycle == 0) {
906                 load_addr(cpu_reg.pc, 1);
907                 cpu_reg.pc++;
908                 return TRUE;
909             }
910             else if (cycle == 1) {
911                 load_addr(cpu_reg.pc, 2);
912                 cpu_reg.pc++;
913                 *done = TRUE;
914                 return TRUE;
915             }
916             break;
917
918         case ADDR_MODE_IND:
919             //takes 4 cycles.
920             if (cycle == 0) {
921                 load_addr(cpu_reg.pc, 1);
922                 cpu_reg.pc++;
923                 return TRUE;
924             }
925             else if (cycle == 1) {
926                 load_addr(cpu_reg.pc, 2);
927                 cpu_reg.pc++;
928                 return TRUE;
929             }
930             else if (cycle == 2) {
931                 load_memory(get_cpu_addr_buf());
932                 return TRUE;
933             }
934             else if (cycle == 3) {
935                 unsigned char low, hi;
936                 unsigned short addr;
937                 low = get_cpu_data_buf();
938                 hi = load_memory(get_cpu_addr_buf() + 1);
939                 addr = (hi << 8) | low;
940                 set_cpu_addr_buf(addr);
941                 *done = TRUE;
942                 return TRUE;
943             }
944             break;
945
946         default:
947             return FALSE;
948     }
949     return FALSE;
950 }
951
952 /*
953  * Jump to New Location: JMP
954  * Jump to new location
955  * Flags: none
956  * */
957 int func_JMP(void) {
958     int done = FALSE;
959     int ret;
960
961     ret = jmp(current_exec_index, &done);
962     if (!ret)
963         return FALSE;
964
965     if (!done) 
966         return TRUE;
967
968     cpu_reg.pc = get_cpu_addr_buf();
969
970     exec_done = TRUE;
971     return TRUE;
972 }
973
974 /*
975  * Jump to New Location Saving Return Address: JSR
976  * Jump to Subroutine
977  * Flags: none
978  * */
979 int func_JSR(void) {
980     int done = FALSE;
981
982     //cycle 1,2
983     if (current_exec_index < 2) {
984         return jmp(current_exec_index, &done);
985     }
986     //cycle 3
987     else if (current_exec_index == 3) {
988         //save return addr(-1) hi.
989         push((cpu_reg.pc - 1) >> 8);
990         return TRUE;
991     }
992     //cycle 4
993     else if (current_exec_index == 4) {
994         //save return addr(-1) low.
995         push(cpu_reg.pc - 1);
996         return TRUE;
997     }
998     //cycle 5
999     else if (current_exec_index == 5) {
1000         cpu_reg.pc = get_cpu_addr_buf();
1001         exec_done = TRUE;
1002         return TRUE;
1003     }
1004     return FALSE;
1005 }
1006
1007 /*
1008  * Load Accumulator with Memory: LDA
1009  * M -> A
1010  * Flags: N, Z
1011  * */
1012 int func_LDA(void) {
1013     int done = FALSE;
1014     int ret;
1015
1016     ret = load_addr_mode(&done);
1017     if (!ret)
1018         return FALSE;
1019
1020     if (!done) 
1021         return TRUE;
1022
1023     cpu_reg.acc = get_cpu_data_buf();
1024     //ldx N/Z flags set.
1025     set_negative(cpu_reg.acc);
1026     set_zero(cpu_reg.acc);
1027
1028     exec_done = TRUE;
1029     return TRUE;
1030 }
1031
1032 /*
1033  * Load Index X with Memory: LDX
1034  * M -> X
1035  * Flags: N, Z
1036  * */
1037 int func_LDX(void) {
1038     int done = FALSE;
1039     int ret;
1040
1041     ret = load_addr_mode(&done);
1042     if (!ret)
1043         return FALSE;
1044
1045     if (!done) 
1046         return TRUE;
1047
1048     cpu_reg.x = get_cpu_data_buf();
1049     //ldx N/Z flags set.
1050     set_negative(cpu_reg.x);
1051     set_zero(cpu_reg.x);
1052
1053     exec_done = TRUE;
1054     return TRUE;
1055 }
1056
1057 /*
1058  * Load Index Y with Memory: LDY
1059  * M -> Y
1060  * Flags: N, Z
1061  * */
1062 int func_LDY(void) {
1063     int done = FALSE;
1064     int ret;
1065
1066     ret = load_addr_mode(&done);
1067     if (!ret)
1068         return FALSE;
1069
1070     if (!done) 
1071         return TRUE;
1072
1073     cpu_reg.y = get_cpu_data_buf();
1074     //ldx N/Z flags set.
1075     set_negative(cpu_reg.y);
1076     set_zero(cpu_reg.y);
1077
1078     exec_done = TRUE;
1079     return TRUE;
1080 }
1081
1082 int func_LSR(void) {
1083     return FALSE;
1084 }
1085
1086 int func_NOP(void) {
1087     return FALSE;
1088 }
1089
1090 int func_ORA(void) {
1091     return FALSE;
1092 }
1093
1094 int func_PHA(void) {
1095     return FALSE;
1096 }
1097
1098 int func_PHP(void) {
1099     return FALSE;
1100 }
1101
1102 int func_PLA(void) {
1103     return FALSE;
1104 }
1105
1106 int func_PLP(void) {
1107     return FALSE;
1108 }
1109
1110 int func_ROL(void) {
1111     return FALSE;
1112 }
1113
1114 int func_ROR(void) {
1115     return FALSE;
1116 }
1117
1118 int func_RTI(void) {
1119     return FALSE;
1120 }
1121
1122 /*
1123  * Return from Subroutine: RTS
1124  * Return from Subroutine
1125  * Flags: none
1126  * */
1127 int func_RTS(void) {
1128
1129     //cycle 1
1130     if (current_exec_index == 0) {
1131         //pop return addr low.
1132         pop();
1133         return TRUE;
1134     }
1135     //cycle 2 
1136     if (current_exec_index == 0) {
1137         //set return addr low.
1138         set_cpu_addr_buf(get_cpu_data_buf());
1139         return TRUE;
1140     }
1141     //cycle 3
1142     else if (current_exec_index == 1) {
1143         //pop return addr hi.
1144         pop();
1145         return TRUE;
1146     }
1147     //cycle 4
1148     else if (current_exec_index == 1) {
1149         unsigned char hi, lo;
1150         unsigned short addr;
1151
1152         //set return addr hi
1153         lo = get_cpu_addr_buf();
1154         hi = get_cpu_data_buf();
1155         addr = (hi << 8) | lo;
1156         set_cpu_addr_buf(addr);
1157         return TRUE;
1158     }
1159     //cycle 5
1160     else if (current_exec_index == 2) {
1161         //set pc = addr + 1
1162         cpu_reg.pc = get_cpu_addr_buf() + 1;
1163         exec_done = TRUE;
1164         return TRUE;
1165     }
1166     return FALSE;
1167 }
1168
1169 int func_SBC(void) {
1170     return FALSE;
1171 }
1172
1173 int func_SEC(void) {
1174     return FALSE;
1175 }
1176
1177 int func_SED(void) {
1178     return FALSE;
1179 }
1180
1181 /*
1182  * set interrupt disable.
1183  * */
1184 int func_SEI(void) {
1185     cpu_reg.status.irq_disable = 1;
1186     exec_done = TRUE;
1187     return TRUE;
1188 }
1189
1190 /*
1191  * Store Accumulator in Memory: STA
1192  * A -> M
1193  * Flags: none
1194  * */
1195 int func_STA(void) {
1196     int done = FALSE;
1197     int ret;
1198
1199     ret = store_addr_mode(cpu_reg.acc, &done);
1200     if (!ret)
1201         return FALSE;
1202
1203     if (!done) 
1204         return TRUE;
1205
1206     exec_done = TRUE;
1207     return TRUE;
1208 }
1209
1210 /*
1211  * Store Index X in Memory: STX
1212  * X -> M
1213  * Flags: none
1214  * */
1215 int func_STX(void) {
1216     int done = FALSE;
1217     int ret;
1218
1219     ret = store_addr_mode(cpu_reg.x, &done);
1220     if (!ret)
1221         return FALSE;
1222
1223     if (!done) 
1224         return TRUE;
1225
1226     exec_done = TRUE;
1227     return TRUE;
1228 }
1229
1230 /*
1231  * Store Index Y in Memory: STY
1232  * Y -> M
1233  * Flags: none
1234  * */
1235 int func_STY(void) {
1236     int done = FALSE;
1237     int ret;
1238
1239     ret = store_addr_mode(cpu_reg.y, &done);
1240     if (!ret)
1241         return FALSE;
1242
1243     if (!done) 
1244         return TRUE;
1245
1246     exec_done = TRUE;
1247     return TRUE;
1248 }
1249
1250 /*
1251  * Transfer Accumulator to Index X: TAX
1252  * A -> X
1253  * Flags: N, Z
1254  * */
1255 int func_TAX(void) {
1256     cpu_reg.x = cpu_reg.acc;
1257
1258     set_negative(cpu_reg.x);
1259     set_zero(cpu_reg.x);
1260
1261     exec_done = TRUE;
1262     return TRUE;
1263 }
1264
1265 /*
1266  * Transfer Accumulator to Index Y: TAY
1267  * A -> Y
1268  * Flags: N, Z
1269  * */
1270 int func_TAY(void) {
1271     cpu_reg.y = cpu_reg.acc;
1272
1273     set_negative(cpu_reg.y);
1274     set_zero(cpu_reg.y);
1275
1276     exec_done = TRUE;
1277     return TRUE;
1278 }
1279
1280 /*
1281  * Transfer Stack Pointer to Index X: TSX
1282  * S -> X
1283  * Flags: N, Z
1284  * */
1285 int func_TSX(void) {
1286     cpu_reg.x = cpu_reg.sp;
1287
1288     set_negative(cpu_reg.x);
1289     set_zero(cpu_reg.x);
1290
1291     exec_done = TRUE;
1292     return TRUE;
1293 }
1294
1295 /*
1296  * Transfer Index X to Accumulator: TXA
1297  * X -> A
1298  * Flags: N, Z
1299  * */
1300 int func_TXA(void) {
1301     cpu_reg.acc = cpu_reg.x;
1302
1303     set_negative(cpu_reg.acc);
1304     set_zero(cpu_reg.acc);
1305
1306     exec_done = TRUE;
1307     return TRUE;
1308 }
1309
1310 /*
1311  * Transfer Index X to Stack Pointer: TXS
1312  * X -> S
1313  * Flags: N, Z
1314  * */
1315 int func_TXS(void) {
1316     cpu_reg.sp = cpu_reg.x;
1317
1318     set_negative(cpu_reg.sp);
1319     set_zero(cpu_reg.sp);
1320
1321     exec_done = TRUE;
1322     return TRUE;
1323 }
1324
1325 /*
1326  * Transfer Index Y to Accumulator: TYA
1327  * Y -> A
1328  * Flags: N, Z
1329  * */
1330 int func_TYA(void) {
1331     cpu_reg.acc = cpu_reg.y;
1332
1333     set_negative(cpu_reg.y);
1334     set_zero(cpu_reg.y);
1335
1336     exec_done = TRUE;
1337     return TRUE;
1338 }
1339
1340 /*
1341  * decode6502:
1342  * return execution cycle count
1343  * */
1344 int decode6502(unsigned char inst) {
1345
1346     struct opcode_map * omap = &opcode_list[inst];
1347     if (omap->func == NULL) {
1348         return FALSE;
1349     }
1350
1351     dprint("decode inst: %02x > %s, %d cycle, %d len\n", 
1352             inst, omap->mnemonic, omap->cycle, omap->inst_len);
1353
1354     current_inst = omap;
1355     current_exec_index = 0;
1356
1357     return TRUE;
1358 }
1359
1360 int test_and_set_exec(void) {
1361     int ret;
1362     ret = exec_done;
1363     if (exec_done)
1364         exec_done = FALSE;
1365     return ret;
1366 }
1367
1368 int execute6502(void) {
1369     int ret;
1370     ret = current_inst->func();
1371     current_exec_index++;
1372
1373 #ifdef cycle_check
1374     if (exec_done && (current_inst->cycle - 1 != current_exec_index)) {
1375         if (current_inst->cycle_aux && (
1376                     current_inst->addr_mode == ADDR_MODE_ABS_X ||
1377                     current_inst->addr_mode == ADDR_MODE_ABS_Y ||
1378                     current_inst->addr_mode == ADDR_MODE_INDIR_INDEX ) && 
1379                 (current_inst->cycle == current_exec_index)) {
1380             ;
1381         }
1382         else if ((current_inst->addr_mode == ADDR_MODE_REL) && 
1383                 ((current_inst->cycle == current_exec_index) ||
1384                 (current_inst->cycle + 1 == current_exec_index ))) {
1385             ;
1386         }
1387         else {
1388             fprintf(stderr, "instruction cycle check error!!\n");
1389             return FALSE;
1390         }
1391     }
1392
1393 #endif
1394
1395     return ret;
1396 }
1397
1398 void pc_set(unsigned short addr) {
1399     cpu_reg.pc = addr;
1400 }
1401
1402 unsigned short pc_get(void) {
1403     return cpu_reg.pc;
1404 }
1405
1406 void pc_move(int offset) {
1407     cpu_reg.pc += offset;
1408 }
1409
1410 void dump_6502(int full) {
1411     if (full) 
1412         printf("6502 CPU registers:\n");
1413
1414     printf("pc:     %04x\n", cpu_reg.pc);
1415     if (full) {
1416         printf("acc:    %02x\n", cpu_reg.acc);
1417         printf("x:      %02x\n", cpu_reg.x);
1418         printf("y:      %02x\n", cpu_reg.y);
1419         printf("sp:     %02x\n", cpu_reg.sp);
1420         printf("status:\n");
1421         printf(" negative:   %d\n", cpu_reg.status.negative);
1422         printf(" overflow:   %d\n", cpu_reg.status.overflow);
1423         printf(" break:      %d\n", cpu_reg.status.break_mode);
1424         printf(" decimal:    %d\n", cpu_reg.status.decimal);
1425         printf(" irq:        %d\n", cpu_reg.status.irq_disable);
1426         printf(" zero:       %d\n", cpu_reg.status.zero);
1427         printf(" carry:      %d\n", cpu_reg.status.carry);
1428         printf("-------------------\n");
1429     }
1430     //printf("data:     %02x\n", cpu_data_buffer);
1431 }
1432
1433
1434 int init_6502core(void) {
1435     memset(&cpu_reg, 0, sizeof(struct cpu_6502));
1436     current_inst = NULL;
1437     current_exec_index = 0;
1438     exec_done = FALSE;
1439     return TRUE;
1440 }
1441