diff options
Diffstat (limited to 'sim/erc32/interf.c')
-rw-r--r-- | sim/erc32/interf.c | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c new file mode 100644 index 0000000..d0a781e --- /dev/null +++ b/sim/erc32/interf.c @@ -0,0 +1,526 @@ +/* + * 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. + * + */ + +#include <signal.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/fcntl.h> +#include "sis.h" +#include "bfd.h" +#include <dis-asm.h> +#include "sim-config.h" + +#include "remote-sim.h" + +#ifndef fprintf +extern fprintf(); +#endif + +#define PSR_CWP 0x7 + +#define VAL(x) strtol(x,(char **)NULL,0) + +extern char **buildargv(char *input); + +extern struct disassemble_info dinfo; +extern struct pstate sregs; +extern struct estate ebase; + +extern int current_target_byte_order; +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(sregs, icount, dis) + struct pstate *sregs; + unsigned int 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 = time(NULL); + irq = 0; + 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_read(sregs->asi, sregs->pc, &sregs->inst, + 2, &sregs->hold); +#if 1 /* 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 += time(NULL) - 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); +} + +void +sim_set_callbacks (ptr) + host_callback *ptr; +{ + sim_callback = ptr; +} + +void +sim_size (memsize) + int memsize; +{ +} + +SIM_DESC +sim_open (kind, callback, abfd, argv) + SIM_OPEN_KIND kind; + struct host_callback_struct *callback; + struct _bfd *abfd; + char **argv; +{ + + int argc = 0; + int stat = 1; + int freq = 0; + + sim_callback = callback; + + while (argv[argc]) + argc++; + 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 = VAL(argv[++stat]); + } + } 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; + termsave = fcntl(0, F_GETFL, 0); + INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf); + dinfo.endian = BFD_ENDIAN_BIG; + 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(sd, quitting) + SIM_DESC sd; + int quitting; +{ + + exit_sim(); + fcntl(0, F_SETFL, termsave); + +}; + +SIM_RC +sim_load(sd, prog, abfd, from_tty) + SIM_DESC sd; + char *prog; + bfd *abfd; + int from_tty; +{ + bfd_load (prog); + return SIM_RC_OK; +} + +SIM_RC +sim_create_inferior(sd, abfd, argv, env) + SIM_DESC sd; + struct _bfd *abfd; + char **argv; + char **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(sd, regno, value, length) + SIM_DESC sd; + int regno; + unsigned char *value; + int length; +{ + /* FIXME: Review the computation of regval. */ + int regval; + if (current_target_byte_order == BIG_ENDIAN) + regval = (value[0] << 24) | (value[1] << 16) + | (value[2] << 8) | value[3]; + else + regval = (value[3] << 24) | (value[2] << 16) + | (value[1] << 8) | value[0]; + set_regi(&sregs, regno, regval); + return -1; +} + + +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(sd, mem, buf, length) + SIM_DESC sd; + SIM_ADDR mem; + unsigned char *buf; + int length; +{ + return (sis_memory_write(mem, buf, length)); +} + +int +sim_read(sd, mem, buf, length) + SIM_DESC sd; + SIM_ADDR mem; + unsigned char *buf; + int length; +{ + return (sis_memory_read(mem, buf, length)); +} + +void +sim_info(sd, verbose) + SIM_DESC sd; + int verbose; +{ + show_stat(&sregs); +} + +int simstat = OK; + +void +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; + break; + case OK: + case TIME_OUT: + case BPT_HIT: + *reason = sim_stopped; +#ifdef _WIN32 +#define SIGTRAP 5 +#endif + *sigrc = SIGTRAP; + 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 () +{ + 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_resume(SIM_DESC sd, int step, int siggnal) +{ + simstat = run_sim(&sregs, -1, 0); + + if (sis_gdb_break) flush_windows (); +} + +int +sim_trace (sd) + SIM_DESC sd; +{ + /* FIXME: unfinished */ + sim_resume (sd, 0, 0); + return 1; +} + +void +sim_do_command(sd, cmd) + SIM_DESC sd; + char *cmd; +{ + exec_cmd(&sregs, cmd); +} + +#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 |