forked from Imagelibrary/binutils-gdb
Initial creation of sourceware repository
This commit is contained in:
526
sim/erc32/interf.c
Normal file
526
sim/erc32/interf.c
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user