OSDN Git Service

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