OSDN Git Service

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