OSDN Git Service

debug tool update. jsr bug fix.
[motonesemu/motonesemu.git] / emulator / cpu.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <time.h>
4 #include <stdlib.h>
5 #include "tools.h"
6 #include "clock.h"
7 #include "bus.h"
8
9 //typedef int (clock_func_t) (void);
10 static int fetch_and_decode_inst(void);
11 static int decode_inst(void);
12 static int execute_inst(void);
13 static int reset_handler1(void);
14 static int reset_handler2(void);
15
16 #define NMI_ADDR        0xFFFA
17 #define RESET_ADDR      0xFFFC
18 #define IRQ_BRK_ADDR    0xFFFE
19
20 int decode6502(unsigned char inst);
21 int execute6502(void);
22 int test_and_set_exec(void);
23 int emu_debug(void);
24 int init_6502core(void);
25
26 void pc_set(unsigned short addr);
27 unsigned short pc_get(void);
28 void pc_move(int offset);
29 void start_bus(void);
30 void end_bus(void);
31 void set_rw_pin(int rw);
32
33 static unsigned char cpu_data_buffer;
34 static unsigned short cpu_addr_buffer;
35
36 /*
37  * clock execution function array.
38  * max execution cycle is 7.
39  * the last element must be NULL.
40  * */
41 clock_func_t *execute_func;
42
43 static unsigned long clock_cnt;
44
45 /*for debug purpos*/
46 int get_clock_cnt(void) {
47     return clock_cnt;
48 }
49
50
51 /*
52  * clock handler.
53  * */
54 int clock_cpu(void) {
55     int ret;
56
57     //dprint("%d\n", clock_cnt);
58     clock_cnt++;
59
60     ret = execute_func();
61
62     return ret;
63 }
64
65 unsigned char load_memory(unsigned short addr) {
66
67     set_rw_pin(0);
68     set_bus_addr(addr);
69     start_bus();
70     cpu_data_buffer = get_bus_data();
71     end_bus();
72
73     return cpu_data_buffer;
74 }
75
76 void store_memory(unsigned short addr, unsigned char data) {
77
78     set_rw_pin(1);
79     set_bus_addr(addr);
80     set_bus_data(data);
81     start_bus();
82     end_bus();
83
84     cpu_addr_buffer = addr;
85     cpu_data_buffer = data;
86 }
87
88 /*
89  * load address in the memory.
90  * loading 2 bytes takes 2 cycles.
91  * the parameter "cycle" means first or second read.
92  * */
93 unsigned short load_addr(unsigned short addr, int cycle) {
94     unsigned char byte = load_memory(addr);
95
96     ///NES=little endian. lower byte first, higher byte second.
97     if (cycle == 1)
98         cpu_addr_buffer = byte;
99     else
100         cpu_addr_buffer |= byte << 8;
101     return cpu_addr_buffer;
102 }
103
104 void reset_cpu(void) {
105     init_6502core();
106     execute_func = reset_handler1;
107 }
108
109 static int reset_handler1(void) {
110     load_addr(RESET_ADDR, 1);
111     execute_func = reset_handler2;
112     return TRUE;
113 }
114
115 static int reset_handler2(void) {
116     load_addr(RESET_ADDR + 1, 2);
117     pc_set(cpu_addr_buffer);
118
119     execute_func = fetch_and_decode_inst;
120     return TRUE;
121 }
122
123 static int decode_inst(void) {
124     int ret;
125
126     ret = decode6502(cpu_data_buffer);
127
128     return ret;
129 }
130
131 static int fetch_and_decode_inst(void) {
132     int ret;
133     unsigned short pc;
134
135     //for debug.c
136     void break_hit(void);
137     void disas_pc(void);
138     void dump_6502(int full);
139     extern int debug_mode;
140     extern unsigned short break_point;
141     extern int dbg_log_msg;
142     extern int critical_error;
143
144
145     pc = pc_get();
146
147     if (break_point == pc) {
148         break_hit();
149     }
150
151     if (dbg_log_msg) {
152         disas_pc();
153     }
154     if (debug_mode) {
155         if (!dbg_log_msg)
156             disas_pc();
157         ret = emu_debug();
158         if (!ret)
159             return FALSE;
160     }
161     //dprint("fetch\n");
162     load_memory(pc);
163
164     ret = decode_inst();
165     if (!ret) {
166         disas_pc();
167         dump_6502(TRUE);
168         fprintf(stderr, "cpu decode instruction failure.\n");
169         while (emu_debug());
170
171         critical_error = TRUE;
172         //raise(SIGINT);
173         //abort();
174         return FALSE;
175     }
176
177     execute_func = execute_inst;
178     pc_move(1);
179
180     return TRUE;
181 }
182
183 static int execute_inst(void) {
184     int ret;
185
186     void disas_pc(void);
187     void dump_6502(int full);
188     extern int critical_error;
189
190     //dprint("execute\n");
191
192     //execute the instruction
193     ret = execute6502();
194     /*
195     */
196     if (!ret) {
197         fprintf(stderr, "cpu execute instruction failure.\n");
198         disas_pc();
199         dump_6502(TRUE);
200         while (emu_debug());
201
202         critical_error = TRUE;
203         //raise(SIGINT);
204         return ret;
205     }
206
207     //last cycle goes to next execute cycle
208     if (test_and_set_exec()) {
209         execute_func = fetch_and_decode_inst;
210     }
211     return TRUE;
212 }
213
214 void set_cpu_addr_buf(unsigned short addr) {
215     cpu_addr_buffer = addr;
216 }
217
218 unsigned short get_cpu_addr_buf(void) {
219     return cpu_addr_buffer;
220 }
221
222 void set_cpu_data_buf(unsigned char data) {
223     cpu_data_buffer = data;
224 }
225
226 unsigned char get_cpu_data_buf(void) {
227     return cpu_data_buffer;
228 }
229
230 int init_cpu(void) {
231     int ret;
232
233     ret = init_6502core();
234     if (!ret) {
235         return FALSE;
236     }
237
238     ret = register_clock_hander(clock_cpu);
239     if (!ret) {
240         return FALSE;
241     }
242     execute_func = NULL;
243     clock_cnt = 0;
244     cpu_data_buffer = 0;
245     cpu_addr_buffer = 0;
246
247     return TRUE;
248 }
249