X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Ferc32%2Finterf.c;h=89f747fd6e44dc0cfa91fd8141d36eafd640669a;hb=50838d1be72ddd30e0b5f081933482424ae5a6b0;hp=e81fbf3a7a5f542582ca94d22b7b7f998b76d350;hpb=f4d2ff34bef1789eef9bed93572993ee023270e2;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c index e81fbf3a7a..89f747fd6e 100644 --- a/sim/erc32/interf.c +++ b/sim/erc32/interf.c @@ -1,39 +1,37 @@ -/* - * This file is part of SIS. - * - * SIS, SPARC instruction simulator V1.6 Copyright (C) 1995 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 2 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, write to the Free Software Foundation, Inc., 675 - * Mass Ave, Cambridge, MA 02139, USA. - * - */ +/* This file is part of SIS (SPARC instruction simulator) + Copyright (C) 1995-2020 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 . */ + +#include "config.h" #include #include #include +#include +#include #include "sis.h" +#include "libiberty.h" #include "bfd.h" #include +#include "sim-config.h" -#ifndef fprintf -extern fprintf(); -#endif - -#define VAL(x) strtol(x,(char *)NULL,0) +#include "gdb/remote-sim.h" +#include "gdb/signals.h" -extern char **buildargv(char *input); +#define PSR_CWP 0x7 extern struct disassemble_info dinfo; extern struct pstate sregs; @@ -41,273 +39,346 @@ 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 char uart_dev1[], uart_dev2[]; +extern int sparclite; +extern int dumbio; +extern int sparclite_board; +extern int termsave; +extern char uart_dev1[], uart_dev2[]; int sis_gdb_break = 1; -#ifdef IUREV0 -extern int iurev0; -#endif +host_callback *sim_callback; -#ifdef MECREV0 -extern int mecrev0; -#endif - -run_sim(sregs, go, icount, dis) +int +run_sim(sregs, icount, dis) struct pstate *sregs; - int go; - unsigned int icount; + uint64 icount; int dis; { - int mexc, ws; + int mexc, irq; if (sis_verbose) - printf_filtered("resuming at %x\n", sregs->pc); - sregs->starttime = time(NULL); - while ((!sregs->err_mode & (go || (icount > 0))) && - ((sregs->bptnum == 0) || !(sregs->bphit = check_bpt(sregs)))) { + (*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 = 0; - - check_interrupts(sregs); - if (sregs->trap) { - sregs->err_mode = execute_trap(sregs); - } else { - if (sregs->psr & 0x080) - sregs->asi = 8; - else - sregs->asi = 9; -#ifdef IUREV0 - if (iurev0 && sregs->rett_err) { - sregs->asi &= ~0x1; - sregs->asi |= ((sregs->psr & 0x040) >> 6); - } -#endif + sregs->icnt = 1; - mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst, &sregs->hold); - if (sregs->annul) { - sregs->annul = 0; - sregs->icnt = 1; - sregs->pc = sregs->npc; - sregs->npc = sregs->npc + 4; - } else { + 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 (sregs->histlen) { - sregs->histbuf[sregs->histind].addr = sregs->pc; - sregs->histbuf[sregs->histind].time = ebase.simtime; - sregs->histind++; - if (sregs->histind >= sregs->histlen) - sregs->histind = 0; - } - if (dis) { - printf(" %8d ", ebase.simtime); - dis_mem(sregs->pc, 1, &dinfo); - } if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) { if (sis_verbose) - printf_filtered("SW BP hit at %x\n", sregs->pc); - return (BPT_HIT); + (*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) { - go = icount = 0; + icount = 0; } } - sregs->tottime += time(NULL) - sregs->starttime; + 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); + return ERROR; if (sregs->bphit) { if (sis_verbose) - printf_filtered("HW BP hit at %x\n", sregs->pc); - return (BPT_HIT); + (*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 CTRL_C; } - return (TIME_OUT); + return TIME_OUT; } - -void -sim_open(char *args) +SIM_DESC +sim_open (kind, callback, abfd, argv) + SIM_OPEN_KIND kind; + struct host_callback_struct *callback; + struct bfd *abfd; + char * const *argv; { int argc = 0; - char **argv; - int cont = 1; - int stat = 0; - int grdl = 0; - int freq = 15; - - printf_filtered("\n SIS - SPARC instruction simulator %s\n", sis_version); - printf_filtered(" Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n"); - argv = buildargv(args); - if (argv != NULL) - while (argv[argc]) - argc++; + 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 = 1; - } -#ifdef IUREV0 - if (strcmp(argv[stat], "-iurev0") == 0) { - iurev0 = 1; - printf_filtered(" simulating IU rev.0 jmpl/restore bug\n"); - } -#endif -#ifdef MECREV0 - if (strcmp(argv[stat], "-mecrev0") == 0) { - mecrev0 = 1; - printf_filtered(" simulating MEC rev.0 timer and uart interrupt bug\n"); - } -#endif + sis_verbose++; + } else if (strcmp(argv[stat], "-nfp") == 0) { - printf_filtered("no FPU\n"); nfp = 1; - } - if (strcmp(argv[stat], "-uart1") == 0) { - if ((stat + 1) < argc) - strcpy(uart_dev1, argv[++stat]); - } - if (strcmp(argv[stat], "-uart2") == 0) { - if ((stat + 1) < argc) - strcpy(uart_dev2, argv[++stat]); - } + } 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) { - printf_filtered("disabling GDB trap handling for breakpoints\n"); sis_gdb_break = 0; - } - if (strcmp(argv[stat], "-freq") == 0) + } else + if (strcmp(argv[stat], "-freq") == 0) { if ((stat + 1) < argc) { - freq = VAL(argv[++stat]); - printf_filtered(" ERC32 freq %d Mhz\n", freq); + 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++; } - freeargv(argv); - sregs.freq = freq; - INIT_DISASSEMBLE_INFO(dinfo, stdout, fprintf); - init_signals(); + 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; + termsave = fcntl(0, F_GETFL, 0); + INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf); +#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(int quitting) +sim_close(sd, quitting) + SIM_DESC sd; + int quitting; { exit_sim(); + fcntl(0, F_SETFL, termsave); }; -int -sim_load(char *prog, int from_tty) +SIM_RC +sim_load(sd, prog, abfd, from_tty) + SIM_DESC sd; + const char *prog; + bfd *abfd; + int from_tty; { - bfd_load(*prog); - return (0); + bfd_load (prog); + return SIM_RC_OK; } -void -sim_create_inferior(int start_address, char **argv, char **env) +SIM_RC +sim_create_inferior(sd, abfd, argv, env) + SIM_DESC sd; + struct 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; } -void -sim_store_register(regno, value) +int +sim_store_register(sd, regno, value, length) + SIM_DESC sd; int regno; unsigned char *value; + int length; { - /* FIXME: Review the computation of regval. */ - int regval = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]; + int regval; + + regval = (value[0] << 24) | (value[1] << 16) + | (value[2] << 8) | value[3]; set_regi(&sregs, regno, regval); + return length; } -void -sim_fetch_register(regno, buf) +int +sim_fetch_register(sd, regno, buf, length) + SIM_DESC sd; int regno; unsigned char *buf; + int length; { get_regi(&sregs, regno, buf); + return -1; } int -sim_write(mem, buf, length) - int mem; - unsigned char *buf; - int length; +sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length) { - return (sis_memory_write(mem, buf, length)); + int i, len; + + for (i = 0; i < length; i++) { + sis_memory_write ((mem + i) ^ EBT, &buf[i], 1); + } + return length; } int -sim_read(int mem, unsigned char *buf, int length) +sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) { - return (sis_memory_read(mem, buf, length)); + int i, len; + + for (i = 0; i < length; i++) { + sis_memory_read ((mem + i) ^ EBT, &buf[i], 1); + } + return length; } void -sim_info(int verbose) +sim_info(sd, verbose) + SIM_DESC sd; + int verbose; { show_stat(&sregs); - - } int simstat = OK; -enum sim_stop { - sim_exited, sim_stopped, sim_signalled -}; - void -sim_stop_reason(enum sim_stop * reason, int *sigrc) +sim_stop_reason(sd, reason, sigrc) + SIM_DESC sd; + enum sim_stop * reason; + int *sigrc; { switch (simstat) { case CTRL_C: *reason = sim_stopped; - *sigrc = SIGINT; + *sigrc = GDB_SIGNAL_INT; break; case OK: case TIME_OUT: case BPT_HIT: *reason = sim_stopped; - *sigrc = SIGTRAP; + *sigrc = GDB_SIGNAL_TRAP; break; case ERROR: *sigrc = 0; @@ -317,28 +388,84 @@ sim_stop_reason(enum sim_stop * reason, int *sigrc) simstat = OK; } - -void -sim_resume(int step, int siggnal) +/* 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 () { - simstat = run_sim(&sregs, 1, 0, 0); + 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 sp; + int i; + + sp = sregs.r[(win * 16 + 14) & 0x7f]; +#if 1 + if (sis_verbose > 2) { + uint32 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_kill(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(cmd) - char *cmd; +sim_do_command(sd, cmd) + 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; +} +#if 0 /* FIXME: These shouldn't exist. */ int sim_insert_breakpoint(int addr) @@ -347,7 +474,7 @@ sim_insert_breakpoint(int addr) sregs.bpts[sregs.bptnum] = addr & ~0x3; sregs.bptnum++; if (sis_verbose) - printf_filtered("inserted HW BP at %x\n", addr); + (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr); return 0; } else return 1; @@ -365,8 +492,10 @@ sim_remove_breakpoint(int addr) sregs.bpts[i] = sregs.bpts[i + 1]; sregs.bptnum -= 1; if (sis_verbose) - printf_filtered("removed HW BP at %x\n", addr); + (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr); return 0; } return 1; } + +#endif