Commit | Line | Data |
---|---|---|
f4d2ff34 RS |
1 | /* |
2 | * This file is part of SIS. | |
3 | * | |
4 | * SIS, SPARC instruction simulator V1.6 Copyright (C) 1995 Jiri Gaisler, | |
5 | * European Space Agency | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it under | |
8 | * the terms of the GNU General Public License as published by the Free | |
9 | * Software Foundation; either version 2 of the License, or (at your option) | |
10 | * any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 | * more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along with | |
18 | * this program; if not, write to the Free Software Foundation, Inc., 675 | |
19 | * Mass Ave, Cambridge, MA 02139, USA. | |
20 | * | |
21 | */ | |
22 | ||
23 | #include <signal.h> | |
24 | #include <string.h> | |
25 | #include <stdio.h> | |
a665caa6 | 26 | #include <sys/fcntl.h> |
f4d2ff34 RS |
27 | #include "sis.h" |
28 | #include "bfd.h" | |
29 | #include <dis-asm.h> | |
30 | ||
a665caa6 RS |
31 | #include "remote-sim.h" |
32 | ||
f4d2ff34 RS |
33 | #ifndef fprintf |
34 | extern fprintf(); | |
35 | #endif | |
36 | ||
37 | #define VAL(x) strtol(x,(char *)NULL,0) | |
38 | ||
39 | extern char **buildargv(char *input); | |
40 | ||
41 | extern struct disassemble_info dinfo; | |
42 | extern struct pstate sregs; | |
43 | extern struct estate ebase; | |
44 | ||
45 | extern int ctrl_c; | |
46 | extern int nfp; | |
a665caa6 RS |
47 | extern int ift; |
48 | extern int rom8; | |
49 | extern int wrp; | |
f4d2ff34 RS |
50 | extern int sis_verbose; |
51 | extern char *sis_version; | |
52 | extern struct estate ebase; | |
53 | extern struct evcell evbuf[]; | |
54 | extern struct irqcell irqarr[]; | |
55 | extern int irqpend, ext_irl; | |
a665caa6 RS |
56 | extern int sparclite; |
57 | extern int termsave; | |
58 | extern char uart_dev1[], uart_dev2[]; | |
f4d2ff34 RS |
59 | |
60 | int sis_gdb_break = 1; | |
61 | ||
a665caa6 | 62 | host_callback *sim_callback; |
f4d2ff34 RS |
63 | |
64 | run_sim(sregs, go, icount, dis) | |
65 | struct pstate *sregs; | |
66 | int go; | |
67 | unsigned int icount; | |
68 | int dis; | |
69 | { | |
70 | int mexc, ws; | |
71 | ||
72 | if (sis_verbose) | |
a665caa6 RS |
73 | (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n", |
74 | sregs->pc); | |
75 | init_stdio(); | |
76 | sregs->starttime = time(NULL); | |
f4d2ff34 RS |
77 | while ((!sregs->err_mode & (go || (icount > 0))) && |
78 | ((sregs->bptnum == 0) || !(sregs->bphit = check_bpt(sregs)))) { | |
79 | ||
80 | sregs->fhold = 0; | |
81 | sregs->hold = 0; | |
82 | sregs->icnt = 0; | |
83 | ||
84 | check_interrupts(sregs); | |
85 | if (sregs->trap) { | |
86 | sregs->err_mode = execute_trap(sregs); | |
87 | } else { | |
88 | if (sregs->psr & 0x080) | |
89 | sregs->asi = 8; | |
90 | else | |
91 | sregs->asi = 9; | |
f4d2ff34 RS |
92 | |
93 | mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst, &sregs->hold); | |
94 | if (sregs->annul) { | |
95 | sregs->annul = 0; | |
96 | sregs->icnt = 1; | |
97 | sregs->pc = sregs->npc; | |
98 | sregs->npc = sregs->npc + 4; | |
99 | } else { | |
100 | if (mexc) { | |
101 | sregs->trap = I_ACC_EXC; | |
102 | } else { | |
103 | if (sregs->histlen) { | |
104 | sregs->histbuf[sregs->histind].addr = sregs->pc; | |
105 | sregs->histbuf[sregs->histind].time = ebase.simtime; | |
106 | sregs->histind++; | |
107 | if (sregs->histind >= sregs->histlen) | |
108 | sregs->histind = 0; | |
109 | } | |
110 | if (dis) { | |
111 | printf(" %8d ", ebase.simtime); | |
112 | dis_mem(sregs->pc, 1, &dinfo); | |
113 | } | |
114 | if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) { | |
115 | if (sis_verbose) | |
a665caa6 RS |
116 | (*sim_callback->printf_filtered) (sim_callback, |
117 | "SW BP hit at %x\n", sregs->pc); | |
f4d2ff34 RS |
118 | return (BPT_HIT); |
119 | } else | |
120 | dispatch_instruction(sregs); | |
121 | } | |
122 | icount--; | |
123 | } | |
124 | if (sregs->trap) { | |
125 | sregs->err_mode = execute_trap(sregs); | |
126 | } | |
127 | } | |
128 | advance_time(sregs); | |
129 | if (ctrl_c) { | |
130 | go = icount = 0; | |
131 | } | |
132 | } | |
a665caa6 | 133 | sim_stop(); |
f4d2ff34 | 134 | sregs->tottime += time(NULL) - sregs->starttime; |
a665caa6 RS |
135 | restore_stdio(); |
136 | clearerr(stdin); | |
f4d2ff34 RS |
137 | if (sregs->err_mode) |
138 | error_mode(sregs->pc); | |
139 | if (sregs->err_mode) | |
140 | return (ERROR); | |
141 | if (sregs->bphit) { | |
142 | if (sis_verbose) | |
a665caa6 RS |
143 | (*sim_callback->printf_filtered) (sim_callback, |
144 | "HW BP hit at %x\n", sregs->pc); | |
f4d2ff34 RS |
145 | return (BPT_HIT); |
146 | } | |
147 | if (ctrl_c) { | |
148 | ctrl_c = 0; | |
149 | return (CTRL_C); | |
150 | } | |
151 | return (TIME_OUT); | |
152 | } | |
153 | ||
a665caa6 RS |
154 | void |
155 | sim_set_callbacks (ptr) | |
156 | host_callback *ptr; | |
157 | { | |
158 | sim_callback = ptr; | |
159 | } | |
f4d2ff34 RS |
160 | |
161 | void | |
a665caa6 RS |
162 | sim_size (memsize) |
163 | int memsize; | |
164 | { | |
165 | } | |
166 | ||
167 | void | |
168 | sim_open(args) | |
169 | char *args; | |
f4d2ff34 RS |
170 | { |
171 | ||
172 | int argc = 0; | |
173 | char **argv; | |
174 | int cont = 1; | |
175 | int stat = 0; | |
176 | int grdl = 0; | |
177 | int freq = 15; | |
178 | ||
a665caa6 RS |
179 | (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version); |
180 | (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n"); | |
f4d2ff34 RS |
181 | argv = buildargv(args); |
182 | if (argv != NULL) | |
183 | while (argv[argc]) | |
184 | argc++; | |
185 | while (stat < argc) { | |
186 | if (argv[stat][0] == '-') { | |
187 | if (strcmp(argv[stat], "-v") == 0) { | |
188 | sis_verbose = 1; | |
a665caa6 | 189 | } else |
f4d2ff34 | 190 | if (strcmp(argv[stat], "-nfp") == 0) { |
a665caa6 | 191 | (*sim_callback->printf_filtered) (sim_callback, "no FPU\n"); |
f4d2ff34 | 192 | nfp = 1; |
a665caa6 RS |
193 | } else |
194 | if (strcmp(argv[stat], "-ift") == 0) { | |
195 | ift = 1; | |
196 | } else | |
197 | if (strcmp(argv[stat], "-sparclite") == 0) { | |
198 | (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n"); | |
199 | sparclite = 1; | |
200 | } else | |
201 | if (strcmp(argv[stat], "-wrp") == 0) { | |
202 | wrp = 1; | |
203 | } else | |
204 | if (strcmp(argv[stat], "-rom8") == 0) { | |
205 | rom8 = 1; | |
206 | } else | |
207 | if (strcmp(argv[stat], "-uart1") == 0) { | |
208 | if ((stat + 1) < argc) | |
209 | strcpy(uart_dev1, argv[++stat]); | |
210 | } else | |
211 | if (strcmp(argv[stat], "-uart2") == 0) { | |
212 | if ((stat + 1) < argc) | |
213 | strcpy(uart_dev2, argv[++stat]); | |
214 | } else | |
f4d2ff34 | 215 | if (strcmp(argv[stat], "-nogdb") == 0) { |
a665caa6 | 216 | (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n"); |
f4d2ff34 | 217 | sis_gdb_break = 0; |
a665caa6 | 218 | } else |
f4d2ff34 RS |
219 | if (strcmp(argv[stat], "-freq") == 0) |
220 | if ((stat + 1) < argc) { | |
221 | freq = VAL(argv[++stat]); | |
a665caa6 | 222 | (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq); |
f4d2ff34 RS |
223 | } |
224 | } else | |
225 | bfd_load(argv[stat]); | |
226 | stat++; | |
227 | } | |
228 | freeargv(argv); | |
229 | sregs.freq = freq; | |
a665caa6 RS |
230 | termsave = fcntl(0, F_GETFL, 0); |
231 | INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf); | |
f4d2ff34 RS |
232 | init_signals(); |
233 | reset_all(); | |
234 | ebase.simtime = 0; | |
235 | init_sim(); | |
236 | init_bpt(&sregs); | |
237 | reset_stat(&sregs); | |
238 | } | |
239 | ||
240 | void | |
241 | sim_close(int quitting) | |
242 | { | |
243 | ||
244 | exit_sim(); | |
a665caa6 | 245 | fcntl(0, F_SETFL, termsave); |
f4d2ff34 RS |
246 | |
247 | }; | |
248 | ||
b7b31114 SG |
249 | /* Return non-zero if the caller should handle the load. Zero if |
250 | we have loaded the image. */ | |
a665caa6 RS |
251 | |
252 | int sim_load PARAMS ((char *prog, int from_tty)); | |
253 | ||
f4d2ff34 | 254 | int |
a665caa6 RS |
255 | sim_load(prog, from_tty) |
256 | char *prog; | |
257 | int from_tty; | |
f4d2ff34 | 258 | { |
b7b31114 | 259 | bfd_load(prog); |
f4d2ff34 RS |
260 | return (0); |
261 | } | |
262 | ||
a665caa6 RS |
263 | void sim_create_inferior PARAMS ((SIM_ADDR start_address, char **argv, char **env)); |
264 | ||
f4d2ff34 | 265 | void |
a665caa6 RS |
266 | sim_create_inferior(start_address, argv, env) |
267 | SIM_ADDR start_address; | |
268 | char **argv; | |
269 | char **env; | |
f4d2ff34 RS |
270 | { |
271 | ebase.simtime = 0; | |
272 | reset_all(); | |
273 | reset_stat(&sregs); | |
274 | sregs.pc = start_address & ~3; | |
275 | sregs.npc = sregs.pc + 4; | |
276 | ||
277 | } | |
278 | ||
279 | void | |
280 | sim_store_register(regno, value) | |
281 | int regno; | |
282 | unsigned char *value; | |
283 | { | |
284 | /* FIXME: Review the computation of regval. */ | |
285 | int regval = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]; | |
286 | set_regi(&sregs, regno, regval); | |
287 | } | |
288 | ||
289 | ||
290 | void | |
291 | sim_fetch_register(regno, buf) | |
292 | int regno; | |
293 | unsigned char *buf; | |
294 | { | |
295 | get_regi(&sregs, regno, buf); | |
296 | } | |
297 | ||
298 | int | |
299 | sim_write(mem, buf, length) | |
a665caa6 | 300 | SIM_ADDR mem; |
f4d2ff34 RS |
301 | unsigned char *buf; |
302 | int length; | |
303 | { | |
304 | return (sis_memory_write(mem, buf, length)); | |
305 | } | |
306 | ||
a665caa6 RS |
307 | int sim_read PARAMS ((SIM_ADDR mem, unsigned char *buf, int length)); |
308 | ||
f4d2ff34 | 309 | int |
a665caa6 RS |
310 | sim_read(mem, buf, length) |
311 | SIM_ADDR mem; | |
312 | unsigned char *buf; | |
313 | int length; | |
f4d2ff34 RS |
314 | { |
315 | return (sis_memory_read(mem, buf, length)); | |
316 | } | |
317 | ||
318 | void | |
319 | sim_info(int verbose) | |
320 | { | |
321 | show_stat(&sregs); | |
322 | ||
323 | ||
324 | } | |
325 | ||
326 | int simstat = OK; | |
327 | ||
f4d2ff34 RS |
328 | void |
329 | sim_stop_reason(enum sim_stop * reason, int *sigrc) | |
330 | { | |
331 | ||
332 | switch (simstat) { | |
333 | case CTRL_C: | |
334 | *reason = sim_stopped; | |
335 | *sigrc = SIGINT; | |
336 | break; | |
337 | case OK: | |
338 | case TIME_OUT: | |
339 | case BPT_HIT: | |
340 | *reason = sim_stopped; | |
a665caa6 RS |
341 | #ifdef _WIN32 |
342 | #define SIGTRAP 5 | |
343 | #endif | |
f4d2ff34 RS |
344 | *sigrc = SIGTRAP; |
345 | break; | |
346 | case ERROR: | |
347 | *sigrc = 0; | |
348 | *reason = sim_exited; | |
349 | } | |
350 | ctrl_c = 0; | |
351 | simstat = OK; | |
352 | } | |
353 | ||
b7b31114 SG |
354 | /* Flush all register windows out to the stack. Starting after the invalid |
355 | window, flush all windows up to, and including the current window. This | |
356 | allows GDB to do backtraces and look at local variables for frames that | |
357 | are still in the register windows. Note that strictly speaking, this | |
358 | behavior is *wrong* for several reasons. First, it doesn't use the window | |
359 | overflow handlers. It therefore assumes standard frame layouts and window | |
360 | handling policies. Second, it changes system state behind the back of the | |
361 | target program. I expect this to mainly pose problems when debugging trap | |
362 | handlers. | |
363 | */ | |
364 | ||
365 | #define PSR_CWP 0x7 | |
366 | ||
367 | static void | |
368 | flush_windows () | |
369 | { | |
370 | int invwin; | |
371 | int cwp; | |
372 | int win; | |
373 | int ws; | |
374 | ||
375 | /* Keep current window handy */ | |
376 | ||
377 | cwp = sregs.psr & PSR_CWP; | |
378 | ||
379 | /* Calculate the invalid window from the wim. */ | |
380 | ||
381 | for (invwin = 0; invwin <= PSR_CWP; invwin++) | |
382 | if ((sregs.wim >> invwin) & 1) | |
383 | break; | |
384 | ||
385 | /* Start saving with the window after the invalid window. */ | |
386 | ||
387 | invwin = (invwin - 1) & PSR_CWP; | |
388 | ||
389 | for (win = invwin; ; win = (win - 1) & PSR_CWP) | |
390 | { | |
391 | uint32 sp; | |
392 | int i; | |
393 | ||
394 | sp = sregs.r[(win * 16 + 14) & 0x7f]; | |
395 | ||
396 | for (i = 0; i < 16; i++) | |
397 | memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2, | |
398 | &ws); | |
399 | ||
400 | if (win == cwp) | |
401 | break; | |
402 | } | |
403 | } | |
f4d2ff34 RS |
404 | |
405 | void | |
406 | sim_resume(int step, int siggnal) | |
407 | { | |
408 | simstat = run_sim(&sregs, 1, 0, 0); | |
b7b31114 | 409 | |
a665caa6 RS |
410 | if (sis_gdb_break) flush_windows (); |
411 | } | |
412 | ||
413 | int | |
414 | sim_trace () | |
415 | { | |
416 | /* FIXME: unfinished */ | |
417 | sim_resume (0, 0); | |
418 | return 1; | |
f4d2ff34 RS |
419 | } |
420 | ||
421 | void | |
422 | sim_kill(void) | |
423 | { | |
a665caa6 | 424 | } |
f4d2ff34 RS |
425 | |
426 | void | |
427 | sim_do_command(cmd) | |
428 | char *cmd; | |
429 | { | |
430 | exec_cmd(&sregs, cmd); | |
431 | } | |
432 | ||
a665caa6 | 433 | #if 0 /* FIXME: These shouldn't exist. */ |
f4d2ff34 RS |
434 | |
435 | int | |
436 | sim_insert_breakpoint(int addr) | |
437 | { | |
438 | if (sregs.bptnum < BPT_MAX) { | |
439 | sregs.bpts[sregs.bptnum] = addr & ~0x3; | |
440 | sregs.bptnum++; | |
441 | if (sis_verbose) | |
a665caa6 | 442 | (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr); |
f4d2ff34 RS |
443 | return 0; |
444 | } else | |
445 | return 1; | |
446 | } | |
447 | ||
448 | int | |
449 | sim_remove_breakpoint(int addr) | |
450 | { | |
451 | int i = 0; | |
452 | ||
453 | while ((i < sregs.bptnum) && (sregs.bpts[i] != addr)) | |
454 | i++; | |
455 | if (addr == sregs.bpts[i]) { | |
456 | for (; i < sregs.bptnum - 1; i++) | |
457 | sregs.bpts[i] = sregs.bpts[i + 1]; | |
458 | sregs.bptnum -= 1; | |
459 | if (sis_verbose) | |
a665caa6 | 460 | (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr); |
f4d2ff34 RS |
461 | return 0; |
462 | } | |
463 | return 1; | |
464 | } | |
a665caa6 RS |
465 | |
466 | #endif |