#if 1
#define TRACE (1)
#endif
#include "bfd.h"
#include "sim-main.h"
#include "sim-utils.h"
#include "sim-options.h"
#include "sim-assert.h"
#include "sim-hw.h"
#include "itable.h"
#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include <ansidecl.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include "getopt.h"
#include "libiberty.h"
#include "bfd.h"
#include "gdb/callback.h"
#include "gdb/remote-sim.h"
#include "sysdep.h"
#ifndef PARAMS
#define PARAMS(x)
#endif
char* pr_addr PARAMS ((SIM_ADDR addr));
char* pr_uword64 PARAMS ((uword64 addr));
#define CPU cpu
#define SD sd
#define RSVD_INSTRUCTION (0x00000005)
#define RSVD_INSTRUCTION_MASK (0xFC00003F)
#define RSVD_INSTRUCTION_ARG_SHIFT 6
#define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
#define Debug_DBD 0x80000000
#define Debug_DM 0x40000000
#define Debug_DBp 0x00000002
static void ColdReset PARAMS((SIM_DESC sd));
#define DELAYSLOT() {\
if (STATE & simDELAYSLOT)\
sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
STATE |= simDELAYSLOT;\
}
#define JALDELAYSLOT() {\
DELAYSLOT ();\
STATE |= simJALDELAYSLOT;\
}
#define NULLIFY() {\
STATE &= ~simDELAYSLOT;\
STATE |= simSKIPNEXT;\
}
#define CANCELDELAYSLOT() {\
DSSTATE = 0;\
STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
}
#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
#define K0BASE (0x80000000)
#define K0SIZE (0x20000000)
#define K1BASE (0xA0000000)
#define K1SIZE (0x20000000)
static int firmware_option_p = 0;
static SIM_ADDR idt_monitor_base = 0xBFC00000;
static SIM_ADDR pmon_monitor_base = 0xBFC00500;
static SIM_ADDR lsipmon_monitor_base = 0xBFC00200;
static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg);
#define MEM_SIZE (2 << 20)
#if defined(TRACE)
static char *tracefile = "trace.din";
FILE *tracefh = NULL;
static void open_trace PARAMS((SIM_DESC sd));
#endif
static const char * get_insn_name (sim_cpu *, int);
static char* board = NULL;
static DECLARE_OPTION_HANDLER (mips_option_handler);
enum {
OPTION_DINERO_TRACE = OPTION_START,
OPTION_DINERO_FILE,
OPTION_FIRMWARE,
OPTION_BOARD
};
static SIM_RC
mips_option_handler (sd, cpu, opt, arg, is_command)
SIM_DESC sd;
sim_cpu *cpu;
int opt;
char *arg;
int is_command;
{
int cpu_nr;
switch (opt)
{
case OPTION_DINERO_TRACE:
#if defined(TRACE)
for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
{
sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
if (arg == NULL)
STATE |= simTRACE;
else if (strcmp (arg, "yes") == 0)
STATE |= simTRACE;
else if (strcmp (arg, "no") == 0)
STATE &= ~simTRACE;
else if (strcmp (arg, "on") == 0)
STATE |= simTRACE;
else if (strcmp (arg, "off") == 0)
STATE &= ~simTRACE;
else
{
fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg);
return SIM_RC_FAIL;
}
}
return SIM_RC_OK;
#else
fprintf(stderr,"\
Simulator constructed without dinero tracing support (for performance).\n\
Re-compile simulator with \"-DTRACE\" to enable this option.\n");
return SIM_RC_FAIL;
#endif
case OPTION_DINERO_FILE:
#if defined(TRACE)
if (optarg != NULL) {
char *tmp;
tmp = (char *)malloc(strlen(optarg) + 1);
if (tmp == NULL)
{
sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg);
return SIM_RC_FAIL;
}
else {
strcpy(tmp,optarg);
tracefile = tmp;
sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile);
}
}
#endif
return SIM_RC_OK;
case OPTION_FIRMWARE:
return sim_firmware_command (sd, arg);
case OPTION_BOARD:
{
if (arg)
{
board = zalloc(strlen(arg) + 1);
strcpy(board, arg);
}
return SIM_RC_OK;
}
}
return SIM_RC_OK;
}
static const OPTION mips_options[] =
{
{ {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE},
'\0', "on|off", "Enable dinero tracing",
mips_option_handler },
{ {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
'\0', "FILE", "Write dinero trace to FILE",
mips_option_handler },
{ {"firmware", required_argument, NULL, OPTION_FIRMWARE},
'\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor",
mips_option_handler },
{ {"board", required_argument, NULL, OPTION_BOARD},
'\0', "none"
#define BOARD_JMR3904 "jmr3904"
"|" BOARD_JMR3904
#define BOARD_JMR3904_PAL "jmr3904pal"
"|" BOARD_JMR3904_PAL
#define BOARD_JMR3904_DEBUG "jmr3904debug"
"|" BOARD_JMR3904_DEBUG
#define BOARD_BSP "bsp"
"|" BOARD_BSP
, "Customize simulation for a particular board.", mips_option_handler },
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
};
int interrupt_pending;
void
interrupt_event (SIM_DESC sd, void *data)
{
sim_cpu *cpu = STATE_CPU (sd, 0);
address_word cia = CIA_GET (cpu);
if (SR & status_IE)
{
interrupt_pending = 0;
SignalExceptionInterrupt (1);
}
else if (!interrupt_pending)
sim_events_schedule (sd, 1, interrupt_event, data);
}
static void device_init(SIM_DESC sd) {
#ifdef DEVICE_INIT
extern void register_devices(SIM_DESC);
register_devices(sd);
#endif
}
SIM_DESC
sim_open (kind, cb, abfd, argv)
SIM_OPEN_KIND kind;
host_callback *cb;
struct _bfd *abfd;
char **argv;
{
SIM_DESC sd = sim_state_alloc (kind, cb);
sim_cpu *cpu = STATE_CPU (sd, 0);
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
STATE_WATCHPOINTS (sd)->pc = &(PC);
STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
CPU_INSN_NAME (cpu) = get_insn_name;
CPU_MAX_INSNS (cpu) = nr_itable_entries;
STATE = 0;
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
return 0;
sim_add_option_table (sd, NULL, mips_options);
if (sim_parse_args (sd, argv) != SIM_RC_OK)
{
sim_module_uninstall (sd);
return 0;
}
if (board == NULL)
{
sim_do_command(sd," memory region 0x7fff8000,0x8000") ;
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
K1BASE, K0SIZE,
MEM_SIZE,
K0BASE);
device_init(sd);
}
else if (board != NULL
&& (strcmp(board, BOARD_BSP) == 0))
{
int i;
STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
0x9FC00000,
4 * 1024 * 1024,
0xBFC00000);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
0x80000000,
4 * 1024 * 1024,
0xA0000000);
for (i=0; i<8; i++)
{
unsigned size = 4 * 1024 * 1024;
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
0x88000000 + (i * size),
size,
0xA8000000 + (i * size));
}
}
#if (WITH_HW)
else if (board != NULL
&& (strcmp(board, BOARD_JMR3904) == 0 ||
strcmp(board, BOARD_JMR3904_PAL) == 0 ||
strcmp(board, BOARD_JMR3904_DEBUG) == 0))
{
int i;
if (! firmware_option_p)
{
idt_monitor_base = 0;
pmon_monitor_base = 0;
lsipmon_monitor_base = 0;
}
STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
0x9FC00000,
4 * 1024 * 1024,
0xBFC00000);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
0x80000000,
4 * 1024 * 1024,
0xA0000000);
for (i=0; i<8; i++)
{
unsigned size = 4 * 1024 * 1024;
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
0x88000000 + (i * size),
size,
0xA8000000 + (i * size));
}
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB1000000, 0x400);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2100000, 0x004);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2500000, 0x004);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2700000, 0x004);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB3C00000, 0x004);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF8000, 0x900);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFE000, 0x01c);
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300);
sim_hw_parse (sd, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20");
sim_hw_parse (sd, "/tx3904cpu");
sim_hw_parse (sd, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100");
sim_hw_parse (sd, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100");
sim_hw_parse (sd, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100");
sim_hw_parse (sd, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100");
{
extern char* sockser_addr;
if(sockser_addr == NULL)
sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio");
else
sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp");
}
sim_hw_parse (sd, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100");
sim_hw_parse (sd, "/tx3904sio@0xfffff400/backend stdio");
sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu");
sim_hw_parse (sd, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc");
sim_hw_parse (sd, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc");
sim_hw_parse (sd, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc");
sim_hw_parse (sd, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc");
sim_hw_parse (sd, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc");
if(! strcmp(board, BOARD_JMR3904_PAL))
{
sim_hw_parse (sd, "/pal@0xffff0000");
sim_hw_parse (sd, "/pal@0xffff0000/reg 0xffff0000 64");
sim_hw_parse (sd, "/pal@0x31000000 > countdown tmr0 /tx3904irc");
sim_hw_parse (sd, "/pal@0x31000000 > timer tmr1 /tx3904irc");
sim_hw_parse (sd, "/pal@0x31000000 > int int0 /tx3904irc");
}
if(! strcmp(board, BOARD_JMR3904_DEBUG))
{
sim_hw_parse (sd, "/glue@0xffff0000/reg 0xffff0000 0x50");
sim_hw_parse (sd, "/glue@0xffff0000 > int0 int0 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int1 int1 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int2 int2 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int3 int3 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int4 int4 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int5 int5 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int6 int6 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int7 int7 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
sim_hw_parse (sd, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
}
device_init(sd);
}
#endif
if (sim_analyze_program (sd,
(STATE_PROG_ARGV (sd) != NULL
? *STATE_PROG_ARGV (sd)
: NULL),
abfd) != SIM_RC_OK)
{
sim_module_uninstall (sd);
return 0;
}
if (sim_config (sd) != SIM_RC_OK)
{
sim_module_uninstall (sd);
return 0;
}
if (sim_post_argv_init (sd) != SIM_RC_OK)
{
sim_module_uninstall (sd);
return 0;
}
SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
SIM_ASSERT (sizeof(word64) == (8 * sizeof(char)));
{
int rn;
for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++)
{
if (rn < 32)
cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
else if ((rn >= FGR_BASE) && (rn < (FGR_BASE + NR_FGR)))
cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE;
else if ((rn >= 33) && (rn <= 37))
cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
else if ((rn == SRIDX)
|| (rn == FCR0IDX)
|| (rn == FCR31IDX)
|| ((rn >= 72) && (rn <= 89)))
cpu->register_widths[rn] = 32;
else
cpu->register_widths[rn] = 0;
}
}
#if defined(TRACE)
if (STATE & simTRACE)
open_trace(sd);
#endif
if (idt_monitor_base != 0)
{
unsigned loop;
unsigned idt_monitor_size = 1 << 11;
sim_do_commandf (sd, "memory region 0x%x,0x%x",
idt_monitor_base, idt_monitor_size);
for (loop = 0; (loop < idt_monitor_size); loop += 4)
{
address_word vaddr = (idt_monitor_base + loop);
unsigned32 insn = (RSVD_INSTRUCTION |
(((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK)
<< RSVD_INSTRUCTION_ARG_SHIFT));
H2T (insn);
sim_write (sd, vaddr, (char *)&insn, sizeof (insn));
}
}
if ((pmon_monitor_base != 0) || (lsipmon_monitor_base != 0))
{
unsigned loop;
for (loop = 0; (loop < 24); loop++)
{
unsigned32 value = ((0x500 - 8) / 8);
switch (loop)
{
case 0:
value = 7;
break;
case 1:
value = 8;
break;
case 2:
value = 6;
break;
case 3:
value = 10;
break;
case 5:
value = ((0x500 - 16) / 8);
break;
case 8:
value = 17;
break;
case 11:
value = 28;
break;
}
SIM_ASSERT (idt_monitor_base != 0);
value = ((unsigned int) idt_monitor_base + (value * 8));
H2T (value);
if (pmon_monitor_base != 0)
{
address_word vaddr = (pmon_monitor_base + (loop * 4));
sim_write (sd, vaddr, (char *)&value, sizeof (value));
}
if (lsipmon_monitor_base != 0)
{
address_word vaddr = (lsipmon_monitor_base + (loop * 4));
sim_write (sd, vaddr, (char *)&value, sizeof (value));
}
}
if ((idt_monitor_base != 0) ||
(pmon_monitor_base != 0) ||
(lsipmon_monitor_base != 0))
{
unsigned32 halt[2] = { 0x2404002f ,
HALT_INSTRUCTION };
H2T (halt[0]);
H2T (halt[1]);
sim_write (sd, 0x80000000, (char *) halt, sizeof (halt));
sim_write (sd, 0x80000180, (char *) halt, sizeof (halt));
sim_write (sd, 0x80000200, (char *) halt, sizeof (halt));
sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt));
sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt));
sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt));
}
}
return sd;
}
#if defined(TRACE)
static void
open_trace(sd)
SIM_DESC sd;
{
tracefh = fopen(tracefile,"wb+");
if (tracefh == NULL)
{
sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile);
tracefh = stderr;
}
}
#endif
static const char *
get_insn_name (sim_cpu *cpu, int i)
{
return itable[i].name;
}
void
sim_close (sd, quitting)
SIM_DESC sd;
int quitting;
{
#ifdef DEBUG
printf("DBG: sim_close: entered (quitting = %d)\n",quitting);
#endif
sim_module_uninstall (sd);
sim_io_shutdown (sd);
#if defined(TRACE)
if (tracefh != NULL && tracefh != stderr)
fclose(tracefh);
tracefh = NULL;
#endif
return;
}
int
sim_write (sd,addr,buffer,size)
SIM_DESC sd;
SIM_ADDR addr;
unsigned char *buffer;
int size;
{
int index;
sim_cpu *cpu = STATE_CPU (sd, 0);
#ifdef DEBUG
sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
#endif
for (index = 0; index < size; index++)
{
address_word vaddr = (address_word)addr + index;
address_word paddr;
int cca;
if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
break;
if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
break;
}
return(index);
}
int
sim_read (sd,addr,buffer,size)
SIM_DESC sd;
SIM_ADDR addr;
unsigned char *buffer;
int size;
{
int index;
sim_cpu *cpu = STATE_CPU (sd, 0);
#ifdef DEBUG
sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
#endif
for (index = 0; (index < size); index++)
{
address_word vaddr = (address_word)addr + index;
address_word paddr;
int cca;
if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
break;
if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
break;
}
return(index);
}
int
sim_store_register (sd,rn,memory,length)
SIM_DESC sd;
int rn;
unsigned char *memory;
int length;
{
sim_cpu *cpu = STATE_CPU (sd, 0);
#ifdef DEBUG
sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory)));
#endif
if (cpu->register_widths[rn] == 0)
{
sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
return 0;
}
if (rn >= FGR_BASE && rn < FGR_BASE + NR_FGR)
{
cpu->fpr_state[rn - FGR_BASE] = fmt_uninterpreted;
if (cpu->register_widths[rn] == 32)
{
if (length == 8)
{
cpu->fgr[rn - FGR_BASE] =
(unsigned32) T2H_8 (*(unsigned64*)memory);
return 8;
}
else
{
cpu->fgr[rn - FGR_BASE] = T2H_4 (*(unsigned32*)memory);
return 4;
}
}
else
{
cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory);
return 8;
}
}
if (cpu->register_widths[rn] == 32)
{
if (length == 8)
{
cpu->registers[rn] =
(unsigned32) T2H_8 (*(unsigned64*)memory);
return 8;
}
else
{
cpu->registers[rn] = T2H_4 (*(unsigned32*)memory);
return 4;
}
}
else
{
cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
return 8;
}
return 0;
}
int
sim_fetch_register (sd,rn,memory,length)
SIM_DESC sd;
int rn;
unsigned char *memory;
int length;
{
sim_cpu *cpu = STATE_CPU (sd, 0);
#ifdef DEBUG
#if 0
sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
#endif
#endif
if (cpu->register_widths[rn] == 0)
{
sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn);
return 0;
}
if (rn >= FGR_BASE && rn < FGR_BASE + NR_FGR)
{
if (cpu->register_widths[rn] == 32)
{
if (length == 8)
{
*(unsigned64*)memory =
H2T_8 ((unsigned32) (cpu->fgr[rn - FGR_BASE]));
return 8;
}
else
{
*(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGR_BASE]);
return 4;
}
}
else
{
*(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]);
return 8;
}
}
if (cpu->register_widths[rn] == 32)
{
if (length == 8)
{
*(unsigned64*)memory =
H2T_8 ((unsigned32) (cpu->registers[rn]));
return 8;
}
else
{
*(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
return 4;
}
}
else
{
*(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
return 8;
}
return 0;
}
SIM_RC
sim_create_inferior (sd, abfd, argv,env)
SIM_DESC sd;
struct _bfd *abfd;
char **argv;
char **env;
{
#ifdef DEBUG
#if 0
printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
pr_addr(PC));
#endif
#endif
ColdReset(sd);
if (abfd != NULL)
{
int cpu_nr;
for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
{
sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
CIA_SET (cpu, (unsigned64) bfd_get_start_address (abfd));
}
}
#if 0
if (argv || env)
{
char **cptr;
sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n");
for (cptr = argv; (cptr && *cptr); cptr++)
printf("DBG: arg \"%s\"\n",*cptr);
}
#endif
return SIM_RC_OK;
}
void
sim_do_command (sd,cmd)
SIM_DESC sd;
char *cmd;
{
if (sim_args_command (sd, cmd) != SIM_RC_OK)
sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n",
cmd);
}
static char *
fetch_str (SIM_DESC sd,
address_word addr)
{
char *buf;
int nr = 0;
char null;
while (sim_read (sd, addr + nr, &null, 1) == 1 && null != 0)
nr++;
buf = NZALLOC (char, nr + 1);
sim_read (sd, addr, buf, nr);
return buf;
}
static SIM_RC
sim_firmware_command (SIM_DESC sd, char *arg)
{
int address_present = 0;
SIM_ADDR address;
firmware_option_p = 1;
{
char *p = strchr (arg, '@');
if (p)
{
char *q;
address_present = 1;
p ++;
address = strtoul (p, &q, 0);
if (*q != '\0')
{
sim_io_printf (sd, "Invalid address given to the"
"`sim firmware NAME@ADDRESS' command: %s\n",
p);
return SIM_RC_FAIL;
}
}
else
{
address_present = 0;
address = -1;
}
}
if (! strncmp (arg, "idt", 3))
{
idt_monitor_base = address_present ? address : 0xBFC00000;
pmon_monitor_base = 0;
lsipmon_monitor_base = 0;
}
else if (! strncmp (arg, "pmon", 4))
{
pmon_monitor_base = address_present ? address : 0xBFC00500;
idt_monitor_base = pmon_monitor_base - 0x500;
lsipmon_monitor_base = 0;
}
else if (! strncmp (arg, "lsipmon", 7))
{
pmon_monitor_base = 0;
lsipmon_monitor_base = address_present ? address : 0xBFC00200;
idt_monitor_base = lsipmon_monitor_base - 0x200;
}
else if (! strncmp (arg, "none", 4))
{
if (address_present)
{
sim_io_printf (sd,
"The `sim firmware none' command does "
"not take an `ADDRESS' argument.\n");
return SIM_RC_FAIL;
}
idt_monitor_base = 0;
pmon_monitor_base = 0;
lsipmon_monitor_base = 0;
}
else
{
sim_io_printf (sd, "\
Unrecognized name given to the `sim firmware NAME' command: %s\n\
Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n",
arg);
return SIM_RC_FAIL;
}
return SIM_RC_OK;
}
int
sim_monitor (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
unsigned int reason)
{
#ifdef DEBUG
printf("DBG: sim_monitor: entered (reason = %d)\n",reason);
#endif
reason >>= 1;
switch (reason)
{
case 6:
{
char *path = fetch_str (sd, A0);
V0 = sim_io_open (sd, path, (int)A1);
zfree (path);
break;
}
case 7:
{
int fd = A0;
int nr = A2;
char *buf = zalloc (nr);
V0 = sim_io_read (sd, fd, buf, nr);
sim_write (sd, A1, buf, nr);
zfree (buf);
}
break;
case 8:
{
int fd = A0;
int nr = A2;
char *buf = zalloc (nr);
sim_read (sd, A1, buf, nr);
V0 = sim_io_write (sd, fd, buf, nr);
zfree (buf);
break;
}
case 10:
{
V0 = sim_io_close (sd, (int)A0);
break;
}
case 2:
{
if (A0 == 0)
V0 = (unsigned_word)-1;
}
case 11:
{
char tmp;
sim_io_flush_stdout (sd);
if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char))
{
sim_io_error(sd,"Invalid return from character read");
V0 = (unsigned_word)-1;
}
else
V0 = (unsigned_word)tmp;
break;
}
case 3:
case 12:
{
char tmp = (char)(A0 & 0xFF);
sim_io_write_stdout (sd, &tmp, sizeof(char));
break;
}
case 17:
{
sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n");
sim_engine_halt (SD, CPU, NULL, NULL_CIA, sim_exited,
(unsigned int)(A0 & 0xFFFFFFFF));
break;
}
case 28:
break;
case 55:
{
unsigned_4 value = MEM_SIZE ;
unsigned_4 zero = 0;
H2T (value);
sim_write (sd, A0 + 0, (char *)&value, 4);
sim_write (sd, A0 + 4, (char *)&zero, 4);
sim_write (sd, A0 + 8, (char *)&zero, 4);
break;
}
case 158:
{
address_word s = A0;
char c;
signed_word *ap = &A1;
while (sim_read (sd, s++, &c, 1) && c != '\0')
{
if (c == '%')
{
char tmp[40];
enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
int width = 0, trunc = 0, haddot = 0, longlong = 0;
while (sim_read (sd, s++, &c, 1) && c != '\0')
{
if (strchr ("dobxXulscefg%", c))
break;
else if (c == '-')
fmt = FMT_LJUST;
else if (c == '0')
fmt = FMT_RJUST0;
else if (c == '~')
fmt = FMT_CENTER;
else if (c == '*')
{
if (haddot)
trunc = (int)*ap++;
else
width = (int)*ap++;
}
else if (c >= '1' && c <= '9')
{
address_word t = s;
unsigned int n;
while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c))
tmp[s - t] = c;
tmp[s - t] = '\0';
n = (unsigned int)strtol(tmp,NULL,10);
if (haddot)
trunc = n;
else
width = n;
s--;
}
else if (c == '.')
haddot = 1;
}
switch (c)
{
case '%':
sim_io_printf (sd, "%%");
break;
case 's':
if ((int)*ap != 0)
{
address_word p = *ap++;
char ch;
while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0')
sim_io_printf(sd, "%c", ch);
}
else
sim_io_printf(sd,"(null)");
break;
case 'c':
sim_io_printf (sd, "%c", (int)*ap++);
break;
default:
if (c == 'l')
{
sim_read (sd, s++, &c, 1);
if (c == 'l')
{
longlong = 1;
sim_read (sd, s++, &c, 1);
}
}
if (strchr ("dobxXu", c))
{
word64 lv = (word64) *ap++;
if (c == 'b')
sim_io_printf(sd,"<binary not supported>");
else
{
sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c);
if (longlong)
sim_io_printf(sd, tmp, lv);
else
sim_io_printf(sd, tmp, (int)lv);
}
}
else if (strchr ("eEfgG", c))
{
double dbl = *(double*)(ap++);
sprintf (tmp, "%%%d.%d%c", width, trunc, c);
sim_io_printf (sd, tmp, dbl);
trunc = 0;
}
}
}
else
sim_io_printf(sd, "%c", c);
}
break;
}
default:
return 0;
}
return 1;
}
static void
store_word (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
uword64 vaddr,
signed_word val)
{
address_word paddr;
int uncached;
if ((vaddr & 3) != 0)
SignalExceptionAddressStore ();
else
{
if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
isTARGET, isREAL))
{
const uword64 mask = 7;
uword64 memval;
unsigned int byte;
paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
byte = (vaddr & mask) ^ (BigEndianCPU << 2);
memval = ((uword64) val) << (8 * byte);
StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
isREAL);
}
}
}
static signed_word
load_word (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
uword64 vaddr)
{
if ((vaddr & 3) != 0)
{
SIM_CORE_SIGNAL (SD, cpu, cia, read_map, AccessLength_WORD+1, vaddr, read_transfer, sim_core_unaligned_signal);
}
else
{
address_word paddr;
int uncached;
if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
isTARGET, isREAL))
{
const uword64 mask = 0x7;
const unsigned int reverse = ReverseEndian ? 1 : 0;
const unsigned int bigend = BigEndianCPU ? 1 : 0;
uword64 memval;
unsigned int byte;
paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
isDATA, isREAL);
byte = (vaddr & mask) ^ (bigend << 2);
return EXTEND32 (memval >> (8 * byte));
}
}
return 0;
}
static void
mips16_entry (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
unsigned int insn)
{
int aregs, sregs, rreg;
#ifdef DEBUG
printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn);
#endif
aregs = (insn & 0x700) >> 8;
sregs = (insn & 0x0c0) >> 6;
rreg = (insn & 0x020) >> 5;
if (sregs == 3)
abort ();
if (aregs < 5)
{
int i;
signed_word tsp;
for (i = 0; i < aregs; i++)
store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]);
tsp = SP;
SP -= 32;
if (rreg)
{
tsp -= 4;
store_word (SD, CPU, cia, (uword64) tsp, RA);
}
for (i = 0; i < sregs; i++)
{
tsp -= 4;
store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]);
}
}
else
{
int i;
signed_word tsp;
tsp = SP + 32;
if (rreg)
{
tsp -= 4;
RA = load_word (SD, CPU, cia, (uword64) tsp);
}
for (i = 0; i < sregs; i++)
{
tsp -= 4;
GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp);
}
SP += 32;
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
if (aregs == 5)
{
FGR[0] = WORD64LO (GPR[4]);
FPR_STATE[0] = fmt_uninterpreted;
}
else if (aregs == 6)
{
FGR[0] = WORD64LO (GPR[5]);
FGR[1] = WORD64LO (GPR[4]);
FPR_STATE[0] = fmt_uninterpreted;
FPR_STATE[1] = fmt_uninterpreted;
}
}
PC = RA;
}
}
#if defined(TRACE)
void
dotrace (SIM_DESC sd,
sim_cpu *cpu,
FILE *tracefh,
int type,
SIM_ADDR address,
int width,
char *comment,...)
{
if (STATE & simTRACE) {
va_list ap;
fprintf(tracefh,"%d %s ; width %d ; ",
type,
pr_addr(address),
width);
va_start(ap,comment);
vfprintf(tracefh,comment,ap);
va_end(ap);
fprintf(tracefh,"\n");
}
return;
}
#endif
static void
ColdReset (SIM_DESC sd)
{
int cpu_nr;
for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
{
sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
PC = (unsigned_word) UNSIGNED64 (0xFFFFFFFFBFC00000);
SR &= ~(status_SR | status_TS | status_RP);
SR |= (status_ERL | status_BEV);
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT
&& WITH_TARGET_WORD_BITSIZE == 64)
SR |= status_FR;
PENDING_INVALIDATE();
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
int rn;
for (rn = 0; (rn < 32); rn++)
FPR_STATE[rn] = fmt_uninterpreted;
}
}
}
void
signal_exception (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
int exception,...)
{
#ifdef DEBUG
sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
#endif
LLBIT = 0;
#ifdef SIM_CPU_EXCEPTION_TRIGGER
SIM_CPU_EXCEPTION_TRIGGER(sd, cpu, cia);
#endif
switch (exception) {
case DebugBreakPoint:
if (! (Debug & Debug_DM))
{
if (INDELAYSLOT())
{
CANCELDELAYSLOT();
Debug |= Debug_DBD;
DEPC = cia - 4;
}
else
{
Debug &= ~Debug_DBD;
DEPC = cia;
}
Debug |= Debug_DM;
Debug |= Debug_DBp;
PC = 0xBFC00200;
sim_engine_restart (SD, CPU, NULL, NULL_CIA);
}
break;
case ReservedInstruction:
{
va_list ap;
unsigned int instruction;
va_start(ap,exception);
instruction = va_arg(ap,unsigned int);
va_end(ap);
if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
{
int reason = (instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK;
if (!sim_monitor (SD, CPU, cia, reason))
sim_io_error (sd, "sim_monitor: unhandled reason = %d, pc = 0x%s\n", reason, pr_addr (cia));
sim_engine_restart (SD, CPU, NULL, RA);
}
else if ((cia & 1) != 0
&& (instruction & 0xf81f) == 0xe809
&& (instruction & 0x0c0) != 0x0c0)
{
mips16_entry (SD, CPU, cia, instruction);
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
}
sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
}
default:
#ifdef SUBTARGET_R3900
CAUSE = LSMASKED32(CAUSE, 31, 7) | LSINSERTED32(exception, 6, 2);
SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 3, 0), 5, 2);
if (STATE & simDELAYSLOT)
{
STATE &= ~simDELAYSLOT;
CAUSE |= cause_BD;
EPC = (cia - 4);
}
else
EPC = cia;
if (SR & status_BEV)
PC = (signed)0xBFC00000 + 0x180;
else
PC = (signed)0x80000000 + 0x080;
#else
if (! (SR & status_EXL))
{
CAUSE = (exception << 2);
if (STATE & simDELAYSLOT)
{
STATE &= ~simDELAYSLOT;
CAUSE |= cause_BD;
EPC = (cia - 4);
}
else
EPC = cia;
}
else
{
CAUSE = (exception << 2);
}
SR |= status_EXL;
if (SR & status_BEV)
PC = (signed)0xBFC00200 + 0x180;
else
PC = (signed)0x80000000 + 0x180;
#endif
switch ((CAUSE >> 2) & 0x1F)
{
case Interrupt:
return;
case NMIReset:
#ifdef SUBTARGET_3900
PC = (signed)0xBFC00000;
#endif
return;
case TLBModification:
case TLBLoad:
case TLBStore:
case AddressLoad:
case AddressStore:
case InstructionFetch:
case DataReference:
sim_engine_halt (SD, CPU, NULL, PC,
sim_stopped, SIM_SIGBUS);
case ReservedInstruction:
case CoProcessorUnusable:
PC = EPC;
sim_engine_halt (SD, CPU, NULL, PC,
sim_stopped, SIM_SIGILL);
case IntegerOverflow:
case FPE:
sim_engine_halt (SD, CPU, NULL, PC,
sim_stopped, SIM_SIGFPE);
case BreakPoint:
sim_engine_halt (SD, CPU, NULL, PC, sim_stopped, SIM_SIGTRAP);
break;
case SystemCall:
case Trap:
sim_engine_restart (SD, CPU, NULL, PC);
break;
case Watch:
PC = EPC;
sim_engine_halt (SD, CPU, NULL, PC,
sim_stopped, SIM_SIGTRAP);
default:
PC = EPC;
sim_engine_halt (SD, CPU, NULL, PC,
sim_stopped, SIM_SIGABRT);
}
case SimulatorFault:
{
va_list ap;
char *msg;
va_start(ap,exception);
msg = va_arg(ap,char *);
va_end(ap);
sim_engine_abort (SD, CPU, NULL_CIA,
"FATAL: Simulator error \"%s\"\n",msg);
}
}
return;
}
void
unpredictable_action(sim_cpu *cpu, address_word cia)
{
SIM_DESC sd = CPU_STATE(cpu);
sim_io_eprintf(sd, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia));
sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGABRT);
}
static int UNUSED
CoProcPresent(unsigned int coproc_number)
{
return(0);
}
void
cop_lw (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
int coproc_num,
int coproc_reg,
unsigned int memword)
{
switch (coproc_num)
{
case 1:
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
#ifdef DEBUG
printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
#endif
StoreFPR(coproc_reg,fmt_word,(uword64)memword);
FPR_STATE[coproc_reg] = fmt_uninterpreted;
break;
}
default:
#if 0
sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(cia));
#endif
break;
}
return;
}
void
cop_ld (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
int coproc_num,
int coproc_reg,
uword64 memword)
{
#ifdef DEBUG
printf("DBG: COP_LD: coproc_num = %d, coproc_reg = %d, value = 0x%s : PC = 0x%s\n", coproc_num, coproc_reg, pr_uword64(memword), pr_addr(cia) );
#endif
switch (coproc_num) {
case 1:
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
StoreFPR(coproc_reg,fmt_uninterpreted,memword);
break;
}
default:
#if 0
sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(cia));
#endif
break;
}
return;
}
unsigned int
cop_sw (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
int coproc_num,
int coproc_reg)
{
unsigned int value = 0;
switch (coproc_num)
{
case 1:
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
FP_formats hold;
hold = FPR_STATE[coproc_reg];
FPR_STATE[coproc_reg] = fmt_word;
value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
FPR_STATE[coproc_reg] = hold;
break;
}
default:
#if 0
sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
#endif
break;
}
return(value);
}
uword64
cop_sd (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
int coproc_num,
int coproc_reg)
{
uword64 value = 0;
switch (coproc_num)
{
case 1:
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
value = ValueFPR(coproc_reg,fmt_uninterpreted);
break;
}
default:
#if 0
sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
#endif
break;
}
return(value);
}
void
decode_coproc (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
unsigned int instruction)
{
int coprocnum = ((instruction >> 26) & 3);
switch (coprocnum)
{
case 0:
{
int code = ((instruction >> 21) & 0x1F);
int rt = ((instruction >> 16) & 0x1F);
int rd = ((instruction >> 11) & 0x1F);
int tail = instruction & 0x3ff;
if (((code == 0x00) || (code == 0x04)
|| (code == 0x01) || (code == 0x05))
&& tail == 0)
{
code &= ~1;
switch (rd)
{
#ifdef SUBTARGET_R3900
case 3:
case 7:
case 15:
break;
case 8:
if (code == 0x00)
GPR[rt] = COP0_BADVADDR;
else
COP0_BADVADDR = GPR[rt];
break;
#endif
case 12:
if (code == 0x00)
GPR[rt] = SR;
else
SR = GPR[rt];
break;
case 13:
if (code == 0x00)
GPR[rt] = CAUSE;
else
CAUSE = GPR[rt];
break;
case 14:
if (code == 0x00)
GPR[rt] = (signed_word) (signed_address) EPC;
else
EPC = GPR[rt];
break;
#ifdef SUBTARGET_R3900
case 16:
if (code == 0x00)
GPR[rt] = Debug;
else
Debug = GPR[rt];
break;
#else
case 16:
if (code == 0x00)
GPR[rt] = C0_CONFIG;
else
C0_CONFIG = GPR[rt];
break;
#endif
#ifdef SUBTARGET_R3900
case 17:
if (code == 0x00)
GPR[rt] = DEPC;
else
DEPC = GPR[rt];
break;
#else
#endif
if (STATE_VERBOSE_P(SD))
sim_io_eprintf (SD,
"Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n",
(unsigned long)cia);
GPR[rt] = 0xDEADC0DE;
default:
if (code == 0x00)
GPR[rt] = (signed_word) (signed32) COP0_GPR[rd];
else
COP0_GPR[rd] = GPR[rt];
#if 0
if (code == 0x00)
sim_io_printf(sd,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia);
else
sim_io_printf(sd,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia);
#endif
}
}
else if (code == 0x10 && (tail & 0x3f) == 0x18)
{
if (SR & status_ERL)
{
sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet");
PC = EPC;
SR &= ~status_ERL;
}
else
{
PC = EPC;
SR &= ~status_EXL;
}
}
else if (code == 0x10 && (tail & 0x3f) == 0x10)
{
#ifdef SUBTARGET_R3900
SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0);
#endif
}
else if (code == 0x10 && (tail & 0x3f) == 0x1F)
{
Debug &= ~Debug_DM;
DELAYSLOT();
DSPC = DEPC;
}
else
sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
}
break;
case 2:
{
int handle = 0;
if(! handle)
{
sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
instruction,pr_addr(cia));
}
}
break;
case 1:
case 3:
SignalException(ReservedInstruction,instruction);
break;
}
return;
}
#define NUMCELLS 16
#define CELLSIZE 32
static char*
get_cell (void)
{
static char buf[NUMCELLS][CELLSIZE];
static int cell=0;
if (++cell>=NUMCELLS) cell=0;
return buf[cell];
}
static int thirty_two = 32;
char*
pr_addr(addr)
SIM_ADDR addr;
{
char *paddr_str=get_cell();
switch (sizeof(addr))
{
case 8:
sprintf(paddr_str,"%08lx%08lx",
(unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
break;
case 4:
sprintf(paddr_str,"%08lx",(unsigned long)addr);
break;
case 2:
sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff));
break;
default:
sprintf(paddr_str,"%x",addr);
}
return paddr_str;
}
char*
pr_uword64(addr)
uword64 addr;
{
char *paddr_str=get_cell();
sprintf(paddr_str,"%08lx%08lx",
(unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
return paddr_str;
}
void
mips_core_signal (SIM_DESC sd,
sim_cpu *cpu,
sim_cia cia,
unsigned map,
int nr_bytes,
address_word addr,
transfer_type transfer,
sim_core_signals sig)
{
const char *copy = (transfer == read_transfer ? "read" : "write");
address_word ip = CIA_ADDR (cia);
switch (sig)
{
case sim_core_unmapped_signal:
sim_io_eprintf (sd, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
nr_bytes, copy,
(unsigned long) addr, (unsigned long) ip);
COP0_BADVADDR = addr;
SignalExceptionDataReference();
break;
case sim_core_unaligned_signal:
sim_io_eprintf (sd, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
nr_bytes, copy,
(unsigned long) addr, (unsigned long) ip);
COP0_BADVADDR = addr;
if(transfer == read_transfer)
SignalExceptionAddressLoad();
else
SignalExceptionAddressStore();
break;
default:
sim_engine_abort (sd, cpu, cia,
"mips_core_signal - internal error - bad switch");
}
}
void
mips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
{
ASSERT(cpu != NULL);
if(cpu->exc_suspended > 0)
sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", cpu->exc_suspended);
PC = cia;
memcpy(cpu->exc_trigger_registers, cpu->registers, sizeof(cpu->exc_trigger_registers));
cpu->exc_suspended = 0;
}
void
mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
{
ASSERT(cpu != NULL);
if(cpu->exc_suspended > 0)
sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n",
cpu->exc_suspended, exception);
memcpy(cpu->exc_suspend_registers, cpu->registers, sizeof(cpu->exc_suspend_registers));
memcpy(cpu->registers, cpu->exc_trigger_registers, sizeof(cpu->registers));
cpu->exc_suspended = exception;
}
void
mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
{
ASSERT(cpu != NULL);
if(exception == 0 && cpu->exc_suspended > 0)
{
if(cpu->exc_suspended != sim_signal_to_host(sd, SIM_SIGTRAP))
sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n",
cpu->exc_suspended);
}
else if(exception != 0 && cpu->exc_suspended > 0)
{
if(exception != cpu->exc_suspended)
sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
cpu->exc_suspended, exception);
memcpy(cpu->registers, cpu->exc_suspend_registers, sizeof(cpu->registers));
}
else if(exception != 0 && cpu->exc_suspended == 0)
{
sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception);
}
cpu->exc_suspended = 0;
}