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>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <sys/fcntl.h>
29 #include "sis.h"
30 #include "bfd.h"
31 #include <dis-asm.h>
32 #include "sim-config.h"
33
34 #include "gdb/remote-sim.h"
35
36 #ifndef fprintf
37 extern fprintf();
38 #endif
39
40 #define PSR_CWP 0x7
41
42 #define VAL(x) strtol(x,(char **)NULL,0)
43
44 extern char **buildargv(char *input);
45
46 extern struct disassemble_info dinfo;
47 extern struct pstate sregs;
48 extern struct estate ebase;
49
50 extern int current_target_byte_order;
51 extern int ctrl_c;
52 extern int nfp;
53 extern int ift;
54 extern int rom8;
55 extern int wrp;
56 extern int uben;
proto_register_cisco_pid(void)57 extern int sis_verbose;
58 extern char *sis_version;
59 extern struct estate ebase;
60 extern struct evcell evbuf[];
61 extern struct irqcell irqarr[];
62 extern int irqpend, ext_irl;
63 extern int sparclite;
64 extern int dumbio;
65 extern int sparclite_board;
66 extern int termsave;
67 extern char uart_dev1[], uart_dev2[];
68
69 int sis_gdb_break = 1;
70
71 host_callback *sim_callback;
72
73 int
74 run_sim(sregs, icount, dis)
75 struct pstate *sregs;
76 unsigned int icount;
77 int dis;
78 {
79 int mexc, irq;
80
81 if (sis_verbose)
82 (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
83 sregs->pc);
84 init_stdio();
85 sregs->starttime = time(NULL);
86 irq = 0;
87 while (!sregs->err_mode & (icount > 0)) {
88
89 sregs->fhold = 0;
90 sregs->hold = 0;
91 sregs->icnt = 1;
92
93 if (sregs->psr & 0x080)
94 sregs->asi = 8;
95 else
96 sregs->asi = 9;
97
98 #if 0 /* DELETE ME! for debugging purposes only */
99 if (sis_verbose > 1)
100 if (sregs->pc == 0 || sregs->npc == 0)
101 printf ("bogus pc or npc\n");
102 #endif
103 mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst,
104 2, &sregs->hold);
105 #if 1 /* DELETE ME! for debugging purposes only */
106 if (sis_verbose > 2)
107 printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
108 sregs->pc, sregs->npc,
109 sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
110 sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
111 sregs->wim,
112 sregs->psr & 7,
113 sregs->inst);
114 #endif
115 if (sregs->annul) {
116 sregs->annul = 0;
117 sregs->icnt = 1;
118 sregs->pc = sregs->npc;
119 sregs->npc = sregs->npc + 4;
120 } else {
121 if (ext_irl) irq = check_interrupts(sregs);
122 if (!irq) {
123 if (mexc) {
124 sregs->trap = I_ACC_EXC;
125 } else {
126 if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
127 if (sis_verbose)
128 (*sim_callback->printf_filtered) (sim_callback,
129 "SW BP hit at %x\n", sregs->pc);
130 sim_halt();
131 restore_stdio();
132 clearerr(stdin);
133 return (BPT_HIT);
134 } else
135 dispatch_instruction(sregs);
136 }
137 icount--;
138 }
139 if (sregs->trap) {
140 irq = 0;
141 sregs->err_mode = execute_trap(sregs);
142 }
143 }
144 advance_time(sregs);
145 if (ctrl_c) {
146 icount = 0;
147 }
148 }
149 sim_halt();
150 sregs->tottime += time(NULL) - sregs->starttime;
151 restore_stdio();
152 clearerr(stdin);
153 if (sregs->err_mode)
154 error_mode(sregs->pc);
155 if (sregs->err_mode)
156 return (ERROR);
157 if (sregs->bphit) {
158 if (sis_verbose)
159 (*sim_callback->printf_filtered) (sim_callback,
160 "HW BP hit at %x\n", sregs->pc);
161 return (BPT_HIT);
162 }
163 if (ctrl_c) {
164 ctrl_c = 0;
165 return (CTRL_C);
166 }
167 return (TIME_OUT);
168 }
169
170 void
171 sim_set_callbacks (ptr)
172 host_callback *ptr;
173 {
174 sim_callback = ptr;
175 }
176
177 void
178 sim_size (memsize)
179 int memsize;
180 {
181 }
182
183 SIM_DESC
184 sim_open (kind, callback, abfd, argv)
185 SIM_OPEN_KIND kind;
186 struct host_callback_struct *callback;
187 struct bfd *abfd;
188 char **argv;
189 {
190
191 int argc = 0;
192 int stat = 1;
193 int freq = 0;
194
195 sim_callback = callback;
196
197 while (argv[argc])
198 argc++;
199 while (stat < argc) {
200 if (argv[stat][0] == '-') {
201 if (strcmp(argv[stat], "-v") == 0) {
202 sis_verbose++;
203 } else
204 if (strcmp(argv[stat], "-nfp") == 0) {
205 nfp = 1;
206 } else
207 if (strcmp(argv[stat], "-ift") == 0) {
208 ift = 1;
209 } else
210 if (strcmp(argv[stat], "-sparclite") == 0) {
211 sparclite = 1;
212 } else
213 if (strcmp(argv[stat], "-sparclite-board") == 0) {
214 sparclite_board = 1;
215 } else
216 if (strcmp(argv[stat], "-dumbio") == 0) {
217 dumbio = 1;
218 } else
219 if (strcmp(argv[stat], "-wrp") == 0) {
220 wrp = 1;
221 } else
222 if (strcmp(argv[stat], "-rom8") == 0) {
223 rom8 = 1;
224 } else
225 if (strcmp(argv[stat], "-uben") == 0) {
226 uben = 1;
227 } else
228 if (strcmp(argv[stat], "-uart1") == 0) {
229 if ((stat + 1) < argc)
230 strcpy(uart_dev1, argv[++stat]);
231 } else
232 if (strcmp(argv[stat], "-uart2") == 0) {
233 if ((stat + 1) < argc)
234 strcpy(uart_dev2, argv[++stat]);
235 } else
236 if (strcmp(argv[stat], "-nogdb") == 0) {
237 sis_gdb_break = 0;
238 } else
239 if (strcmp(argv[stat], "-freq") == 0) {
240 if ((stat + 1) < argc) {
241 freq = VAL(argv[++stat]);
242 }
243 } else {
244 (*sim_callback->printf_filtered) (sim_callback,
245 "unknown option %s\n",
246 argv[stat]);
247 }
248 } else
249 bfd_load(argv[stat]);
250 stat++;
251 }
252
253 if (sis_verbose) {
254 (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
255 (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
256 if (nfp)
257 (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
258 if (sparclite)
259 (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
260 if (dumbio)
261 (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
262 if (sis_gdb_break == 0)
263 (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
264 if (freq)
265 (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
266 }
267
268 sregs.freq = freq ? freq : 15;
269 termsave = fcntl(0, F_GETFL, 0);
270 INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
271 dinfo.endian = BFD_ENDIAN_BIG;
272 reset_all();
273 ebase.simtime = 0;
274 init_sim();
275 init_bpt(&sregs);
276 reset_stat(&sregs);
277
278 /* Fudge our descriptor for now. */
279 return (SIM_DESC) 1;
280 }
281
282 void
283 sim_close(sd, quitting)
284 SIM_DESC sd;
285 int quitting;
286 {
287
288 exit_sim();
289 fcntl(0, F_SETFL, termsave);
290
291 };
292
293 SIM_RC
294 sim_load(sd, prog, abfd, from_tty)
295 SIM_DESC sd;
296 char *prog;
297 bfd *abfd;
298 int from_tty;
299 {
300 bfd_load (prog);
301 return SIM_RC_OK;
302 }
303
304 SIM_RC
305 sim_create_inferior(sd, abfd, argv, env)
306 SIM_DESC sd;
307 struct bfd *abfd;
308 char **argv;
309 char **env;
310 {
311 bfd_vma start_address = 0;
312 if (abfd != NULL)
313 start_address = bfd_get_start_address (abfd);
314
315 ebase.simtime = 0;
316 reset_all();
317 reset_stat(&sregs);
318 sregs.pc = start_address & ~3;
319 sregs.npc = sregs.pc + 4;
320 return SIM_RC_OK;
321 }
322
323 int
324 sim_store_register(sd, regno, value, length)
325 SIM_DESC sd;
326 int regno;
327 unsigned char *value;
328 int length;
329 {
330 /* FIXME: Review the computation of regval. */
331 int regval;
332 if (current_target_byte_order == BIG_ENDIAN)
333 regval = (value[0] << 24) | (value[1] << 16)
334 | (value[2] << 8) | value[3];
335 else
336 regval = (value[3] << 24) | (value[2] << 16)
337 | (value[1] << 8) | value[0];
338 set_regi(&sregs, regno, regval);
339 return -1;
340 }
341
342
343 int
344 sim_fetch_register(sd, regno, buf, length)
345 SIM_DESC sd;
346 int regno;
347 unsigned char *buf;
348 int length;
349 {
350 get_regi(&sregs, regno, buf);
351 return -1;
352 }
353
354 int
355 sim_write(sd, mem, buf, length)
356 SIM_DESC sd;
357 SIM_ADDR mem;
358 unsigned char *buf;
359 int length;
360 {
361 return (sis_memory_write(mem, buf, length));
362 }
363
364 int
365 sim_read(sd, mem, buf, length)
366 SIM_DESC sd;
367 SIM_ADDR mem;
368 unsigned char *buf;
369 int length;
370 {
371 return (sis_memory_read(mem, buf, length));
372 }
373
374 void
375 sim_info(sd, verbose)
376 SIM_DESC sd;
377 int verbose;
378 {
379 show_stat(&sregs);
380 }
381
382 int simstat = OK;
383
384 void
385 sim_stop_reason(sd, reason, sigrc)
386 SIM_DESC sd;
387 enum sim_stop * reason;
388 int *sigrc;
389 {
390
391 switch (simstat) {
392 case CTRL_C:
393 *reason = sim_stopped;
394 *sigrc = SIGINT;
395 break;
396 case OK:
397 case TIME_OUT:
398 case BPT_HIT:
399 *reason = sim_stopped;
400 #ifdef _WIN32
401 #define SIGTRAP 5
402 #endif
403 *sigrc = SIGTRAP;
404 break;
405 case ERROR:
406 *sigrc = 0;
407 *reason = sim_exited;
408 }
409 ctrl_c = 0;
410 simstat = OK;
411 }
412
413 /* Flush all register windows out to the stack. Starting after the invalid
414 window, flush all windows up to, and including the current window. This
415 allows GDB to do backtraces and look at local variables for frames that
416 are still in the register windows. Note that strictly speaking, this
417 behavior is *wrong* for several reasons. First, it doesn't use the window
418 overflow handlers. It therefore assumes standard frame layouts and window
419 handling policies. Second, it changes system state behind the back of the
420 target program. I expect this to mainly pose problems when debugging trap
421 handlers.
422 */
423
424 static void
425 flush_windows ()
426 {
427 int invwin;
428 int cwp;
429 int win;
430 int ws;
431
432 /* Keep current window handy */
433
434 cwp = sregs.psr & PSR_CWP;
435
436 /* Calculate the invalid window from the wim. */
437
438 for (invwin = 0; invwin <= PSR_CWP; invwin++)
439 if ((sregs.wim >> invwin) & 1)
440 break;
441
442 /* Start saving with the window after the invalid window. */
443
444 invwin = (invwin - 1) & PSR_CWP;
445
446 for (win = invwin; ; win = (win - 1) & PSR_CWP)
447 {
448 uint32 sp;
449 int i;
450
451 sp = sregs.r[(win * 16 + 14) & 0x7f];
452 #if 1
453 if (sis_verbose > 2) {
454 uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
455 printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
456 }
457 #endif
458
459 for (i = 0; i < 16; i++)
460 memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
461 &ws);
462
463 if (win == cwp)
464 break;
465 }
466 }
467
468 void
469 sim_resume(SIM_DESC sd, int step, int siggnal)
470 {
471 simstat = run_sim(&sregs, -1, 0);
472
473 if (sis_gdb_break) flush_windows ();
474 }
475
476 int
477 sim_trace (sd)
478 SIM_DESC sd;
479 {
480 /* FIXME: unfinished */
481 sim_resume (sd, 0, 0);
482 return 1;
483 }
484
485 void
486 sim_do_command(sd, cmd)
487 SIM_DESC sd;
488 char *cmd;
489 {
490 exec_cmd(&sregs, cmd);
491 }
492
493 #if 0 /* FIXME: These shouldn't exist. */
494
495 int
496 sim_insert_breakpoint(int addr)
497 {
498 if (sregs.bptnum < BPT_MAX) {
499 sregs.bpts[sregs.bptnum] = addr & ~0x3;
500 sregs.bptnum++;
501 if (sis_verbose)
502 (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
503 return 0;
504 } else
505 return 1;
506 }
507
508 int
509 sim_remove_breakpoint(int addr)
510 {
511 int i = 0;
512
513 while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
514 i++;
515 if (addr == sregs.bpts[i]) {
516 for (; i < sregs.bptnum - 1; i++)
517 sregs.bpts[i] = sregs.bpts[i + 1];
518 sregs.bptnum -= 1;
519 if (sis_verbose)
520 (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
521 return 0;
522 }
523 return 1;
524 }
525
526 #endif
527