2 * This file is part of SIS.
4 * SIS, SPARC instruction simulator V1.6 Copyright (C) 1995 Jiri Gaisler,
5 * European Space Agency
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 3 of the License, or (at your option)
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
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, see <http://www.gnu.org/licenses/>.
28 #include <sys/fcntl.h>
30 #include "libiberty.h"
33 #include "sim-config.h"
35 #include "gdb/remote-sim.h"
36 #include "gdb/signals.h"
40 extern struct disassemble_info dinfo;
41 extern struct pstate sregs;
42 extern struct estate ebase;
44 extern int current_target_byte_order;
51 extern int sis_verbose;
52 extern char *sis_version;
53 extern struct estate ebase;
54 extern struct evcell evbuf[];
55 extern struct irqcell irqarr[];
56 extern int irqpend, ext_irl;
59 extern int sparclite_board;
61 extern char uart_dev1[], uart_dev2[];
63 int sis_gdb_break = 1;
65 host_callback *sim_callback;
68 run_sim(sregs, icount, dis)
76 (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
79 sregs->starttime = time(NULL);
81 while (!sregs->err_mode & (icount > 0)) {
87 if (sregs->psr & 0x080)
92 #if 0 /* DELETE ME! for debugging purposes only */
94 if (sregs->pc == 0 || sregs->npc == 0)
95 printf ("bogus pc or npc\n");
97 mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst,
99 #if 1 /* DELETE ME! for debugging purposes only */
101 printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
102 sregs->pc, sregs->npc,
103 sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
104 sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
112 sregs->pc = sregs->npc;
113 sregs->npc = sregs->npc + 4;
115 if (ext_irl) irq = check_interrupts(sregs);
118 sregs->trap = I_ACC_EXC;
120 if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
122 (*sim_callback->printf_filtered) (sim_callback,
123 "SW BP hit at %x\n", sregs->pc);
129 dispatch_instruction(sregs);
135 sregs->err_mode = execute_trap(sregs);
144 sregs->tottime += time(NULL) - sregs->starttime;
148 error_mode(sregs->pc);
153 (*sim_callback->printf_filtered) (sim_callback,
154 "HW BP hit at %x\n", sregs->pc);
165 sim_set_callbacks (ptr)
178 sim_open (kind, callback, abfd, argv)
180 struct host_callback_struct *callback;
189 sim_callback = callback;
193 while (stat < argc) {
194 if (argv[stat][0] == '-') {
195 if (strcmp(argv[stat], "-v") == 0) {
198 if (strcmp(argv[stat], "-nfp") == 0) {
201 if (strcmp(argv[stat], "-ift") == 0) {
204 if (strcmp(argv[stat], "-sparclite") == 0) {
207 if (strcmp(argv[stat], "-sparclite-board") == 0) {
210 if (strcmp(argv[stat], "-dumbio") == 0) {
213 if (strcmp(argv[stat], "-wrp") == 0) {
216 if (strcmp(argv[stat], "-rom8") == 0) {
219 if (strcmp(argv[stat], "-uben") == 0) {
222 if (strcmp(argv[stat], "-uart1") == 0) {
223 if ((stat + 1) < argc)
224 strcpy(uart_dev1, argv[++stat]);
226 if (strcmp(argv[stat], "-uart2") == 0) {
227 if ((stat + 1) < argc)
228 strcpy(uart_dev2, argv[++stat]);
230 if (strcmp(argv[stat], "-nogdb") == 0) {
233 if (strcmp(argv[stat], "-freq") == 0) {
234 if ((stat + 1) < argc) {
235 freq = strtol(argv[++stat], (char **)NULL, 0);
238 if (strncmp(argv[stat], "--sysroot=", sizeof("--sysroot=") - 1) == 0) {
239 /* Ignore until we start to support this. */
241 (*sim_callback->printf_filtered) (sim_callback,
242 "unknown option %s\n",
246 bfd_load(argv[stat]);
251 (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
252 (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (
[email protected])\n");
254 (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
256 (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
258 (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
259 if (sis_gdb_break == 0)
260 (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
262 (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
265 sregs.freq = freq ? freq : 15;
266 termsave = fcntl(0, F_GETFL, 0);
267 INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
268 dinfo.endian = BFD_ENDIAN_BIG;
275 /* Fudge our descriptor for now. */
280 sim_close(sd, quitting)
286 fcntl(0, F_SETFL, termsave);
291 sim_load(sd, prog, abfd, from_tty)
302 sim_create_inferior(sd, abfd, argv, env)
308 bfd_vma start_address = 0;
310 start_address = bfd_get_start_address (abfd);
315 sregs.pc = start_address & ~3;
316 sregs.npc = sregs.pc + 4;
321 sim_store_register(sd, regno, value, length)
324 unsigned char *value;
327 /* FIXME: Review the computation of regval. */
329 if (current_target_byte_order == BIG_ENDIAN)
330 regval = (value[0] << 24) | (value[1] << 16)
331 | (value[2] << 8) | value[3];
333 regval = (value[3] << 24) | (value[2] << 16)
334 | (value[1] << 8) | value[0];
335 set_regi(&sregs, regno, regval);
341 sim_fetch_register(sd, regno, buf, length)
347 get_regi(&sregs, regno, buf);
352 sim_write(sd, mem, buf, length)
355 const unsigned char *buf;
358 return (sis_memory_write(mem, buf, length));
362 sim_read(sd, mem, buf, length)
368 return (sis_memory_read(mem, buf, length));
372 sim_info(sd, verbose)
382 sim_stop_reason(sd, reason, sigrc)
384 enum sim_stop * reason;
390 *reason = sim_stopped;
391 *sigrc = GDB_SIGNAL_INT;
396 *reason = sim_stopped;
397 *sigrc = GDB_SIGNAL_TRAP;
401 *reason = sim_exited;
407 /* Flush all register windows out to the stack. Starting after the invalid
408 window, flush all windows up to, and including the current window. This
409 allows GDB to do backtraces and look at local variables for frames that
410 are still in the register windows. Note that strictly speaking, this
411 behavior is *wrong* for several reasons. First, it doesn't use the window
412 overflow handlers. It therefore assumes standard frame layouts and window
413 handling policies. Second, it changes system state behind the back of the
414 target program. I expect this to mainly pose problems when debugging trap
426 /* Keep current window handy */
428 cwp = sregs.psr & PSR_CWP;
430 /* Calculate the invalid window from the wim. */
432 for (invwin = 0; invwin <= PSR_CWP; invwin++)
433 if ((sregs.wim >> invwin) & 1)
436 /* Start saving with the window after the invalid window. */
438 invwin = (invwin - 1) & PSR_CWP;
440 for (win = invwin; ; win = (win - 1) & PSR_CWP)
445 sp = sregs.r[(win * 16 + 14) & 0x7f];
447 if (sis_verbose > 2) {
448 uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
449 printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
453 for (i = 0; i < 16; i++)
454 memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
463 sim_resume(SIM_DESC sd, int step, int siggnal)
465 simstat = run_sim(&sregs, UINT64_MAX, 0);
467 if (sis_gdb_break) flush_windows ();
474 /* FIXME: unfinished */
475 sim_resume (sd, 0, 0);
480 sim_do_command(sd, cmd)
484 exec_cmd(&sregs, cmd);
488 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
493 #if 0 /* FIXME: These shouldn't exist. */
496 sim_insert_breakpoint(int addr)
498 if (sregs.bptnum < BPT_MAX) {
499 sregs.bpts[sregs.bptnum] = addr & ~0x3;
502 (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
509 sim_remove_breakpoint(int addr)
513 while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
515 if (addr == sregs.bpts[i]) {
516 for (; i < sregs.bptnum - 1; i++)
517 sregs.bpts[i] = sregs.bpts[i + 1];
520 (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);