OSDN Git Service

added ram
[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 };
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_BIT8      0x80
63 #define N_BIT16     0x8000
64
65 struct opcode_map {
66     unsigned char   opcode;
67     char            mnemonic[4];
68     handler_6502_t  *func;
69     int             addr_mode;
70     int             cycle;
71     int             cycle_aux;  /*Add one cycle if indexing across page boundary*/
72     int             inst_len;
73 };
74
75 static struct cpu_6502 cpu_reg;
76 static struct opcode_map *current_inst;
77 static int current_exec_index;
78 static int exec_done;
79
80 unsigned char load_memory(unsigned short addr);
81 unsigned short load_addr(unsigned short addr, int cycle);
82
83 unsigned char get_cpu_data_buf(void);
84 void set_cpu_data_buf(unsigned char data);
85 unsigned short get_cpu_addr_buf(void);
86 void set_cpu_addr_buf(unsigned short addr);
87
88 int func_ADC(void);
89 int func_AND(void);
90 int func_ASL(void);
91 int func_BCC(void);
92 int func_BCS(void);
93 int func_BEQ(void);
94 int func_BIT(void);
95 int func_BMI(void);
96 int func_BNE(void);
97 int func_BPL(void);
98 int func_BRK(void);
99 int func_BVC(void);
100 int func_BVS(void);
101 int func_CLC(void);
102 int func_CLD(void);
103 int func_CLI(void);
104 int func_CLV(void);
105 int func_CMP(void);
106 int func_CPX(void);
107 int func_CPY(void);
108 int func_DEC(void);
109 int func_DEX(void);
110 int func_DEY(void);
111 int func_EOR(void);
112 int func_INC(void);
113 int func_INX(void);
114 int func_INY(void);
115 int func_JMP(void);
116 int func_JSR(void);
117 int func_LDA(void);
118 int func_LDX(void);
119 int func_LDY(void);
120 int func_LSR(void);
121 int func_NOP(void);
122 int func_ORA(void);
123 int func_PHA(void);
124 int func_PHP(void);
125 int func_PLA(void);
126 int func_PLP(void);
127 int func_ROL(void);
128 int func_ROR(void);
129 int func_RTI(void);
130 int func_RTS(void);
131 int func_SBC(void);
132 int func_SEC(void);
133 int func_SED(void);
134 int func_SEI(void);
135 int func_STA(void);
136 int func_STX(void);
137 int func_STY(void);
138 int func_TAX(void);
139 int func_TAY(void);
140 int func_TSX(void);
141 int func_TXA(void);
142 int func_TXS(void);
143 int func_TYA(void);
144
145 struct opcode_map opcode_list [255] = {
146 #include "opcode"
147 };
148
149
150 /*
151  * awk '{print "int func_" $2 "(void) {\n\n}"}' < opcode-6502 | sort | uniq
152  *
153  * */
154
155
156
157 static int addr_mode_exec(int *done) {
158     switch (current_inst->addr_mode) {
159         case ADDR_MODE_ACC:
160         case ADDR_MODE_IMP:
161             //accumulator/implied doesn't need memory operation.
162             return FALSE;
163
164         case ADDR_MODE_IMM:
165         case ADDR_MODE_REL:
166             //load immediate/relative value takes 1 cycle.
167             if (current_exec_index == 0) {
168                 load_memory(cpu_reg.pc);
169                 cpu_reg.pc++;
170                 goto addr_mode_done;
171             }
172             break;
173
174         case ADDR_MODE_ZP:
175             //zp takes two cycles.
176             if (current_exec_index == 0) {
177                 load_memory(cpu_reg.pc);
178                 cpu_reg.pc++;
179                 return TRUE;
180             }
181             else if (current_exec_index == 1) {
182                 unsigned short zp = get_cpu_data_buf();
183                 load_memory(zp);
184                 goto addr_mode_done;
185             }
186             break;
187
188         case ADDR_MODE_ZP_X:
189             //zp indexed with x takes three cycles.
190             if (current_exec_index == 0) {
191                 load_memory(cpu_reg.pc);
192                 cpu_reg.pc++;
193                 return TRUE;
194             }
195             else if (current_exec_index == 1) {
196                 unsigned char imm = get_cpu_data_buf();
197                 set_cpu_data_buf(imm + cpu_reg.x);
198                 return TRUE;
199             }
200             else if (current_exec_index == 2) {
201                 unsigned short zp = get_cpu_data_buf();
202                 load_memory(zp);
203                 goto addr_mode_done;
204             }
205             break;
206
207         case ADDR_MODE_ZP_Y:
208             //zp indexed with y takes three cycles.
209             if (current_exec_index == 0) {
210                 load_memory(cpu_reg.pc);
211                 cpu_reg.pc++;
212                 return TRUE;
213             }
214             else if (current_exec_index == 1) {
215                 unsigned char imm = get_cpu_data_buf();
216                 set_cpu_data_buf(imm + cpu_reg.y);
217                 return TRUE;
218             }
219             else if (current_exec_index == 2) {
220                 unsigned short zp = get_cpu_data_buf();
221                 load_memory(zp);
222                 goto addr_mode_done;
223             }
224             break;
225
226         case ADDR_MODE_ABS:
227             //takes three cycles.
228             if (current_exec_index == 0) {
229                 load_addr(cpu_reg.pc, 1);
230                 cpu_reg.pc++;
231                 return TRUE;
232             }
233             else if (current_exec_index == 1) {
234                 load_addr(cpu_reg.pc, 2);
235                 cpu_reg.pc++;
236                 return TRUE;
237             }
238             else if (current_exec_index == 2) {
239                 unsigned short addr = get_cpu_addr_buf();
240                 load_memory(addr);
241                 goto addr_mode_done;
242             }
243             break;
244
245         case ADDR_MODE_ABS_X:
246             //abs indexed with x takes three cycles.
247             if (current_exec_index == 0) {
248                 load_addr(cpu_reg.pc, 1);
249                 cpu_reg.pc++;
250                 return TRUE;
251             }
252             else if (current_exec_index == 1) {
253                 load_addr(cpu_reg.pc, 2);
254                 cpu_reg.pc++;
255                 return TRUE;
256             }
257             else if (current_exec_index == 2) {
258                 if (current_inst->cycle_aux) {
259                     //Add one cycle if indexing across page boundary
260                     unsigned short addr = get_cpu_addr_buf();
261                     unsigned short hi_8, added_hi_8;
262
263                     hi_8 = addr >> 8;
264                     addr += cpu_reg.x;
265                     added_hi_8 = addr >> 8;
266
267                     if (hi_8 == added_hi_8) {
268                         load_memory(addr);
269                         goto addr_mode_done;
270                     }
271
272                     //load value in the next cycle.
273                     set_cpu_data_buf(addr);
274                     return TRUE;
275                 }
276                 else {
277                     unsigned short addr = get_cpu_addr_buf();
278                     addr += cpu_reg.x;
279                     load_memory(addr);
280                     goto addr_mode_done;
281                 }
282             }
283             else if (current_exec_index == 3) {
284                 if (current_inst->cycle_aux) {
285                     unsigned short addr = get_cpu_data_buf();
286                     load_memory(addr);
287                     goto addr_mode_done;
288                 }
289             }
290
291             break;
292
293         case ADDR_MODE_ABS_Y:
294             //abs indexed with y takes three cycles.
295             if (current_exec_index == 0) {
296                 load_addr(cpu_reg.pc, 1);
297                 cpu_reg.pc++;
298                 return TRUE;
299             }
300             else if (current_exec_index == 1) {
301                 load_addr(cpu_reg.pc, 2);
302                 cpu_reg.pc++;
303                 return TRUE;
304             }
305             else if (current_exec_index == 2) {
306                 if (current_inst->cycle_aux) {
307                     //Add one cycle if indexing across page boundary
308                     unsigned short addr = get_cpu_addr_buf();
309                     unsigned short hi_8, added_hi_8;
310
311                     hi_8 = addr >> 8;
312                     addr += cpu_reg.y;
313                     added_hi_8 = addr >> 8;
314
315                     if (hi_8 == added_hi_8) {
316                         load_memory(addr);
317                         goto addr_mode_done;
318                     }
319
320                     //load value in the next cycle.
321                     set_cpu_data_buf(addr);
322                     return TRUE;
323                 }
324                 else {
325                     unsigned short addr = get_cpu_addr_buf();
326                     addr += cpu_reg.y;
327                     load_memory(addr);
328                     goto addr_mode_done;
329                 }
330             }
331             else if (current_exec_index == 3) {
332                 if (current_inst->cycle_aux) {
333                     unsigned short addr = get_cpu_data_buf();
334                     load_memory(addr);
335                     goto addr_mode_done;
336                 }
337             }
338             break;
339
340         case ADDR_MODE_INDEX_INDIR:
341         case ADDR_MODE_INDIR_INDEX:
342 #warning zp indexed indirect, zp indirect indexed must be reworked!!
343
344         default:
345             return FALSE;
346     }
347     return FALSE;
348
349 addr_mode_done:
350     *done = TRUE;
351     return TRUE;
352 }
353
354 int func_ADC(void) {
355     return FALSE;
356 }
357
358 int func_AND(void) {
359     return FALSE;
360 }
361
362 int func_ASL(void) {
363     return FALSE;
364 }
365
366 int func_BCC(void) {
367     return FALSE;
368 }
369
370 int func_BCS(void) {
371     return FALSE;
372 }
373
374 int func_BEQ(void) {
375     return FALSE;
376 }
377
378 int func_BIT(void) {
379     return FALSE;
380 }
381
382 int func_BMI(void) {
383     return FALSE;
384 }
385
386 int func_BNE(void) {
387     return FALSE;
388 }
389
390 int func_BPL(void) {
391     return FALSE;
392 }
393
394 int func_BRK(void) {
395     return FALSE;
396 }
397
398 int func_BVC(void) {
399     return FALSE;
400 }
401
402 int func_BVS(void) {
403     return FALSE;
404 }
405
406 int func_CLC(void) {
407     return FALSE;
408 }
409
410 int func_CLD(void) {
411     return FALSE;
412 }
413
414 int func_CLI(void) {
415     return FALSE;
416 }
417
418 int func_CLV(void) {
419     return FALSE;
420 }
421
422 int func_CMP(void) {
423     return FALSE;
424 }
425
426 int func_CPX(void) {
427     return FALSE;
428 }
429
430 int func_CPY(void) {
431     return FALSE;
432 }
433
434 int func_DEC(void) {
435     return FALSE;
436 }
437
438 int func_DEX(void) {
439     return FALSE;
440 }
441
442 int func_DEY(void) {
443     return FALSE;
444 }
445
446 int func_EOR(void) {
447     return FALSE;
448 }
449
450 int func_INC(void) {
451     return FALSE;
452 }
453
454 int func_INX(void) {
455     return FALSE;
456 }
457
458 int func_INY(void) {
459     return FALSE;
460 }
461
462 int func_JMP(void) {
463     return FALSE;
464 }
465
466 int func_JSR(void) {
467     return FALSE;
468 }
469
470 /*
471  * Load Accumulator with Memory: LDA
472  * M -> A
473  * Flags: N, Z
474  * */
475 int func_LDA(void) {
476     return FALSE;
477 }
478
479 /*
480  * Load Index X with Memory: LDX
481  * M -> X
482  * Flags: N, Z
483  * */
484 int func_LDX(void) {
485     int done = FALSE;
486     int ret;
487
488     ret = addr_mode_exec(&done);
489     if (!ret)
490         return FALSE;
491
492     if (!done) 
493         return TRUE;
494
495     cpu_reg.x = get_cpu_data_buf();
496     //ldx N/Z flags set.
497     if (cpu_reg.x == 0)
498         cpu_reg.status.zero = 1;
499     if (cpu_reg.x & N_BIT8)
500         cpu_reg.status.negative = 1;
501     exec_done = TRUE;
502     return TRUE;
503 }
504
505 /*
506  * Load Index Y with Memory: LDY
507  * M -> Y
508  * Flags: N, Z
509  * */
510 int func_LDY(void) {
511     int done = FALSE;
512     int ret;
513
514     ret = addr_mode_exec(&done);
515     if (!ret)
516         return FALSE;
517
518     if (!done) 
519         return TRUE;
520
521     cpu_reg.y = get_cpu_data_buf();
522     //ldx N/Z flags set.
523     if (cpu_reg.y == 0)
524         cpu_reg.status.zero = 1;
525     if (cpu_reg.y & N_BIT8)
526         cpu_reg.status.negative = 1;
527     exec_done = TRUE;
528     return TRUE;
529 }
530
531 int func_LSR(void) {
532     return FALSE;
533 }
534
535 int func_NOP(void) {
536     return FALSE;
537 }
538
539 int func_ORA(void) {
540     return FALSE;
541 }
542
543 int func_PHA(void) {
544     return FALSE;
545 }
546
547 int func_PHP(void) {
548     return FALSE;
549 }
550
551 int func_PLA(void) {
552     return FALSE;
553 }
554
555 int func_PLP(void) {
556     return FALSE;
557 }
558
559 int func_ROL(void) {
560     return FALSE;
561 }
562
563 int func_ROR(void) {
564     return FALSE;
565 }
566
567 int func_RTI(void) {
568     return FALSE;
569 }
570
571 int func_RTS(void) {
572     return FALSE;
573 }
574
575 int func_SBC(void) {
576     return FALSE;
577 }
578
579 int func_SEC(void) {
580     return FALSE;
581 }
582
583 int func_SED(void) {
584     return FALSE;
585 }
586
587 /*
588  * set interrupt disable.
589  * */
590 int func_SEI(void) {
591     cpu_reg.status.irq_disable = 1;
592     exec_done = TRUE;
593     return TRUE;
594 }
595
596 int func_STA(void) {
597     return FALSE;
598 }
599
600 int func_STX(void) {
601     return FALSE;
602 }
603
604 int func_STY(void) {
605     return FALSE;
606 }
607
608 int func_TAX(void) {
609     return FALSE;
610 }
611
612 int func_TAY(void) {
613     return FALSE;
614 }
615
616 /*
617  * Transfer Stack Pointer to Index X: TSX
618  * S -> X
619  * Flags: N, Z
620  * */
621 int func_TSX(void) {
622     cpu_reg.x = cpu_reg.sp;
623
624     if (cpu_reg.x & N_BIT8)
625         cpu_reg.status.negative = 1;
626     if (cpu_reg.x == 0)
627         cpu_reg.status.zero = 1;
628
629     exec_done = TRUE;
630     return TRUE;
631 }
632
633 int func_TXA(void) {
634     return FALSE;
635 }
636
637 /*
638  * Transfer Index X to Stack Pointer: TXS
639  * X -> S
640  * Flags: N, Z
641  * */
642 int func_TXS(void) {
643     cpu_reg.sp = cpu_reg.x;
644
645     if (cpu_reg.sp & N_BIT8)
646         cpu_reg.status.negative = 1;
647     if (cpu_reg.sp == 0)
648         cpu_reg.status.zero = 1;
649
650     exec_done = TRUE;
651     return TRUE;
652 }
653
654 int func_TYA(void) {
655     return FALSE;
656 }
657
658 /*
659  * decode6502:
660  * return execution cycle count
661  * */
662 int decode6502(unsigned char inst) {
663
664     struct opcode_map * omap = &opcode_list[inst];
665     if (omap->func == NULL) {
666         return FALSE;
667     }
668
669     dprint("decode inst: %02x > %s, %d cycle, %d len\n", 
670             inst, omap->mnemonic, omap->cycle, omap->inst_len);
671
672     current_inst = omap;
673     current_exec_index = 0;
674
675     return TRUE;
676 }
677 int test_and_set_exec(void) {
678     int ret;
679     ret = exec_done;
680     if (exec_done)
681         exec_done = FALSE;
682     return ret;
683 }
684
685 int execute6502(void) {
686     int ret;
687     ret = current_inst->func();
688     current_exec_index++;
689     return ret;
690 }
691
692 void pc_set(unsigned short addr) {
693     cpu_reg.pc = addr;
694 }
695
696 unsigned short pc_get(void) {
697     return cpu_reg.pc;
698 }
699
700 void pc_move(int offset) {
701     cpu_reg.pc += offset;
702 }
703
704 void dump_6502(int full) {
705     if (full) 
706         printf("6502 CPU registers:\n");
707
708     printf("pc:     %04x\n", cpu_reg.pc);
709     if (full) {
710         printf("acc:    %02x\n", cpu_reg.acc);
711         printf("x:      %02x\n", cpu_reg.x);
712         printf("y:      %02x\n", cpu_reg.y);
713         printf("sp:     %02x\n", cpu_reg.sp);
714         printf("status:\n");
715         printf(" negative:   %d\n", cpu_reg.status.negative);
716         printf(" overflow:   %d\n", cpu_reg.status.overflow);
717         printf(" break:      %d\n", cpu_reg.status.break_mode);
718         printf(" decimal:    %d\n", cpu_reg.status.decimal);
719         printf(" irq:        %d\n", cpu_reg.status.irq_disable);
720         printf(" zero:       %d\n", cpu_reg.status.zero);
721         printf(" carry:      %d\n", cpu_reg.status.carry);
722         printf("-------------------\n");
723     }
724     //printf("data:     %02x\n", cpu_data_buffer);
725 }
726
727
728 int init_6502core(void) {
729     memset(&cpu_reg, 0, sizeof(struct cpu_6502));
730     current_inst = NULL;
731     current_exec_index = 0;
732     exec_done = FALSE;
733     return TRUE;
734 }
735