123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- /* This file is part of SIS (SPARC instruction simulator)
- Copyright (C) 1995-2022 Free Software Foundation, Inc.
- Contributed by Jiri Gaisler, European Space Agency
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- /* This must come before any other includes. */
- #include "defs.h"
- #include <signal.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/fcntl.h>
- #include "sis.h"
- #include "libiberty.h"
- #include "bfd.h"
- #include <dis-asm.h>
- #include "sim-config.h"
- #include "sim/sim.h"
- #include "gdb/signals.h"
- #define PSR_CWP 0x7
- extern struct disassemble_info dinfo;
- extern struct pstate sregs;
- extern struct estate ebase;
- extern int ctrl_c;
- extern int nfp;
- extern int ift;
- extern int rom8;
- extern int wrp;
- extern int uben;
- extern int sis_verbose;
- extern char *sis_version;
- extern struct estate ebase;
- extern struct evcell evbuf[];
- extern struct irqcell irqarr[];
- extern int irqpend, ext_irl;
- extern int sparclite;
- extern int dumbio;
- extern int sparclite_board;
- extern int termsave;
- extern char uart_dev1[], uart_dev2[];
- int sis_gdb_break = 1;
- host_callback *sim_callback;
- int
- run_sim(struct pstate *sregs, uint64_t icount, int dis)
- {
- int mexc, irq;
- if (sis_verbose)
- (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
- sregs->pc);
- init_stdio();
- sregs->starttime = get_time();
- irq = 0;
- if ((sregs->pc != 0) && (ebase.simtime == 0))
- boot_init();
- while (!sregs->err_mode & (icount > 0)) {
- sregs->fhold = 0;
- sregs->hold = 0;
- sregs->icnt = 1;
- if (sregs->psr & 0x080)
- sregs->asi = 8;
- else
- sregs->asi = 9;
- #if 0 /* DELETE ME! for debugging purposes only */
- if (sis_verbose > 1)
- if (sregs->pc == 0 || sregs->npc == 0)
- printf ("bogus pc or npc\n");
- #endif
- mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
- #if 0 /* DELETE ME! for debugging purposes only */
- if (sis_verbose > 2)
- printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
- sregs->pc, sregs->npc,
- sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
- sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
- sregs->wim,
- sregs->psr & 7,
- sregs->inst);
- #endif
- if (sregs->annul) {
- sregs->annul = 0;
- sregs->icnt = 1;
- sregs->pc = sregs->npc;
- sregs->npc = sregs->npc + 4;
- } else {
- if (ext_irl) irq = check_interrupts(sregs);
- if (!irq) {
- if (mexc) {
- sregs->trap = I_ACC_EXC;
- } else {
- if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
- if (sis_verbose)
- (*sim_callback->printf_filtered) (sim_callback,
- "SW BP hit at %x\n", sregs->pc);
- sim_halt();
- restore_stdio();
- clearerr(stdin);
- return BPT_HIT;
- } else
- dispatch_instruction(sregs);
- }
- icount--;
- }
- if (sregs->trap) {
- irq = 0;
- sregs->err_mode = execute_trap(sregs);
- }
- }
- advance_time(sregs);
- if (ctrl_c) {
- icount = 0;
- }
- }
- sim_halt();
- sregs->tottime += get_time() - sregs->starttime;
- restore_stdio();
- clearerr(stdin);
- if (sregs->err_mode)
- error_mode(sregs->pc);
- if (sregs->err_mode)
- return ERROR;
- if (sregs->bphit) {
- if (sis_verbose)
- (*sim_callback->printf_filtered) (sim_callback,
- "HW BP hit at %x\n", sregs->pc);
- return BPT_HIT;
- }
- if (ctrl_c) {
- ctrl_c = 0;
- return CTRL_C;
- }
- return TIME_OUT;
- }
- SIM_DESC
- sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback,
- struct bfd *abfd, char * const *argv)
- {
- int argc = 0;
- int stat = 1;
- int freq = 0;
- sim_callback = callback;
- argc = countargv (argv);
- while (stat < argc) {
- if (argv[stat][0] == '-') {
- if (strcmp(argv[stat], "-v") == 0) {
- sis_verbose++;
- } else
- if (strcmp(argv[stat], "-nfp") == 0) {
- nfp = 1;
- } else
- if (strcmp(argv[stat], "-ift") == 0) {
- ift = 1;
- } else
- if (strcmp(argv[stat], "-sparclite") == 0) {
- sparclite = 1;
- } else
- if (strcmp(argv[stat], "-sparclite-board") == 0) {
- sparclite_board = 1;
- } else
- if (strcmp(argv[stat], "-dumbio") == 0) {
- dumbio = 1;
- } else
- if (strcmp(argv[stat], "-wrp") == 0) {
- wrp = 1;
- } else
- if (strcmp(argv[stat], "-rom8") == 0) {
- rom8 = 1;
- } else
- if (strcmp(argv[stat], "-uben") == 0) {
- uben = 1;
- } else
- if (strcmp(argv[stat], "-uart1") == 0) {
- if ((stat + 1) < argc)
- strcpy(uart_dev1, argv[++stat]);
- } else
- if (strcmp(argv[stat], "-uart2") == 0) {
- if ((stat + 1) < argc)
- strcpy(uart_dev2, argv[++stat]);
- } else
- if (strcmp(argv[stat], "-nogdb") == 0) {
- sis_gdb_break = 0;
- } else
- if (strcmp(argv[stat], "-freq") == 0) {
- if ((stat + 1) < argc) {
- freq = strtol(argv[++stat], (char **)NULL, 0);
- }
- } else
- if (strncmp(argv[stat], "--sysroot=", sizeof("--sysroot=") - 1) == 0) {
- /* Ignore until we start to support this. */
- } else {
- (*sim_callback->printf_filtered) (sim_callback,
- "unknown option %s\n",
- argv[stat]);
- }
- } else
- bfd_load(argv[stat]);
- stat++;
- }
- if (sis_verbose) {
- (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
- (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
- if (nfp)
- (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
- if (sparclite)
- (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
- if (dumbio)
- (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
- if (sis_gdb_break == 0)
- (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
- if (freq)
- (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
- }
- sregs.freq = freq ? freq : 15;
- #ifdef F_GETFL
- termsave = fcntl(0, F_GETFL, 0);
- #endif
- INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf,
- fprintf_styled);
- #ifdef HOST_LITTLE_ENDIAN
- dinfo.endian = BFD_ENDIAN_LITTLE;
- #else
- dinfo.endian = BFD_ENDIAN_BIG;
- #endif
- reset_all();
- ebase.simtime = 0;
- init_sim();
- init_bpt(&sregs);
- reset_stat(&sregs);
- /* Fudge our descriptor for now. */
- return (SIM_DESC) 1;
- }
- void
- sim_close(SIM_DESC sd, int quitting)
- {
- exit_sim();
- #ifdef F_SETFL
- fcntl(0, F_SETFL, termsave);
- #endif
- }
- SIM_RC
- sim_load(SIM_DESC sd, const char *prog, bfd *abfd, int from_tty)
- {
- bfd_load (prog);
- return SIM_RC_OK;
- }
- SIM_RC
- sim_create_inferior(SIM_DESC sd, bfd *abfd, char * const *argv,
- char * const *env)
- {
- bfd_vma start_address = 0;
- if (abfd != NULL)
- start_address = bfd_get_start_address (abfd);
- ebase.simtime = 0;
- reset_all();
- reset_stat(&sregs);
- sregs.pc = start_address & ~3;
- sregs.npc = sregs.pc + 4;
- return SIM_RC_OK;
- }
- int
- sim_store_register(SIM_DESC sd, int regno, unsigned char *value, int length)
- {
- int regval;
- regval = (value[0] << 24) | (value[1] << 16)
- | (value[2] << 8) | value[3];
- set_regi(&sregs, regno, regval);
- return length;
- }
- int
- sim_fetch_register(SIM_DESC sd, int regno, unsigned char *buf, int length)
- {
- get_regi(&sregs, regno, buf);
- return -1;
- }
- int
- sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
- {
- int i, len;
- for (i = 0; i < length; i++) {
- sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
- }
- return length;
- }
- int
- sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
- {
- int i, len;
- for (i = 0; i < length; i++) {
- sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
- }
- return length;
- }
- void
- sim_info(SIM_DESC sd, int verbose)
- {
- show_stat(&sregs);
- }
- int simstat = OK;
- void
- sim_stop_reason(SIM_DESC sd, enum sim_stop *reason, int *sigrc)
- {
- switch (simstat) {
- case CTRL_C:
- *reason = sim_stopped;
- *sigrc = GDB_SIGNAL_INT;
- break;
- case OK:
- case TIME_OUT:
- case BPT_HIT:
- *reason = sim_stopped;
- *sigrc = GDB_SIGNAL_TRAP;
- break;
- case ERROR:
- *sigrc = 0;
- *reason = sim_exited;
- }
- ctrl_c = 0;
- simstat = OK;
- }
- /* Flush all register windows out to the stack. Starting after the invalid
- window, flush all windows up to, and including the current window. This
- allows GDB to do backtraces and look at local variables for frames that
- are still in the register windows. Note that strictly speaking, this
- behavior is *wrong* for several reasons. First, it doesn't use the window
- overflow handlers. It therefore assumes standard frame layouts and window
- handling policies. Second, it changes system state behind the back of the
- target program. I expect this to mainly pose problems when debugging trap
- handlers.
- */
- static void
- flush_windows (void)
- {
- int invwin;
- int cwp;
- int win;
- int ws;
- /* Keep current window handy */
- cwp = sregs.psr & PSR_CWP;
- /* Calculate the invalid window from the wim. */
- for (invwin = 0; invwin <= PSR_CWP; invwin++)
- if ((sregs.wim >> invwin) & 1)
- break;
- /* Start saving with the window after the invalid window. */
- invwin = (invwin - 1) & PSR_CWP;
- for (win = invwin; ; win = (win - 1) & PSR_CWP)
- {
- uint32_t sp;
- int i;
- sp = sregs.r[(win * 16 + 14) & 0x7f];
- #if 1
- if (sis_verbose > 2) {
- uint32_t fp = sregs.r[(win * 16 + 30) & 0x7f];
- printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
- }
- #endif
- for (i = 0; i < 16; i++)
- memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
- &ws);
- if (win == cwp)
- break;
- }
- }
- void
- sim_resume(SIM_DESC sd, int step, int siggnal)
- {
- simstat = run_sim(&sregs, UINT64_MAX, 0);
- if (sis_gdb_break) flush_windows ();
- }
- void
- sim_do_command(SIM_DESC sd, const char *cmd)
- {
- exec_cmd(&sregs, cmd);
- }
- char **
- sim_complete_command (SIM_DESC sd, const char *text, const char *word)
- {
- return NULL;
- }
- char *
- sim_memory_map (SIM_DESC sd)
- {
- return NULL;
- }
- #if 0 /* FIXME: These shouldn't exist. */
- int
- sim_insert_breakpoint(int addr)
- {
- if (sregs.bptnum < BPT_MAX) {
- sregs.bpts[sregs.bptnum] = addr & ~0x3;
- sregs.bptnum++;
- if (sis_verbose)
- (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
- return 0;
- } else
- return 1;
- }
- int
- sim_remove_breakpoint(int addr)
- {
- int i = 0;
- while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
- i++;
- if (addr == sregs.bpts[i]) {
- for (; i < sregs.bptnum - 1; i++)
- sregs.bpts[i] = sregs.bpts[i + 1];
- sregs.bptnum -= 1;
- if (sis_verbose)
- (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
- return 0;
- }
- return 1;
- }
- #endif
|