]>
Commit | Line | Data |
---|---|---|
321a78a5 SC |
1 | /* Simulator for the WDC 65816 architecture. |
2 | ||
3 | Written by Steve Chamberlain of Cygnus Support. | |
4 | [email protected] | |
5 | ||
6 | This file is part of W65 sim | |
7 | ||
8 | ||
9 | THIS SOFTWARE IS NOT COPYRIGHTED | |
10 | ||
11 | Cygnus offers the following for use in the public domain. Cygnus | |
12 | makes no warranty with regard to the software or it's performance | |
13 | and the user accepts the software "AS IS" with all faults. | |
14 | ||
15 | CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO | |
16 | THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
18 | ||
19 | */ | |
20 | ||
b6de8f6a ILT |
21 | #include "config.h" |
22 | ||
23 | #include <stdio.h> | |
321a78a5 | 24 | #include <signal.h> |
b6de8f6a ILT |
25 | #ifdef HAVE_STDLIB_H |
26 | #include <stdlib.h> | |
27 | #endif | |
28 | #ifdef HAVE_TIME_H | |
29 | #include <time.h> | |
30 | #endif | |
31 | #ifdef HAVE_UNISTD_H | |
32 | #include <unistd.h> | |
33 | #endif | |
321a78a5 SC |
34 | #include <sys/param.h> |
35 | #include "bfd.h" | |
a325a02e | 36 | #include "callback.h" |
321a78a5 SC |
37 | #include "remote-sim.h" |
38 | #include "../../newlib/libc/sys/w65/sys/syscall.h" | |
39 | ||
40 | #include "interp.h" | |
41 | ||
42 | saved_state_type saved_state; | |
43 | ||
44 | int | |
45 | get_now () | |
46 | { | |
47 | return time ((long *) 0); | |
48 | } | |
49 | void | |
50 | control_c (sig, code, scp, addr) | |
51 | int sig; | |
52 | int code; | |
53 | char *scp; | |
54 | char *addr; | |
55 | { | |
56 | saved_state.exception = SIGINT; | |
57 | } | |
58 | ||
59 | wai () | |
60 | { | |
61 | saved_state.exception = SIGTRAP; | |
62 | } | |
63 | ||
64 | ||
65 | ||
66 | wdm (acc, x) | |
67 | int acc; | |
68 | int x; | |
69 | ||
70 | { | |
71 | int cycles; | |
72 | /* The x points to where the registers live, acc has code */ | |
73 | ||
74 | #define R(arg) (x + arg * 2) | |
75 | unsigned R0 = R(0); | |
76 | unsigned R4 = R(4); | |
77 | unsigned R5 = R(5); | |
78 | unsigned R6 = R(6); | |
79 | unsigned R7 = R(7); | |
80 | unsigned R8 = R(8); | |
81 | unsigned char *memory = saved_state.memory; | |
82 | int a1 = fetch16 (R (4)); | |
83 | switch (a1) | |
84 | { | |
85 | case SYS_write: | |
86 | { | |
87 | int file = fetch16 (R5); | |
88 | unsigned char *buf = fetch24 (R6) + memory; | |
89 | int len = fetch16 (R8); | |
90 | int res = write (file, buf, len); | |
91 | store16 (R0, res); | |
92 | break; | |
93 | } | |
94 | case 0: | |
95 | printf ("%c", acc); | |
96 | fflush (stdout); | |
97 | break; | |
98 | case 1: | |
99 | saved_state.exception = SIGTRAP; | |
100 | break; | |
101 | default: | |
102 | saved_state.exception = SIGILL; | |
103 | break; | |
104 | } | |
105 | } | |
106 | ||
107 | ||
108 | void | |
109 | sim_resume (step, insignal) | |
110 | int step; | |
111 | int insignal; | |
112 | { | |
113 | void (*prev) (); | |
114 | register unsigned char *memory; | |
115 | if (step) | |
116 | { | |
117 | saved_state.exception = SIGTRAP; | |
118 | } | |
119 | else | |
120 | { | |
121 | saved_state.exception = 0; | |
122 | } | |
123 | ||
124 | ||
125 | prev = signal (SIGINT, control_c); | |
126 | do | |
127 | { | |
128 | int x = (saved_state.p >> 4) & 1; | |
129 | int m = (saved_state.p >> 5) & 1; | |
130 | if (x == 0 && m == 0) | |
131 | { | |
132 | ifunc_X0_M0 (); | |
133 | } | |
134 | else if (x == 0 && m == 1) | |
135 | { | |
136 | ifunc_X0_M1 (); | |
137 | } | |
138 | else if (x == 1 && m == 0) | |
139 | { | |
140 | ifunc_X1_M0 (); | |
141 | } | |
142 | else if (x == 1 && m == 1) | |
143 | { | |
144 | ifunc_X1_M1 (); | |
145 | } | |
146 | } | |
147 | while (saved_state.exception == 0); | |
148 | ||
149 | signal (SIGINT, prev); | |
150 | } | |
151 | ||
152 | ||
153 | ||
154 | ||
155 | init_pointers () | |
156 | { | |
157 | if (!saved_state.memory) | |
158 | { | |
159 | saved_state.memory = calloc (64 * 1024, NUMSEGS); | |
160 | } | |
161 | } | |
162 | ||
163 | int | |
164 | sim_write (addr, buffer, size) | |
165 | SIM_ADDR addr; | |
166 | unsigned char *buffer; | |
167 | int size; | |
168 | { | |
169 | int i; | |
170 | init_pointers (); | |
171 | ||
172 | for (i = 0; i < size; i++) | |
173 | { | |
174 | saved_state.memory[(addr + i) & MMASK] = buffer[i]; | |
175 | } | |
176 | return size; | |
177 | } | |
178 | ||
179 | int | |
180 | sim_read (addr, buffer, size) | |
181 | SIM_ADDR addr; | |
182 | unsigned char *buffer; | |
183 | int size; | |
184 | { | |
185 | int i; | |
186 | ||
187 | init_pointers (); | |
188 | ||
189 | for (i = 0; i < size; i++) | |
190 | { | |
191 | buffer[i] = saved_state.memory[(addr + i) & MMASK]; | |
192 | } | |
193 | return size; | |
194 | } | |
195 | ||
196 | ||
197 | ||
198 | struct | |
199 | { | |
200 | unsigned int *ptr; | |
201 | int size; | |
202 | } | |
203 | rinfo[] = | |
204 | ||
205 | { | |
206 | &saved_state.r[0], 2, | |
207 | &saved_state.r[1], 2, | |
208 | &saved_state.r[2], 2, | |
209 | &saved_state.r[3], 2, | |
210 | &saved_state.r[4], 2, | |
211 | &saved_state.r[5], 2, | |
212 | &saved_state.r[6], 2, | |
213 | &saved_state.r[7], 2, | |
214 | &saved_state.r[8], 2, | |
215 | &saved_state.r[9], 2, | |
216 | &saved_state.r[10], 2, | |
217 | &saved_state.r[11], 2, | |
218 | &saved_state.r[12], 2, | |
219 | &saved_state.r[13], 2, | |
220 | &saved_state.r[14], 2, | |
221 | &saved_state.r[15], 4, | |
222 | &saved_state.pc, 4, | |
223 | &saved_state.a, 4, | |
224 | &saved_state.x, 4, | |
225 | &saved_state.y, 4, | |
226 | &saved_state.dbr, 4, | |
227 | &saved_state.d, 4, | |
228 | &saved_state.s, 4, | |
229 | &saved_state.p, 4, | |
230 | &saved_state.ticks, 4, | |
231 | &saved_state.cycles, 4, | |
232 | &saved_state.insts, 4, | |
233 | 0 | |
234 | }; | |
235 | ||
236 | void | |
237 | sim_store_register (rn, value) | |
238 | int rn; | |
239 | unsigned char *value; | |
240 | { | |
241 | unsigned int val; | |
242 | int i; | |
243 | val = 0; | |
244 | for (i = 0; i < rinfo[rn].size; i++) | |
245 | { | |
246 | val |= (*value++) << (i * 8); | |
247 | } | |
248 | ||
249 | *(rinfo[rn].ptr) = val; | |
250 | } | |
251 | ||
252 | void | |
253 | sim_fetch_register (rn, buf) | |
254 | int rn; | |
255 | unsigned char *buf; | |
256 | { | |
257 | unsigned int val = *(rinfo[rn].ptr); | |
258 | int i; | |
259 | ||
260 | for (i = 0; i < rinfo[rn].size; i++) | |
261 | { | |
262 | *buf++ = val; | |
263 | val = val >> 8; | |
264 | } | |
265 | } | |
266 | ||
267 | ||
268 | sim_reg_size (n) | |
269 | { | |
270 | return rinfo[n].size; | |
271 | } | |
272 | int | |
273 | sim_trace () | |
274 | { | |
275 | return 0; | |
276 | } | |
277 | ||
278 | void | |
279 | sim_stop_reason (reason, sigrc) | |
280 | enum sim_stop *reason; | |
281 | int *sigrc; | |
282 | { | |
283 | *reason = sim_stopped; | |
284 | *sigrc = saved_state.exception; | |
285 | } | |
286 | ||
287 | int | |
288 | sim_set_pc (x) | |
289 | SIM_ADDR x; | |
290 | { | |
291 | saved_state.pc = x; | |
292 | return 0; | |
293 | } | |
294 | ||
295 | ||
296 | void | |
297 | sim_info (verbose) | |
298 | int verbose; | |
299 | { | |
300 | double timetaken = (double) saved_state.ticks; | |
301 | double virttime = saved_state.cycles / 2.0e6; | |
302 | ||
303 | printf ("\n\n# instructions executed %10d\n", saved_state.insts); | |
304 | printf ("# cycles %10d\n", saved_state.cycles); | |
305 | printf ("# real time taken %10.4f\n", timetaken); | |
306 | printf ("# virtual time taken %10.4f\n", virttime); | |
307 | ||
308 | if (timetaken != 0) | |
309 | { | |
310 | printf ("# cycles/second %10d\n", (int) (saved_state.cycles / timetaken)); | |
311 | printf ("# simulation ratio %10.4f\n", virttime / timetaken); | |
312 | } | |
313 | ||
314 | } | |
315 | ||
316 | ||
317 | ||
318 | void | |
319 | sim_kill () | |
320 | { | |
321 | ||
322 | } | |
323 | ||
324 | void | |
325 | sim_open (name) | |
326 | char *name; | |
327 | { | |
328 | } | |
329 | ||
330 | ||
331 | ||
332 | #undef fetch8 | |
333 | fetch8func (x) | |
334 | { | |
335 | if (x & ~MMASK) | |
336 | { | |
337 | saved_state.exception = SIGBUS; | |
338 | return 0; | |
339 | } | |
340 | return saved_state.memory[x]; | |
341 | } | |
342 | ||
343 | fetch8 (x) | |
344 | { | |
345 | return fetch8func(x); | |
346 | } | |
347 | ||
348 | void | |
349 | sim_close (quitting) | |
350 | int quitting; | |
351 | { | |
352 | /* nothing to do */ | |
353 | } | |
354 | ||
355 | int | |
356 | sim_load (prog, from_tty) | |
357 | char *prog; | |
358 | int from_tty; | |
359 | { | |
360 | /* Return nonzero so gdb will handle it. */ | |
361 | return 1; | |
362 | } | |
363 | ||
364 | ||
365 | void | |
366 | sim_create_inferior (start_address, argv, env) | |
367 | SIM_ADDR start_address; | |
368 | char **argv; | |
369 | char **env; | |
370 | { | |
371 | /* ??? We assume this is a 4 byte quantity. */ | |
372 | int pc; | |
373 | ||
374 | pc = start_address; | |
375 | sim_store_register (16, (unsigned char *) &pc); | |
376 | } | |
a325a02e SC |
377 | |
378 | void | |
379 | sim_set_callbacks (ptr) | |
380 | struct host_callback_struct *ptr; | |
381 | { | |
382 | ||
383 | } |