OSDN Git Service

f146251b466944733a1dedece0a4ccba4c2f7c43
[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
14 int reset6502(void);
15 int reset_exec6502(void);
16 int decode6502(unsigned char inst);
17 int execute6502(void);
18 int test_and_set_exec(void);
19 int test_and_set_intr(void);
20 int emu_debug(void);
21 int init_6502core(void);
22 int nmi6502(void);
23 int bus_ready(void);
24
25 void pc_set(unsigned short addr);
26 unsigned short pc_get(void);
27 void pc_move(int offset);
28 void report_exec_err(void);
29 void d1_set(int on_off);
30 void d2_set(int on_off);
31 void d3_set(int on_off);
32
33 //for debug.c
34 void break_hit(void);
35 int disas_inst(unsigned short addr);
36 void dump_6502(int full);
37 extern int debug_mode;
38 extern unsigned short break_point;
39 extern int critical_error;
40
41
42 static unsigned char cpu_data_buffer;
43 static unsigned short cpu_addr_buffer;
44
45 static void (*dump_6502_level2)(int);
46 static void (*dump_6502_level3_load)(unsigned short, unsigned char);
47 static void (*dump_6502_level3_store)(unsigned short, unsigned char);
48 static int (*d1_disas)(unsigned short);
49
50 /*
51  * clock execution function array.
52  * max execution cycle is 7.
53  * the last element must be NULL.
54  * */
55 clock_func_t *execute_func;
56
57 static unsigned long clock_cnt;
58
59 /*for debug purpos*/
60 int get_clock_cnt(void) {
61     return clock_cnt;
62 }
63
64
65 /*
66  * clock handler.
67  * */
68 int clock_cpu(void) {
69     int ret;
70
71     //dprint("%d\n", clock_cnt);
72     clock_cnt++;
73
74     ret = execute_func();
75
76     return ret;
77 }
78
79 unsigned char load_memory(unsigned short addr) {
80
81     set_rw_pin(0);
82     set_bus_addr(addr);
83     start_bus();
84     cpu_data_buffer = get_bus_data();
85     end_bus();
86
87     dump_6502_level3_load (addr, cpu_data_buffer);
88     /*
89     */
90     return cpu_data_buffer;
91 }
92
93 void store_memory(unsigned short addr, unsigned char data) {
94     dump_6502_level3_store (addr, data);
95
96     set_rw_pin(1);
97     set_bus_addr(addr);
98     set_bus_data(data);
99     start_bus();
100     end_bus();
101
102     cpu_data_buffer = data;
103 }
104
105 /*
106  * load address in the memory.
107  * loading 2 bytes takes 2 cycles.
108  * the parameter "cycle" means first or second read.
109  * */
110 unsigned short load_addr(unsigned short addr, int cycle) {
111     unsigned short byte = load_memory(addr);
112
113     ///NES=little endian. lower byte first, higher byte second.
114     if (cycle == 1)
115         cpu_addr_buffer = ((cpu_addr_buffer & 0xff00) | byte);
116     else
117         cpu_addr_buffer = ((cpu_addr_buffer & 0x00ff) | (byte << 8));
118     return cpu_addr_buffer;
119 }
120
121 static int reset_handler2(void) {
122     int ret;
123     ret = reset_exec6502();
124     if (!ret) {
125         fprintf(stderr, "cpu reset failure.\n");
126         critical_error = TRUE;
127         return FALSE;
128     }
129
130     if (test_and_set_intr()) {
131         execute_func = fetch_and_decode_inst;
132     }
133     return ret;
134 }
135
136 static int reset_handler1(void) {
137     int ret;
138     ret = reset6502();
139     if (!ret) {
140         fprintf(stderr, "cpu reset failure.\n");
141         critical_error = TRUE;
142         return FALSE;
143     }
144     execute_func = reset_handler2;
145     return TRUE;
146 }
147
148 void reset_cpu(void) {
149     execute_func = reset_handler1;
150 }
151
152 static int nmi_handler(void) {
153     int ret;
154
155     ret = nmi6502();
156     if (!ret) {
157         dump_6502(TRUE);
158         fprintf(stderr, "cpu nmi handling failure.\n");
159         while (emu_debug());
160
161         critical_error = TRUE;
162         return FALSE;
163     }
164
165     //last cycle goes to next execute cycle
166     if (test_and_set_intr()) {
167         //deassert nmi pin.
168         set_nmi_pin(FALSE);
169         execute_func = fetch_and_decode_inst;
170     }
171     return ret;
172 }
173
174 static int decode_inst(void) {
175     int ret;
176
177     ret = decode6502(cpu_data_buffer);
178
179     return ret;
180 }
181
182 static int fetch_and_decode_inst(void) {
183     int ret;
184     unsigned short pc;
185
186     //if nmi occurred, no further execution on the current instruction.
187     if (get_nmi_pin()) {
188         execute_func = nmi_handler;
189         return execute_func();
190     }
191
192
193     dump_6502_level2(TRUE);
194     pc = pc_get();
195
196     if (break_point == pc) {
197         break_hit();
198     }
199
200     d1_disas(pc);
201     if (debug_mode) {
202         ret = emu_debug();
203         if (!ret)
204             return FALSE;
205     }
206     //dprint("fetch\n");
207
208     //if bus not ready, do nothing.
209     if (!bus_ready())
210         return TRUE;
211
212     load_memory(pc);
213
214     ret = decode_inst();
215     if (!ret) {
216         disas_inst(pc);
217         dump_6502(TRUE);
218         fprintf(stderr, "cpu decode instruction failure.\n");
219         while (emu_debug());
220
221         critical_error = TRUE;
222         //raise(SIGINT);
223         //abort();
224         return FALSE;
225     }
226
227     execute_func = execute_inst;
228     pc_move(1);
229
230     return TRUE;
231 }
232
233 static int execute_inst(void) {
234     int ret;
235
236     //dprint("execute\n");
237
238     //execute the instruction
239     ret = execute6502();
240     /*
241     */
242     if (!ret) {
243         report_exec_err();
244         dump_6502(TRUE);
245         while (emu_debug());
246
247         critical_error = TRUE;
248         //raise(SIGINT);
249         return ret;
250     }
251
252     //last cycle goes to next execute cycle
253     if (test_and_set_exec()) {
254         execute_func = fetch_and_decode_inst;
255     }
256     return TRUE;
257 }
258
259 void set_cpu_addr_buf(unsigned short addr) {
260     cpu_addr_buffer = addr;
261 }
262
263 unsigned short get_cpu_addr_buf(void) {
264     return cpu_addr_buffer;
265 }
266
267 void set_cpu_data_buf(unsigned char data) {
268     cpu_data_buffer = data;
269 }
270
271 unsigned char get_cpu_data_buf(void) {
272     return cpu_data_buffer;
273 }
274
275 /*null func*/
276 static void null_dump_6502 (int param) {}
277 static void null_load_store (unsigned short addr, unsigned char data) {}
278 static int null_disas(unsigned short addr) {return 0;}
279
280 static void dump_load (unsigned short addr, unsigned char data) {
281     dprint("                                  ");
282     dprint("                                  ");
283     dprint("load: @%04x = %02x\n", addr, data);
284 }
285 static void dump_store (unsigned short addr, unsigned char data) {
286     dprint("                                  ");
287     dprint("store: @%04x = %02x\n", addr, data);
288 }
289
290 int init_cpu(void) {
291     int ret;
292
293     ret = init_6502core();
294     if (!ret) {
295         return FALSE;
296     }
297
298     ret = register_clock_hander(clock_cpu);
299     if (!ret) {
300         return FALSE;
301     }
302     execute_func = NULL;
303     clock_cnt = 0;
304     cpu_data_buffer = 0;
305     cpu_addr_buffer = 0;
306
307     d1_set(debug_mode);
308     d2_set(debug_mode);
309     d3_set(debug_mode);
310
311     return TRUE;
312 }
313
314 /*------for debug.c-----*/
315 void d1_set(int on_off) {
316     if (on_off) {
317         d1_disas = disas_inst;
318     }
319     else {
320         d1_disas = null_disas;
321     }
322 }
323
324 void d2_set(int on_off) {
325     if (on_off) {
326         dump_6502_level2 = dump_6502;
327     }
328     else {
329         dump_6502_level2 = null_dump_6502;
330     }
331 }
332
333 void d3_set(int on_off) {
334     if (on_off) {
335         dump_6502_level3_load = dump_load;
336         dump_6502_level3_store = dump_store;
337     }
338     else {
339         dump_6502_level3_load = null_load_store;
340         dump_6502_level3_store = null_load_store;
341     }
342 }
343