MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
$Revision$
- $Author$
- $Date$
+ $Date$
NOTEs:
-We only need to take account of the target endianness when moving data
-between the simulator and the host. We do not need to worry about the
-endianness of the host, since this sim code and GDB are executing in
-the same process.
-
The IDT monitor (found on the VR4300 board), seems to lie about
register contents. It seems to treat the registers as sign-extended
32-bit values. This cause *REAL* problems when single-stepping 64-bit
#include "sim-options.h"
#include "sim-assert.h"
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#include "sky-vu.h"
+#include "sky-vpe.h"
+#include "sky-libvpe.h"
+#include "sky-pke.h"
+#include "idecode.h"
+#endif
+/* end-sanitize-sky */
+
#include "config.h"
#include <stdio.h>
/* Get the simulator engine description, without including the code: */
+#if !(WITH_IGEN)
#define SIM_MANIFESTS
#include "oengine.c"
#undef SIM_MANIFESTS
+#endif
+
+/* Within interp.c we refer to the sim_state and sim_cpu directly. */
+#define SD sd
+#define CPU cpu
/* The following reserved instruction value is used when a simulator
/*-- GDB simulator interface ------------------------------------------------*/
/*---------------------------------------------------------------------------*/
-static void dotrace PARAMS((SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
static void ColdReset PARAMS((SIM_DESC sd));
-static long getnum PARAMS((SIM_DESC sd, char *value));
-static unsigned int power2 PARAMS((unsigned int value));
-static void mips_size PARAMS((SIM_DESC sd, int n));
/*---------------------------------------------------------------------------*/
#define K0SIZE (0x20000000)
#define K1BASE (0xA0000000)
#define K1SIZE (0x20000000)
-
-/* Simple run-time monitor support */
-static unsigned char *monitor = NULL;
-static ut_reg monitor_base = 0xBFC00000;
-static unsigned monitor_size = (1 << 11); /* power-of-2 */
-
-static char *logfile = NULL; /* logging disabled by default */
-static FILE *logfh = NULL;
+#define MONITOR_BASE (0xBFC00000)
+#define MONITOR_SIZE (1 << 11)
+#define MEM_SIZE (2 << 20)
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#undef MEM_SIZE
+#define MEM_SIZE (16 << 20) /* 16 MB */
+#endif
+/* end-sanitize-sky */
#if defined(TRACE)
static char *tracefile = "trace.din"; /* default filename for trace log */
-static FILE *tracefh = NULL;
+FILE *tracefh = NULL;
static void open_trace PARAMS((SIM_DESC sd));
#endif /* TRACE */
+static DECLARE_OPTION_HANDLER (mips_option_handler);
+
+enum {
+ OPTION_DINERO_TRACE = OPTION_START,
+ OPTION_DINERO_FILE
+/* start-sanitize-sky */
+ ,OPTION_FLOAT_TYPE
+/* end-sanitize-sky */
+};
+
static SIM_RC
-mips_option_handler (sd, opt, arg)
+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 'l':
- if (arg != NULL) {
- char *tmp;
- tmp = (char *)malloc(strlen(arg) + 1);
- if (tmp == NULL)
- sim_io_printf(sd,"Failed to allocate buffer for logfile name \"%s\"\n",optarg);
- else {
- strcpy(tmp,optarg);
- logfile = tmp;
- }
- }
- return SIM_RC_OK;
-
- case 'n': /* OK */
- sim_io_printf(sd,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg);
- return SIM_RC_FAIL;
-
- case 't': /* ??? */
+ case OPTION_DINERO_TRACE: /* ??? */
#if defined(TRACE)
/* Eventually the simTRACE flag could be treated as a toggle, to
allow external control of the program points being traced
(i.e. only from main onwards, excluding the run-time setup,
etc.). */
- if (arg == NULL)
- STATE |= simTRACE;
- else if (strcmp (arg, "yes") == 0)
- STATE |= simTRACE;
- else if (strcmp (arg, "no") == 0)
- STATE &= ~simTRACE;
- else
+ for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
{
- fprintf (stderr, "Unreconized trace option `%s'\n", arg);
- return SIM_RC_FAIL;
+ 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 /* !TRACE */
fprintf(stderr,"\
-Simulator constructed without tracing support (for performance).\n\
+Simulator constructed without dinero tracing support (for performance).\n\
Re-compile simulator with \"-DTRACE\" to enable this option.\n");
return SIM_RC_FAIL;
#endif /* !TRACE */
- case 'z':
+ case OPTION_DINERO_FILE:
#if defined(TRACE)
if (optarg != NULL) {
char *tmp;
#endif /* TRACE */
return SIM_RC_OK;
+/* start-sanitize-sky */
+ case OPTION_FLOAT_TYPE:
+ /* Use host (fast) or target (accurate) floating point implementation. */
+ if (arg && strcmp (arg, "host") == 0)
+ STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_TARGET;
+ else if (arg && strcmp (arg, "target") == 0)
+ STATE_FP_TYPE_OPT (sd) |= STATE_FP_TYPE_OPT_TARGET;
+ else
+ {
+ fprintf (stderr, "Unrecognized float-type option `%s'\n", arg);
+ return SIM_RC_FAIL;
+ }
+ return SIM_RC_OK;
+/* end-sanitize-sky */
}
return SIM_RC_OK;
static const OPTION mips_options[] =
{
- { {"log", required_argument, NULL,'l'},
- 'l', "FILE", "Log file",
+ { {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE},
+ '\0', "on|off", "Enable dinero tracing",
mips_option_handler },
- { {"name", required_argument, NULL,'n'},
- 'n', "MODEL", "Select arch model",
+ { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
+ '\0', "FILE", "Write dinero trace to FILE",
mips_option_handler },
- { {"trace", optional_argument, NULL,'t'},
- 't', "on|off", "Enable tracing",
- mips_option_handler },
- { {"tracefile",required_argument, NULL,'z'},
- 'z', "FILE", "Write trace to file",
+/* start-sanitize-sky */
+ { {"float-type", required_argument, NULL, OPTION_FLOAT_TYPE},
+ '\0', "host|target", "Use host (fast) or target (accurate) floating point",
mips_option_handler },
+/* end-sanitize-sky */
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
};
static void
interrupt_event (SIM_DESC sd, void *data)
{
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
if (SR & status_IE)
{
interrupt_pending = 0;
}
+/*---------------------------------------------------------------------------*/
+/*-- Device registration hook -----------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+static void device_init(SIM_DESC sd) {
+#ifdef DEVICE_INIT
+ extern void register_devices(SIM_DESC);
+ register_devices(sd);
+#endif
+}
/*---------------------------------------------------------------------------*/
/*-- GDB simulator interface ------------------------------------------------*/
char **argv;
{
SIM_DESC sd = sim_state_alloc (kind, cb);
- sim_cpu *cpu = STATE_CPU (sd, 0);
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
+
+ SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
/* FIXME: watchpoints code shouldn't need this */
STATE_WATCHPOINTS (sd)->pc = &(PC);
STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
- /* memory defaults (unless sim_size was here first) */
- if (STATE_MEM_SIZE (sd) == 0)
- STATE_MEM_SIZE (sd) = (2 << 20);
- STATE_MEM_BASE (sd) = K1BASE;
-
STATE = 0;
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
return 0;
- sim_add_option_table (sd, mips_options);
+ sim_add_option_table (sd, NULL, mips_options);
+
+ /* Allocate core managed memory */
+
+ /* the monitor */
+ sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE);
+ /* For compatibility with the old code - under this (at level one)
+ are the kernel spaces K0 & K1. Both of these map to a single
+ smaller sub region */
+ sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
+/* start-sanitize-sky */
+#ifndef TARGET_SKY
+/* end-sanitize-sky */
+ sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
+ K1BASE, K0SIZE,
+ MEM_SIZE, /* actual size */
+ K0BASE);
+/* start-sanitize-sky */
+#else
+ sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
+ K1BASE, K0SIZE,
+ MEM_SIZE, /* actual size */
+ K0BASE,
+ 0); /* add alias at 0x0000 */
+#endif
+/* end-sanitize-sky */
+
+ device_init(sd);
/* getopt will print the error message so we just have to exit if this fails.
FIXME: Hmmm... in the case of gdb we need getopt to call
/* verify assumptions the simulator made about the host type system.
This macro does not return if there is a problem */
- if (sizeof(int) != (4 * sizeof(char)))
- SignalExceptionSimulatorFault ("sizeof(int) != 4");
- if (sizeof(word64) != (8 * sizeof(char)))
- SignalExceptionSimulatorFault ("sizeof(word64) != 8");
-
-#if defined(HASFPU)
- /* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE
- and DOUBLE binary formats. This is a bit nasty, requiring that we
- trust the explicit manifests held in the source: */
- /* TODO: We need to cope with the simulated target and the host not
- having the same endianness. This will require the high and low
- words of a (double) to be swapped when converting between the
- host and the simulated target. */
- {
- union {
- unsigned int i[2];
- double d;
- float f[2];
- } s;
-
- s.d = (double)523.2939453125;
-
- if ((s.i[0] == 0 && (s.f[1] != (float)4.01102924346923828125
- || s.i[1] != 0x40805A5A))
- || (s.i[1] == 0 && (s.f[0] != (float)4.01102924346923828125
- || s.i[0] != 0x40805A5A)))
- {
- fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n");
- return 0;
- }
- }
-#endif /* HASFPU */
+ SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
+ SIM_ASSERT (sizeof(word64) == (8 * sizeof(char)));
/* This is NASTY, in that we are assuming the size of specific
registers: */
{
int rn;
- for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) {
- if (rn < 32)
- cpu->register_widths[rn] = GPRLEN;
- else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32)))
- cpu->register_widths[rn] = GPRLEN;
- else if ((rn >= 33) && (rn <= 37))
- cpu->register_widths[rn] = GPRLEN;
- else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89)))
- cpu->register_widths[rn] = 32;
- else
- cpu->register_widths[rn] = 0;
- }
+ for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++)
+ {
+ if (rn < 32)
+ cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
+ else if ((rn >= FGRIDX) && (rn < (FGRIDX + 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;
+ }
/* start-sanitize-r5900 */
/* set the 5900 "upper" registers to 64 bits */
for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++)
cpu->register_widths[rn] = 64;
/* end-sanitize-r5900 */
- }
-
- if (logfile != NULL) {
- if (strcmp(logfile,"-") == 0)
- logfh = stdout;
- else {
- logfh = fopen(logfile,"wb+");
- if (logfh == NULL) {
- sim_io_printf(sd,"Failed to create file \"%s\", writing log information to stderr.\n",tracefile);
- logfh = stderr;
- }
+ /* start-sanitize-sky */
+#ifdef TARGET_SKY
+ /* Now the VU registers */
+ for( rn = 0; rn < NUM_VU_INTEGER_REGS; rn++ ) {
+ cpu->register_widths[rn + NUM_R5900_REGS] = 16;
+ cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 16;
}
- }
- /* FIXME: In the future both of these malloc's can be replaced by
- calls to sim-core. */
+ for( rn = NUM_VU_INTEGER_REGS; rn < NUM_VU_REGS; rn++ ) {
+ cpu->register_widths[rn + NUM_R5900_REGS] = 32;
+ cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 32;
+ }
- /* If the host has "mmap" available we could use it to provide a
- very large virtual address space for the simulator, since memory
- would only be allocated within the "mmap" space as it is
- accessed. This can also be linked to the architecture specific
- support, required to simulate the MMU. */
- mips_size(sd, STATE_MEM_SIZE (sd));
- /* NOTE: The above will also have enabled any profiling state! */
-
- /* Create the monitor address space as well */
- monitor = (unsigned char *)calloc(1,monitor_size);
- if (!monitor)
- fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n",
- monitor_size);
+ /* Finally the VIF registers */
+ for( rn = 2*NUM_VU_REGS; rn < 2*NUM_VU_REGS + 2*NUM_VIF_REGS; rn++ )
+ cpu->register_widths[rn + NUM_R5900_REGS] = 32;
+#endif
+ /* end-sanitize-sky */
+ }
#if defined(TRACE)
if (STATE & simTRACE)
not using machine instructions. To avoid clashing with use of
the MIPS TRAP system, we place our own (simulator specific)
"undefined" instructions into the relevant vector slots. */
- for (loop = 0; (loop < monitor_size); loop += 4) {
- address_word vaddr = (monitor_base + loop);
- address_word paddr;
- int cca;
- if (AddressTranslation(vaddr, isDATA, isSTORE, &paddr, &cca, isTARGET, isRAW))
- StoreMemory(cca, AccessLength_WORD,
- (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)),
- 0, paddr, vaddr, isRAW);
- }
+ for (loop = 0; (loop < MONITOR_SIZE); loop += 4)
+ {
+ address_word vaddr = (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));
+ }
/* The PMON monitor uses the same address space, but rather than
branching into it the address of a routine is loaded. We can
cheat for the moment, and direct the PMON routine to IDT style
entry points.*/
for (loop = 0; (loop < 24); loop++)
{
- address_word vaddr = (monitor_base + 0x500 + (loop * 4));
- address_word paddr;
- int cca;
- unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
+ address_word vaddr = (MONITOR_BASE + 0x500 + (loop * 4));
+ unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
switch (loop)
{
case 0: /* read */
value = 7;
break;
-
case 1: /* write */
value = 8;
break;
-
case 2: /* open */
value = 6;
break;
-
case 3: /* close */
value = 10;
break;
-
case 5: /* printf */
value = ((0x500 - 16) / 8); /* not an IDT reason code */
break;
-
case 8: /* cliexit */
value = 17;
break;
-
case 11: /* flush_cache */
value = 28;
break;
}
- /* FIXME - should monitor_base be SIM_ADDR?? */
- value = ((unsigned int)monitor_base + (value * 8));
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- else
- sim_io_error(sd,"Failed to write to monitor space 0x%s",pr_addr(vaddr));
+ /* FIXME - should monitor_base be SIM_ADDR?? */
+ value = ((unsigned int)MONITOR_BASE + (value * 8));
+ H2T (value);
+ sim_write (sd, vaddr, (char *)&value, sizeof (value));
/* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */
vaddr -= 0x300;
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- else
- sim_io_error(sd,"Failed to write to monitor space 0x%s",pr_addr(vaddr));
+ sim_write (sd, vaddr, (char *)&value, sizeof (value));
}
}
if (tracefh != NULL && tracefh != stderr)
fclose(tracefh);
tracefh = NULL;
- STATE &= ~simTRACE;
#endif /* TRACE */
- if (logfh != NULL && logfh != stdout && logfh != stderr)
- fclose(logfh);
- logfh = NULL;
-
- if (STATE_MEMORY (sd) != NULL)
- free(STATE_MEMORY (sd)); /* cfree not available on all hosts */
- STATE_MEMORY (sd) = NULL;
+ /* FIXME - free SD */
return;
}
unsigned char *buffer;
int size;
{
- int index = size;
- uword64 vaddr = (uword64)addr;
+ int index;
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* Return the number of bytes written, or zero if error. */
#ifdef DEBUG
sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
#endif
- /* We provide raw read and write routines, since we do not want to
- count the GDB memory accesses in our statistics gathering. */
+ /* We use raw read and write routines, since we do not want to count
+ the GDB memory accesses in our statistics gathering. */
- /* There is a lot of code duplication in the individual blocks
- below, but the variables are declared locally to a block to give
- the optimiser the best chance of improving the code. We have to
- perform slow byte reads from the host memory, to ensure that we
- get the data into the correct endianness for the (simulated)
- target memory world. */
-
- /* Mask count to get odd byte, odd halfword, and odd word out of the
- way. We can then perform doubleword transfers to and from the
- simulator memory for optimum performance. */
- if (index && (index & 1)) {
- address_word paddr;
- int cca;
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- uword64 value = ((uword64)(*buffer++));
- StoreMemory(cca,AccessLength_BYTE,value,0,paddr,vaddr,isRAW);
- }
- vaddr++;
- index &= ~1; /* logical operations usually quicker than arithmetic on RISC systems */
- }
- if (index && (index & 2)) {
- address_word paddr;
- int cca;
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- uword64 value;
- /* We need to perform the following magic to ensure that that
- bytes are written into same byte positions in the target memory
- world, regardless of the endianness of the host. */
- if (BigEndianMem) {
- value = ((uword64)(*buffer++) << 8);
- value |= ((uword64)(*buffer++) << 0);
- } else {
- value = ((uword64)(*buffer++) << 0);
- value |= ((uword64)(*buffer++) << 8);
- }
- StoreMemory(cca,AccessLength_HALFWORD,value,0,paddr,vaddr,isRAW);
- }
- vaddr += 2;
- index &= ~2;
- }
- if (index && (index & 4)) {
- address_word paddr;
- int cca;
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- uword64 value;
- if (BigEndianMem) {
- value = ((uword64)(*buffer++) << 24);
- value |= ((uword64)(*buffer++) << 16);
- value |= ((uword64)(*buffer++) << 8);
- value |= ((uword64)(*buffer++) << 0);
- } else {
- value = ((uword64)(*buffer++) << 0);
- value |= ((uword64)(*buffer++) << 8);
- value |= ((uword64)(*buffer++) << 16);
- value |= ((uword64)(*buffer++) << 24);
- }
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- }
- vaddr += 4;
- index &= ~4;
- }
- for (;index; index -= 8) {
- address_word paddr;
- int cca;
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- uword64 value;
- if (BigEndianMem) {
- value = ((uword64)(*buffer++) << 56);
- value |= ((uword64)(*buffer++) << 48);
- value |= ((uword64)(*buffer++) << 40);
- value |= ((uword64)(*buffer++) << 32);
- value |= ((uword64)(*buffer++) << 24);
- value |= ((uword64)(*buffer++) << 16);
- value |= ((uword64)(*buffer++) << 8);
- value |= ((uword64)(*buffer++) << 0);
- } else {
- value = ((uword64)(*buffer++) << 0);
- value |= ((uword64)(*buffer++) << 8);
- value |= ((uword64)(*buffer++) << 16);
- value |= ((uword64)(*buffer++) << 24);
- value |= ((uword64)(*buffer++) << 32);
- value |= ((uword64)(*buffer++) << 40);
- value |= ((uword64)(*buffer++) << 48);
- value |= ((uword64)(*buffer++) << 56);
- }
- StoreMemory(cca,AccessLength_DOUBLEWORD,value,0,paddr,vaddr,isRAW);
+ 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;
}
- vaddr += 8;
- }
- return(size);
+ return(index);
}
int
int size;
{
int index;
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* Return the number of bytes read, or zero if error. */
#ifdef DEBUG
sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
#endif /* DEBUG */
- /* TODO: Perform same optimisation as the sim_write() code
- above. NOTE: This will require a bit more work since we will need
- to ensure that the source physical address is doubleword aligned
- before, and then deal with trailing bytes. */
- for (index = 0; (index < size); index++) {
- address_word vaddr;
- address_word paddr;
- unsigned64 value;
- int cca;
- vaddr = (address_word)addr + index;
- if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&cca,isTARGET,isRAW)) {
- LoadMemory(&value,NULL,cca,AccessLength_BYTE,paddr,vaddr,isDATA,isRAW);
- buffer[index] = (unsigned char)(value&0xFF);
- } else
- break;
- }
+ 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);
}
-void
-sim_store_register (sd,rn,memory)
+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);
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* NOTE: gdb (the client) stores registers in target byte order
while the simulator uses host byte order */
#ifdef DEBUG
register number is for the architecture being simulated. */
if (cpu->register_widths[rn] == 0)
- sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
+ {
+ sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
+ return 0;
+ }
+
/* start-sanitize-r5900 */
- else if (rn == REGISTER_SA)
- SA = T2H_8(*(uword64*)memory);
- else if (rn > LAST_EMBED_REGNUM)
- cpu->registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory);
+ if (rn >= 90 && rn < 90 + 32)
+ {
+ GPR1[rn - 90] = T2H_8 (*(unsigned64*)memory);
+ return 8;
+ }
+ switch (rn)
+ {
+ case REGISTER_SA:
+ SA = T2H_8(*(unsigned64*)memory);
+ return 8;
+ case 122: /* FIXME */
+ LO1 = T2H_8(*(unsigned64*)memory);
+ return 8;
+ case 123: /* FIXME */
+ HI1 = T2H_8(*(unsigned64*)memory);
+ return 8;
+ }
/* end-sanitize-r5900 */
- else if (cpu->register_widths[rn] == 32)
- cpu->registers[rn] = T2H_4 (*(unsigned int*)memory);
+
+ /* start-sanitize-sky */
+#ifdef TARGET_SKY
+ if (rn >= NUM_R5900_REGS)
+ {
+ rn = rn - NUM_R5900_REGS;
+
+ if( rn < NUM_VU_REGS )
+ {
+ if (rn < NUM_VU_INTEGER_REGS)
+ return write_vu_int_reg (&(vu0_device.regs), rn, memory);
+ else if (rn >= FIRST_VEC_REG)
+ {
+ rn -= FIRST_VEC_REG;
+ return write_vu_vec_reg (&(vu0_device.regs), rn>>2, rn&3,
+ memory);
+ }
+ else switch (rn - NUM_VU_INTEGER_REGS)
+ {
+ case 0:
+ return write_vu_special_reg (&vu0_device, VU_REG_CIA,
+ memory);
+ case 1:
+ return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MR,
+ memory);
+ case 2: /* VU0 has no P register */
+ return 4;
+ case 3:
+ return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MI,
+ memory);
+ case 4:
+ return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ,
+ memory);
+ default:
+ return write_vu_acc_reg (&(vu0_device.regs),
+ rn - (NUM_VU_INTEGER_REGS + 5),
+ memory);
+ }
+ }
+
+ rn = rn - NUM_VU_REGS;
+
+ if (rn < NUM_VU_REGS)
+ {
+ if (rn < NUM_VU_INTEGER_REGS)
+ return write_vu_int_reg (&(vu1_device.regs), rn, memory);
+ else if (rn >= FIRST_VEC_REG)
+ {
+ rn -= FIRST_VEC_REG;
+ return write_vu_vec_reg (&(vu1_device.regs),
+ rn >> 2, rn & 3, memory);
+ }
+ else switch (rn - NUM_VU_INTEGER_REGS)
+ {
+ case 0:
+ return write_vu_special_reg (&vu1_device, VU_REG_CIA,
+ memory);
+ case 1:
+ return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MR,
+ memory);
+ case 2:
+ return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MP,
+ memory);
+ case 3:
+ return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MI,
+ memory);
+ case 4:
+ return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ,
+ memory);
+ default:
+ return write_vu_acc_reg (&(vu1_device.regs),
+ rn - (NUM_VU_INTEGER_REGS + 5),
+ memory);
+ }
+ }
+
+ rn -= NUM_VU_REGS; /* VIF0 registers are next */
+
+ if (rn < NUM_VIF_REGS)
+ {
+ if (rn < NUM_VIF_REGS-1)
+ return write_pke_reg (&pke0_device, rn, memory);
+ else
+ {
+ sim_io_eprintf( sd, "Can't write vif0_pc (store ignored)\n" );
+ return 0;
+ }
+ }
+
+ rn -= NUM_VIF_REGS; /* VIF1 registers are last */
+
+ if (rn < NUM_VIF_REGS)
+ {
+ if (rn < NUM_VIF_REGS-1)
+ return write_pke_reg (&pke1_device, rn, memory);
+ else
+ {
+ sim_io_eprintf( sd, "Can't write vif1_pc (store ignored)\n" );
+ return 0;
+ }
+ }
+
+ sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+ return 0;
+ }
+#endif
+ /* end-sanitize-sky */
+
+ if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
+ {
+ if (cpu->register_widths[rn] == 32)
+ {
+ cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory);
+ return 4;
+ }
+ else
+ {
+ cpu->fgr[rn - FGRIDX] = T2H_8 (*(unsigned64*)memory);
+ return 8;
+ }
+ }
+
+ if (cpu->register_widths[rn] == 32)
+ {
+ cpu->registers[rn] = T2H_4 (*(unsigned32*)memory);
+ return 4;
+ }
else
- cpu->registers[rn] = T2H_8 (*(uword64*)memory);
+ {
+ cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
+ return 8;
+ }
- return;
+ return 0;
}
-void
-sim_fetch_register (sd,rn,memory)
+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);
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* NOTE: gdb (the client) stores registers in target byte order
while the simulator uses host byte order */
#ifdef DEBUG
#endif /* DEBUG */
if (cpu->register_widths[rn] == 0)
- sim_io_eprintf(sd,"Invalid register width for %d (register fetch ignored)\n",rn);
+ {
+ sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn);
+ return 0;
+ }
+
/* start-sanitize-r5900 */
- else if (rn == REGISTER_SA)
- *((uword64 *)memory) = H2T_8(SA);
- else if (rn > LAST_EMBED_REGNUM)
- *((uword64 *)memory) = H2T_8(cpu->registers1[rn - LAST_EMBED_REGNUM - 1]);
+ if (rn >= 90 && rn < 90 + 32)
+ {
+ *(unsigned64*)memory = GPR1[rn - 90];
+ return 8;
+ }
+ switch (rn)
+ {
+ case REGISTER_SA:
+ *((unsigned64*)memory) = H2T_8(SA);
+ return 8;
+ case 122: /* FIXME */
+ *((unsigned64*)memory) = H2T_8(LO1);
+ return 8;
+ case 123: /* FIXME */
+ *((unsigned64*)memory) = H2T_8(HI1);
+ return 8;
+ }
/* end-sanitize-r5900 */
- else if (cpu->register_widths[rn] == 32)
- *((unsigned int *)memory) = H2T_4 ((unsigned int)(cpu->registers[rn] & 0xFFFFFFFF));
- else /* 64bit register */
- *((uword64 *)memory) = H2T_8 (cpu->registers[rn]);
- return;
-}
+ /* start-sanitize-sky */
+#ifdef TARGET_SKY
+ if (rn >= NUM_R5900_REGS)
+ {
+ rn = rn - NUM_R5900_REGS;
+
+ if (rn < NUM_VU_REGS)
+ {
+ if (rn < NUM_VU_INTEGER_REGS)
+ return read_vu_int_reg (&(vu0_device.regs), rn, memory);
+ else if (rn >= FIRST_VEC_REG)
+ {
+ rn -= FIRST_VEC_REG;
+ return read_vu_vec_reg (&(vu0_device.regs), rn>>2, rn & 3,
+ memory);
+ }
+ else switch (rn - NUM_VU_INTEGER_REGS)
+ {
+ case 0:
+ return read_vu_special_reg(&vu0_device, VU_REG_CIA, memory);
+ case 1:
+ return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MR,
+ memory);
+ case 2: /* VU0 has no P register */
+ *((int *) memory) = 0;
+ return 4;
+ case 3:
+ return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MI,
+ memory);
+ case 4:
+ return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ,
+ memory);
+ default:
+ return read_vu_acc_reg (&(vu0_device.regs),
+ rn - (NUM_VU_INTEGER_REGS + 5),
+ memory);
+ }
+ }
+ rn -= NUM_VU_REGS; /* VU1 registers are next */
-void
-sim_info (sd,verbose)
- SIM_DESC sd;
- int verbose;
-{
- /* Accessed from the GDB "info files" command: */
- if (STATE_VERBOSE_P (sd) || verbose)
+ if (rn < NUM_VU_REGS)
+ {
+ if (rn < NUM_VU_INTEGER_REGS)
+ return read_vu_int_reg (&(vu1_device.regs), rn, memory);
+ else if (rn >= FIRST_VEC_REG)
+ {
+ rn -= FIRST_VEC_REG;
+ return read_vu_vec_reg (&(vu1_device.regs),
+ rn >> 2, rn & 3, memory);
+ }
+ else switch (rn - NUM_VU_INTEGER_REGS)
+ {
+ case 0:
+ return read_vu_special_reg(&vu1_device, VU_REG_CIA, memory);
+ case 1:
+ return read_vu_misc_reg (&(vu1_device.regs),
+ VU_REG_MR, memory);
+ case 2:
+ return read_vu_misc_reg (&(vu1_device.regs),
+ VU_REG_MP, memory);
+ case 3:
+ return read_vu_misc_reg (&(vu1_device.regs),
+ VU_REG_MI, memory);
+ case 4:
+ return read_vu_misc_reg (&(vu1_device.regs),
+ VU_REG_MQ, memory);
+ default:
+ return read_vu_acc_reg (&(vu1_device.regs),
+ rn - (NUM_VU_INTEGER_REGS + 5),
+ memory);
+ }
+ }
+
+ rn -= NUM_VU_REGS; /* VIF0 registers are next */
+
+ if (rn < NUM_VIF_REGS)
+ {
+ if (rn < NUM_VIF_REGS-1)
+ return read_pke_reg (&pke0_device, rn, memory);
+ else
+ return read_pke_pc (&pke0_device, memory);
+ }
+
+ rn -= NUM_VIF_REGS; /* VIF1 registers are last */
+
+ if (rn < NUM_VIF_REGS)
+ {
+ if (rn < NUM_VIF_REGS-1)
+ return read_pke_reg (&pke1_device, rn, memory);
+ else
+ return read_pke_pc (&pke1_device, memory);
+ }
+
+ sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
+ }
+#endif
+ /* end-sanitize-sky */
+
+ /* Any floating point register */
+ if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
{
-
- sim_io_printf (sd, "MIPS %d-bit %s endian simulator\n",
- (PROCESSOR_64BIT ? 64 : 32),
- (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little"));
-
- sim_io_printf (sd, "0x%08X bytes of memory at 0x%s\n",
- STATE_MEM_SIZE (sd),
- pr_addr (STATE_MEM_BASE (sd)));
-
-#if !defined(FASTSIM)
- /* It would be a useful feature, if when performing multi-cycle
- simulations (rather than single-stepping) we keep the start and
- end times of the execution, so that we can give a performance
- figure for the simulator. */
-#endif /* !FASTSIM */
- sim_io_printf (sd, "Number of execution cycles = %ld\n",
- (long) sim_events_time (sd));
-
- /* print information pertaining to MIPS ISA and architecture being simulated */
- /* things that may be interesting */
- /* instructions executed - if available */
- /* cycles executed - if available */
- /* pipeline stalls - if available */
- /* virtual time taken */
- /* profiling size */
- /* profiling frequency */
- /* profile minpc */
- /* profile maxpc */
- }
- profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL);
+ if (cpu->register_widths[rn] == 32)
+ {
+ *(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGRIDX]);
+ return 4;
+ }
+ else
+ {
+ *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGRIDX]);
+ return 8;
+ }
+ }
+
+ if (cpu->register_widths[rn] == 32)
+ {
+ *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
+ return 4;
+ }
+ else
+ {
+ *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
+ return 8;
+ }
+
+ return 0;
}
ColdReset(sd);
if (abfd != NULL)
- /* override PC value set by ColdReset () */
- PC = (unsigned64) bfd_get_start_address (abfd);
+ {
+ /* override PC value set by ColdReset () */
+ 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 /* def DEBUG */
if (argv || env)
return SIM_RC_OK;
}
-typedef enum {e_terminate,e_help,e_setmemsize,e_reset} e_cmds;
-
-static struct t_sim_command {
- e_cmds id;
- const char *name;
- const char *help;
-} sim_commands[] = {
- {e_help, "help", ": Show MIPS simulator private commands"},
- {e_setmemsize,"set-memory-size","<n> : Specify amount of memory simulated"},
- {e_reset, "reset-system", ": Reset the simulated processor"},
- {e_terminate, NULL}
-};
-
void
sim_do_command (sd,cmd)
SIM_DESC sd;
char *cmd;
{
- struct t_sim_command *cptr;
-
- if (!(cmd && *cmd != '\0'))
- cmd = "help";
-
- /* NOTE: Accessed from the GDB "sim" commmand: */
- for (cptr = sim_commands; cptr && cptr->name; cptr++)
- if (strncmp (cmd, cptr->name, strlen(cptr->name)) == 0)
- {
- cmd += strlen(cptr->name);
- switch (cptr->id) {
- case e_help: /* no arguments */
- { /* no arguments */
- struct t_sim_command *lptr;
- sim_io_printf(sd,"List of MIPS simulator commands:\n");
- for (lptr = sim_commands; lptr->name; lptr++)
- sim_io_printf(sd,"%s %s\n",lptr->name,lptr->help);
- sim_args_command (sd, "help");
- }
- break;
-
- case e_setmemsize: /* memory size argument */
- {
- unsigned int newsize = (unsigned int)getnum(sd, cmd);
- mips_size(sd, newsize);
- }
- break;
-
- case e_reset: /* no arguments */
- ColdReset(sd);
- /* NOTE: See the comments in sim_open() relating to device
- initialisation. */
- break;
-
- default:
- sim_io_printf(sd,"FATAL: Matched \"%s\", but failed to match command id %d.\n",cmd,cptr->id);
- break;
- }
- break;
- }
-
- if (!(cptr->name))
- {
- /* try for a common command when the sim specific lookup fails */
- if (sim_args_command (sd, cmd) != SIM_RC_OK)
- sim_io_printf(sd,"Error: \"%s\" is not a valid MIPS simulator command.\n",cmd);
- }
-
- return;
+ if (sim_args_command (sd, cmd) != SIM_RC_OK)
+ sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n",
+ cmd);
}
/*---------------------------------------------------------------------------*/
-/* NOTE: The following routines do not seem to be used by GDB at the
- moment. However, they may be useful to the standalone simulator
- world. */
-
+/*-- Private simulator support interface ------------------------------------*/
+/*---------------------------------------------------------------------------*/
-static void
-mips_size(sd, newsize)
+/* Read a null terminated string from memory, return in a buffer */
+static char *
+fetch_str (sd, addr)
SIM_DESC sd;
- int newsize;
+ address_word addr;
{
- char *new;
- /* Used by "run", and internally, to set the simulated memory size */
- if (newsize == 0) {
- sim_io_printf(sd,"Zero not valid: Memory size still 0x%08X bytes\n",STATE_MEM_SIZE (sd));
- return;
- }
- newsize = power2(newsize);
- if (STATE_MEMORY (sd) == NULL)
- new = (char *)calloc(64,(STATE_MEM_SIZE (sd) / 64));
- else
- new = (char *)realloc(STATE_MEMORY (sd),newsize);
- if (new == NULL) {
- if (STATE_MEMORY (sd) == NULL)
- sim_io_error(sd,"Not enough VM for simulation memory of 0x%08X bytes",STATE_MEM_SIZE (sd));
- else
- sim_io_eprintf(sd,"Failed to resize memory (still 0x%08X bytes)\n",STATE_MEM_SIZE (sd));
- } else {
- STATE_MEM_SIZE (sd) = (unsigned)newsize;
- STATE_MEMORY (sd) = new;
- }
- return;
+ 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;
}
-
-/*---------------------------------------------------------------------------*/
-/*-- Private simulator support interface ------------------------------------*/
-/*---------------------------------------------------------------------------*/
-
/* Simple monitor interface (currently setup for the IDT and PMON monitors) */
static void
-sim_monitor(sd,reason)
- SIM_DESC sd;
- unsigned int reason;
+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);
/* The following callback functions are available, however the
monitor we are simulating does not make use of them: get_errno,
isatty, lseek, rename, system, time and unlink */
- switch (reason) {
+ switch (reason)
+ {
+
case 6: /* int open(char *path,int flags) */
{
- address_word paddr;
- int cca;
- if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
- V0 = sim_io_open(sd,(char *)((int)paddr),(int)A1);
- else
- sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
+ char *path = fetch_str (sd, A0);
+ V0 = sim_io_open (sd, path, (int)A1);
+ zfree (path);
+ break;
}
- break;
case 7: /* int read(int file,char *ptr,int len) */
{
- address_word paddr;
- int cca;
- if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
- V0 = sim_io_read(sd,(int)A0,(char *)((int)paddr),(int)A2);
- else
- sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
+ 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 write(int file,char *ptr,int len) */
{
- address_word paddr;
- int cca;
- if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
- V0 = sim_io_write(sd,(int)A0,(const char *)((int)paddr),(int)A2);
- else
- sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
+ 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;
}
- break;
case 10: /* int close(int file) */
- V0 = sim_io_close(sd,(int)A0);
- break;
+ {
+ V0 = sim_io_close (sd, (int)A0);
+ break;
+ }
+
+ case 2: /* Densan monitor: char inbyte(int waitflag) */
+ {
+ if (A0 == 0) /* waitflag == NOWAIT */
+ V0 = (unsigned_word)-1;
+ }
+ /* Drop through to case 11 */
case 11: /* char inbyte(void) */
{
char tmp;
- if (sim_io_read_stdin(sd,&tmp,sizeof(char)) != sizeof(char)) {
- sim_io_error(sd,"Invalid return from character read");
- V0 = (ut_reg)-1;
- }
+ 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 = (ut_reg)tmp;
+ V0 = (unsigned_word)tmp;
+ break;
}
- break;
+ case 3: /* Densan monitor: void co(char chr) */
case 12: /* void outbyte(char chr) : write a byte to "stdout" */
{
char tmp = (char)(A0 & 0xFF);
- sim_io_write_stdout(sd,&tmp,sizeof(char));
+ sim_io_write_stdout (sd, &tmp, sizeof(char));
+ break;
}
- break;
case 17: /* void _exit() */
- sim_io_eprintf(sd,"sim_monitor(17): _exit(int reason) to be coded\n");
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, sim_exited,
- (unsigned int)(A0 & 0xFFFFFFFF));
- break;
+ {
+ 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 : /* PMON flush_cache */
break;
/* [A0 + 4] = instruction cache size */
/* [A0 + 8] = data cache size */
{
- address_word vaddr = A0;
- address_word paddr, value;
- int cca;
- int failed = 0;
-
- /* NOTE: We use RAW memory writes here, but since we are not
- gathering statistics for the monitor calls we are simulating,
- it is not an issue. */
-
- /* Memory size */
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
- value = (uword64)STATE_MEM_SIZE (sd);
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- /* We re-do the address translations, in-case the block
- overlaps a memory boundary: */
- value = 0;
- vaddr += (AccessLength_WORD + 1);
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
- StoreMemory(cca,AccessLength_WORD,0,value,paddr,vaddr,isRAW);
- vaddr += (AccessLength_WORD + 1);
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL))
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- else
- failed = -1;
- } else
- failed = -1;
- } else
- failed = -1;
-
- if (failed)
- sim_io_error(sd,"Invalid pointer passed into monitor call");
+ unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+ 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);
+ /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
+ break;
}
- break;
-
+
case 158 : /* PMON printf */
/* in: A0 = pointer to format string */
/* A1 = optional argument 1 */
/* out: void */
/* The following is based on the PMON printf source */
{
- address_word paddr;
- int cca;
+ address_word s = A0;
+ char c;
+ signed_word *ap = &A1; /* 1st argument */
/* This isn't the quickest way, since we call the host print
routine for every character almost. But it does avoid
having to allocate and manage a temporary string buffer. */
- if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
- char *s = (char *)((int)paddr);
- signed_word *ap = &A1; /* 1st argument */
- /* TODO: Include check that we only use three arguments (A1, A2 and A3) */
- for (; *s;) {
- if (*s == '%') {
- char tmp[40];
- enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
- int width = 0, trunc = 0, haddot = 0, longlong = 0;
- s++;
- for (; *s; s++) {
- if (strchr ("dobxXulscefg%", *s))
- break;
- else if (*s == '-')
- fmt = FMT_LJUST;
- else if (*s == '0')
- fmt = FMT_RJUST0;
- else if (*s == '~')
- fmt = FMT_CENTER;
- else if (*s == '*') {
- if (haddot)
- trunc = (int)*ap++;
- else
- width = (int)*ap++;
- } else if (*s >= '1' && *s <= '9') {
- char *t;
- unsigned int n;
- for (t = s; isdigit (*s); s++);
- strncpy (tmp, t, s - t);
- tmp[s - t] = '\0';
- n = (unsigned int)strtol(tmp,NULL,10);
- if (haddot)
- trunc = n;
- else
- width = n;
- s--;
- } else if (*s == '.')
- haddot = 1;
- }
- if (*s == '%') {
- sim_io_printf(sd,"%%");
- } else if (*s == 's') {
- if ((int)*ap != 0) {
- if (AddressTranslation(*ap++,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
- char *p = (char *)((int)paddr);;
- sim_io_printf(sd,p);
- } else {
- ap++;
- sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
- }
- }
- else
- sim_io_printf(sd,"(null)");
- } else if (*s == 'c') {
- int n = (int)*ap++;
- sim_io_printf(sd,"%c",n);
- } else {
- if (*s == 'l') {
- if (*++s == 'l') {
- longlong = 1;
- ++s;
- }
- }
- if (strchr ("dobxXu", *s)) {
- word64 lv = (word64) *ap++;
- if (*s == 'b')
- sim_io_printf(sd,"<binary not supported>");
- else {
- sprintf(tmp,"%%%s%c",longlong ? "ll" : "",*s);
- if (longlong)
- sim_io_printf(sd,tmp,lv);
- else
- sim_io_printf(sd,tmp,(int)lv);
- }
- } else if (strchr ("eEfgG", *s)) {
-#ifdef _MSC_VER /* MSVC version 2.x can't convert from uword64 directly */
- double dbl = (double)((word64)*ap++);
-#else
- double dbl = (double)*ap++;
-#endif
- sprintf(tmp,"%%%d.%d%c",width,trunc,*s);
- sim_io_printf(sd,tmp,dbl);
- trunc = 0;
- }
- }
- s++;
- } else
- sim_io_printf(sd,"%c",*s++);
- }
- } else
- sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
+ /* TODO: Include check that we only use three arguments (A1,
+ A2 and A3) */
+ 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%", s))
+ 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;
}
- break;
default:
- sim_io_eprintf(sd,"TODO: sim_monitor(%d) : PC = 0x%s\n",reason,pr_addr(IPC));
- sim_io_eprintf(sd,"(Arguments : A0 = 0x%s : A1 = 0x%s : A2 = 0x%s : A3 = 0x%s)\n",pr_addr(A0),pr_addr(A1),pr_addr(A2),pr_addr(A3));
+ sim_io_error (sd, "TODO: sim_monitor(%d) : PC = 0x%s\n",
+ reason, pr_addr(cia));
break;
}
return;
/* Store a word into memory. */
static void
-store_word (sd, vaddr, val)
- SIM_DESC sd;
- uword64 vaddr;
- t_reg val;
+store_word (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ uword64 vaddr,
+ signed_word val)
{
address_word paddr;
int uncached;
/* Load a word from memory. */
-static t_reg
-load_word (sd, vaddr)
- SIM_DESC sd;
- uword64 vaddr;
+static signed_word
+load_word (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ uword64 vaddr)
{
if ((vaddr & 3) != 0)
SignalExceptionAddressLoad ();
code, but for ease of simulation we just handle them directly. */
static void
-mips16_entry (sd,insn)
- SIM_DESC sd;
- unsigned int insn;
+mips16_entry (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ unsigned int insn)
{
int aregs, sregs, rreg;
if (aregs < 5)
{
int i;
- t_reg tsp;
+ signed_word tsp;
/* This is the entry pseudo-instruction. */
for (i = 0; i < aregs; i++)
- store_word ((uword64) (SP + 4 * i), GPR[i + 4]);
+ store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]);
tsp = SP;
SP -= 32;
if (rreg)
{
tsp -= 4;
- store_word ((uword64) tsp, RA);
+ store_word (SD, CPU, cia, (uword64) tsp, RA);
}
for (i = 0; i < sregs; i++)
{
tsp -= 4;
- store_word ((uword64) tsp, GPR[16 + i]);
+ store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]);
}
}
else
{
int i;
- t_reg tsp;
+ signed_word tsp;
/* This is the exit pseudo-instruction. */
if (rreg)
{
tsp -= 4;
- RA = load_word ((uword64) tsp);
+ RA = load_word (SD, CPU, cia, (uword64) tsp);
}
for (i = 0; i < sregs; i++)
{
tsp -= 4;
- GPR[i + 16] = load_word ((uword64) tsp);
+ GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp);
}
SP += 32;
-#if defined(HASFPU)
- if (aregs == 5)
+ if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
{
- 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;
- }
-#endif /* defined(HASFPU) */
+ 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;
}
-}
-
-static unsigned int
-power2(value)
- unsigned int value;
-{
- int loop,tmp;
-
- /* Round *UP* to the nearest power-of-2 if not already one */
- if (value != (value & ~(value - 1))) {
- for (tmp = value, loop = 0; (tmp != 0); loop++)
- tmp >>= 1;
- value = (1 << loop);
- }
-
- return(value);
-}
-
-static long
-getnum(sd,value)
- SIM_DESC sd;
- char *value;
-{
- long num;
- char *end;
-
- num = strtol(value,&end,10);
- if (end == value)
- sim_io_printf(sd,"Warning: Invalid number \"%s\" ignored, using zero\n",value);
- else {
- if (*end && ((tolower(*end) == 'k') || (tolower(*end) == 'm'))) {
- if (tolower(*end) == 'k')
- num *= (1 << 10);
- else
- num *= (1 << 20);
- end++;
- }
- if (*end)
- sim_io_printf(sd,"Warning: Spurious characters \"%s\" at end of number ignored\n",end);
- }
-
- return(num);
+
}
/*-- trace support ----------------------------------------------------------*/
currently have an ARM version of their tool called ChARM. */
-static
-void dotrace(SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
+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;
/*---------------------------------------------------------------------------*/
static void
-ColdReset (sd)
- SIM_DESC sd;
+ColdReset (SIM_DESC sd)
{
- /* RESET: Fixed PC address: */
- PC = UNSIGNED64 (0xFFFFFFFFBFC00000);
- /* The reset vector address is in the unmapped, uncached memory space. */
-
- SR &= ~(status_SR | status_TS | status_RP);
- SR |= (status_ERL | status_BEV);
-
- /* Cheat and allow access to the complete register set immediately */
- if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT
- && WITH_TARGET_WORD_BITSIZE == 64)
- SR |= status_FR; /* 64bit registers */
-
- /* Ensure that any instructions with pending register updates are
- cleared: */
- {
- int loop;
- for (loop = 0; (loop < PSLOTS); loop++)
- PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1);
- PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0;
- }
-
- /* Initialise the FPU registers to the unknown state */
- if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
+ int cpu_nr;
+ for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
{
- int rn;
- for (rn = 0; (rn < 32); rn++)
- FPR_STATE[rn] = fmt_uninterpreted;
- }
-
- return;
-}
-
-/* Description from page A-22 of the "MIPS IV Instruction Set" manual
- (revision 3.1) */
-/* Translate a virtual address to a physical address and cache
- coherence algorithm describing the mechanism used to resolve the
- memory reference. Given the virtual address vAddr, and whether the
- reference is to Instructions ot Data (IorD), find the corresponding
- physical address (pAddr) and the cache coherence algorithm (CCA)
- used to resolve the reference. If the virtual address is in one of
- the unmapped address spaces the physical address and the CCA are
- determined directly by the virtual address. If the virtual address
- is in one of the mapped address spaces then the TLB is used to
- determine the physical address and access type; if the required
- translation is not present in the TLB or the desired access is not
- permitted the function fails and an exception is taken.
-
- NOTE: Normally (RAW == 0), when address translation fails, this
- function raises an exception and does not return. */
-
-int
-address_translation(sd,vAddr,IorD,LorS,pAddr,CCA,host,raw)
- SIM_DESC sd;
- address_word vAddr;
- int IorD;
- int LorS;
- address_word *pAddr;
- int *CCA;
- int host;
- int raw;
-{
- int res = -1; /* TRUE : Assume good return */
-
-#ifdef DEBUG
- sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
-#endif
-
- /* Check that the address is valid for this memory model */
-
- /* For a simple (flat) memory model, we simply pass virtual
- addressess through (mostly) unchanged. */
- vAddr &= 0xFFFFFFFF;
-
- /* Treat the kernel memory spaces identically for the moment: */
- if ((STATE_MEM_BASE (sd) == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE)))
- vAddr += (K1BASE - K0BASE);
-
- /* Also assume that the K1BASE memory wraps. This is required to
- allow the PMON run-time __sizemem() routine to function (without
- having to provide exception simulation). NOTE: A kludge to work
- around the fact that the monitor memory is currently held in the
- K1BASE space. */
- if (((vAddr < monitor_base) || (vAddr >= (monitor_base + monitor_size))) && (vAddr >= K1BASE && vAddr < (K1BASE + K1SIZE)))
- vAddr = (K1BASE | (vAddr & (STATE_MEM_SIZE (sd) - 1)));
-
- *pAddr = vAddr; /* default for isTARGET */
- *CCA = Uncached; /* not used for isHOST */
-
- /* NOTE: This is a duplicate of the code that appears in the
- LoadMemory and StoreMemory functions. They should be merged into
- a single function (that can be in-lined if required). */
- if ((vAddr >= STATE_MEM_BASE (sd)) && (vAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) {
- if (host)
- *pAddr = (int)&STATE_MEMORY (sd)[((unsigned int)(vAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1))];
- } else if ((vAddr >= monitor_base) && (vAddr < (monitor_base + monitor_size))) {
- if (host)
- *pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
- } else {
-#ifdef DEBUG
- sim_io_eprintf(sd,"Failed: AddressTranslation(0x%s,%s,%s,...) IPC = 0x%s\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),pr_addr(IPC));
-#endif /* DEBUG */
- res = 0; /* AddressTranslation has failed */
- *pAddr = (SIM_ADDR)-1;
- if (!raw) /* only generate exceptions on real memory transfers */
- {
- if (IorD == isINSTRUCTION)
- SignalExceptionInstructionFetch ();
- else if (LorS == isSTORE)
- SignalExceptionAddressStore ();
- else
- SignalExceptionAddressLoad ();
- }
-#ifdef DEBUG
- else
- /* This is a normal occurance during gdb operation, for instance
- trying to print parameters at function start before they have
- been setup, and hence we should not print a warning except
- when debugging the simulator. */
- sim_io_eprintf(sd,"AddressTranslation for %s %s from 0x%s failed\n",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),pr_addr(vAddr));
-#endif
- }
-
- return(res);
-}
-
-/* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
-/* Prefetch data from memory. Prefetch is an advisory instruction for
- which an implementation specific action is taken. The action taken
- may increase performance, but must not change the meaning of the
- program, or alter architecturally-visible state. */
-
-void
-prefetch(sd,CCA,pAddr,vAddr,DATA,hint)
- SIM_DESC sd;
- int CCA;
- address_word pAddr;
- address_word vAddr;
- int DATA;
- int hint;
-{
-#ifdef DEBUG
- sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
-#endif /* DEBUG */
-
- /* For our simple memory model we do nothing */
- return;
-}
-
-/* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
-/* Load a value from memory. Use the cache and main memory as
- specified in the Cache Coherence Algorithm (CCA) and the sort of
- access (IorD) to find the contents of AccessLength memory bytes
- starting at physical location pAddr. The data is returned in the
- fixed width naturally-aligned memory element (MemElem). The
- low-order two (or three) bits of the address and the AccessLength
- indicate which of the bytes within MemElem needs to be given to the
- processor. If the memory access type of the reference is uncached
- then only the referenced bytes are read from memory and valid
- within the memory element. If the access type is cached, and the
- data is not present in cache, an implementation specific size and
- alignment block of memory is read and loaded into the cache to
- satisfy a load reference. At a minimum, the block is the entire
- memory element. */
-void
-load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
- SIM_DESC sd;
- uword64* memvalp;
- uword64* memval1p;
- int CCA;
- int AccessLength;
- address_word pAddr;
- address_word vAddr;
- int IorD;
- int raw;
-{
- uword64 value = 0;
- uword64 value1 = 0;
-
-#ifdef DEBUG
- if (STATE_MEMORY (sd) == NULL)
- sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL"));
-#endif /* DEBUG */
-
-#if defined(WARN_MEM)
- if (CCA != uncached)
- sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
-
- if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
- /* In reality this should be a Bus Error */
- sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
- }
-#endif /* WARN_MEM */
-
- /* Decide which physical memory locations are being dealt with. At
- this point we should be able to split the pAddr bits into the
- relevant address map being simulated. If the "raw" variable is
- set, the memory read being performed should *NOT* update any I/O
- state or affect the CPU state. This also includes avoiding
- affecting statistics gathering. */
-
- /* If instruction fetch then we need to check that the two lo-order
- bits are zero, otherwise raise a InstructionFetch exception: */
- if ((IorD == isINSTRUCTION)
- && ((pAddr & 0x3) != 0)
- && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
- SignalExceptionInstructionFetch ();
- else {
- unsigned int index = 0;
- unsigned char *mem = NULL;
-
-#if defined(TRACE)
- if (!raw)
- dotrace(sd,tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
-#endif /* TRACE */
-
- /* NOTE: Quicker methods of decoding the address space can be used
- when a real memory map is being simulated (i.e. using hi-order
- address bits to select device). */
- if ((pAddr >= STATE_MEM_BASE (sd)) && (pAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) {
- index = ((unsigned int)(pAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1));
- mem = STATE_MEMORY (sd);
- } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
- index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
- mem = monitor;
- }
- if (mem == NULL)
- sim_io_error(sd,"Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
- else {
- /* If we obtained the endianness of the host, and it is the same
- as the target memory system we can optimise the memory
- accesses. However, without that information we must perform
- slow transfer, and hope that the compiler optimisation will
- merge successive loads. */
-
- /* In reality we should always be loading a doubleword value (or
- word value in 32bit memory worlds). The external code then
- extracts the required bytes. However, to keep performance
- high we only load the required bytes into the relevant
- slots. */
- if (BigEndianMem)
- switch (AccessLength) { /* big-endian memory */
- case AccessLength_QUADWORD :
- value1 |= ((uword64)mem[index++] << 56);
- case 14: /* AccessLength is one less than datalen */
- value1 |= ((uword64)mem[index++] << 48);
- case 13:
- value1 |= ((uword64)mem[index++] << 40);
- case 12:
- value1 |= ((uword64)mem[index++] << 32);
- case 11:
- value1 |= ((unsigned int)mem[index++] << 24);
- case 10:
- value1 |= ((unsigned int)mem[index++] << 16);
- case 9:
- value1 |= ((unsigned int)mem[index++] << 8);
- case 8:
- value1 |= mem[index];
-
- case AccessLength_DOUBLEWORD :
- value |= ((uword64)mem[index++] << 56);
- case AccessLength_SEPTIBYTE :
- value |= ((uword64)mem[index++] << 48);
- case AccessLength_SEXTIBYTE :
- value |= ((uword64)mem[index++] << 40);
- case AccessLength_QUINTIBYTE :
- value |= ((uword64)mem[index++] << 32);
- case AccessLength_WORD :
- value |= ((unsigned int)mem[index++] << 24);
- case AccessLength_TRIPLEBYTE :
- value |= ((unsigned int)mem[index++] << 16);
- case AccessLength_HALFWORD :
- value |= ((unsigned int)mem[index++] << 8);
- case AccessLength_BYTE :
- value |= mem[index];
- break;
- }
- else {
- index += (AccessLength + 1);
- switch (AccessLength) { /* little-endian memory */
- case AccessLength_QUADWORD :
- value1 |= ((uword64)mem[--index] << 56);
- case 14: /* AccessLength is one less than datalen */
- value1 |= ((uword64)mem[--index] << 48);
- case 13:
- value1 |= ((uword64)mem[--index] << 40);
- case 12:
- value1 |= ((uword64)mem[--index] << 32);
- case 11:
- value1 |= ((uword64)mem[--index] << 24);
- case 10:
- value1 |= ((uword64)mem[--index] << 16);
- case 9:
- value1 |= ((uword64)mem[--index] << 8);
- case 8:
- value1 |= ((uword64)mem[--index] << 0);
-
- case AccessLength_DOUBLEWORD :
- value |= ((uword64)mem[--index] << 56);
- case AccessLength_SEPTIBYTE :
- value |= ((uword64)mem[--index] << 48);
- case AccessLength_SEXTIBYTE :
- value |= ((uword64)mem[--index] << 40);
- case AccessLength_QUINTIBYTE :
- value |= ((uword64)mem[--index] << 32);
- case AccessLength_WORD :
- value |= ((uword64)mem[--index] << 24);
- case AccessLength_TRIPLEBYTE :
- value |= ((uword64)mem[--index] << 16);
- case AccessLength_HALFWORD :
- value |= ((uword64)mem[--index] << 8);
- case AccessLength_BYTE :
- value |= ((uword64)mem[--index] << 0);
- break;
- }
- }
-
-#ifdef DEBUG
- printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
- (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
-#endif /* DEBUG */
-
- /* TODO: We could try and avoid the shifts when dealing with raw
- memory accesses. This would mean updating the LoadMemory and
- StoreMemory routines to avoid shifting the data before
- returning or using it. */
- if (AccessLength <= AccessLength_DOUBLEWORD) {
- if (!raw) { /* do nothing for raw accessess */
- if (BigEndianMem)
- value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
- else /* little-endian only needs to be shifted up to the correct byte offset */
- value <<= ((pAddr & LOADDRMASK) * 8);
- }
- }
-
-#ifdef DEBUG
- printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
- pr_uword64(value1),pr_uword64(value));
-#endif /* DEBUG */
- }
- }
-
-*memvalp = value;
-if (memval1p) *memval1p = value1;
-}
-
-
-/* Description from page A-23 of the "MIPS IV Instruction Set" manual
- (revision 3.1) */
-/* Store a value to memory. The specified data is stored into the
- physical location pAddr using the memory hierarchy (data caches and
- main memory) as specified by the Cache Coherence Algorithm
- (CCA). The MemElem contains the data for an aligned, fixed-width
- memory element (word for 32-bit processors, doubleword for 64-bit
- processors), though only the bytes that will actually be stored to
- memory need to be valid. The low-order two (or three) bits of pAddr
- and the AccessLength field indicates which of the bytes within the
- MemElem data should actually be stored; only these bytes in memory
- will be changed. */
-
-void
-store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
- SIM_DESC sd;
- int CCA;
- int AccessLength;
- uword64 MemElem;
- uword64 MemElem1; /* High order 64 bits */
- address_word pAddr;
- address_word vAddr;
- int raw;
-{
-#ifdef DEBUG
- sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s,%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr),(raw ? "isRAW" : "isREAL"));
-#endif /* DEBUG */
-
-#if defined(WARN_MEM)
- if (CCA != uncached)
- sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
-
- if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
- sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
-#endif /* WARN_MEM */
-
-#if defined(TRACE)
- if (!raw)
- dotrace(sd,tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
-#endif /* TRACE */
-
- /* See the comments in the LoadMemory routine about optimising
- memory accesses. Also if we wanted to make the simulator smaller,
- we could merge a lot of this code with the LoadMemory
- routine. However, this would slow the simulator down with
- run-time conditionals. */
- {
- unsigned int index = 0;
- unsigned char *mem = NULL;
-
- if ((pAddr >= STATE_MEM_BASE (sd)) && (pAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) {
- index = ((unsigned int)(pAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1));
- mem = STATE_MEMORY (sd);
- } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
- index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
- mem = monitor;
- }
-
- if (mem == NULL)
- sim_io_error(sd,"Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
- else {
- int shift = 0;
-
-#ifdef DEBUG
- printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
-#endif /* DEBUG */
-
- if (AccessLength <= AccessLength_DOUBLEWORD) {
- if (BigEndianMem) {
- if (raw)
- shift = ((7 - AccessLength) * 8);
- else /* real memory access */
- shift = ((pAddr & LOADDRMASK) * 8);
- MemElem <<= shift;
- } else {
- /* no need to shift raw little-endian data */
- if (!raw)
- MemElem >>= ((pAddr & LOADDRMASK) * 8);
- }
- }
-
-#ifdef DEBUG
- printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
-#endif /* DEBUG */
-
- if (BigEndianMem) {
- switch (AccessLength) { /* big-endian memory */
- case AccessLength_QUADWORD :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 14 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 13 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 12 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 11 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 10 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 9 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
- MemElem1 <<= 8;
- case 8 :
- mem[index++] = (unsigned char)(MemElem1 >> 56);
-
- case AccessLength_DOUBLEWORD :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_SEPTIBYTE :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_SEXTIBYTE :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_QUINTIBYTE :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_WORD :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_TRIPLEBYTE :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_HALFWORD :
- mem[index++] = (unsigned char)(MemElem >> 56);
- MemElem <<= 8;
- case AccessLength_BYTE :
- mem[index++] = (unsigned char)(MemElem >> 56);
- break;
- }
- } else {
- index += (AccessLength + 1);
- switch (AccessLength) { /* little-endian memory */
- case AccessLength_QUADWORD :
- mem[--index] = (unsigned char)(MemElem1 >> 56);
- case 14 :
- mem[--index] = (unsigned char)(MemElem1 >> 48);
- case 13 :
- mem[--index] = (unsigned char)(MemElem1 >> 40);
- case 12 :
- mem[--index] = (unsigned char)(MemElem1 >> 32);
- case 11 :
- mem[--index] = (unsigned char)(MemElem1 >> 24);
- case 10 :
- mem[--index] = (unsigned char)(MemElem1 >> 16);
- case 9 :
- mem[--index] = (unsigned char)(MemElem1 >> 8);
- case 8 :
- mem[--index] = (unsigned char)(MemElem1 >> 0);
-
- case AccessLength_DOUBLEWORD :
- mem[--index] = (unsigned char)(MemElem >> 56);
- case AccessLength_SEPTIBYTE :
- mem[--index] = (unsigned char)(MemElem >> 48);
- case AccessLength_SEXTIBYTE :
- mem[--index] = (unsigned char)(MemElem >> 40);
- case AccessLength_QUINTIBYTE :
- mem[--index] = (unsigned char)(MemElem >> 32);
- case AccessLength_WORD :
- mem[--index] = (unsigned char)(MemElem >> 24);
- case AccessLength_TRIPLEBYTE :
- mem[--index] = (unsigned char)(MemElem >> 16);
- case AccessLength_HALFWORD :
- mem[--index] = (unsigned char)(MemElem >> 8);
- case AccessLength_BYTE :
- mem[--index] = (unsigned char)(MemElem >> 0);
- break;
- }
- }
+ sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
+ /* RESET: Fixed PC address: */
+ PC = UNSIGNED64 (0xFFFFFFFFBFC00000);
+ /* The reset vector address is in the unmapped, uncached memory space. */
+
+ SR &= ~(status_SR | status_TS | status_RP);
+ SR |= (status_ERL | status_BEV);
+
+ /* Cheat and allow access to the complete register set immediately */
+ if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT
+ && WITH_TARGET_WORD_BITSIZE == 64)
+ SR |= status_FR; /* 64bit registers */
+
+ /* Ensure that any instructions with pending register updates are
+ cleared: */
+ PENDING_INVALIDATE();
+
+ /* Initialise the FPU registers to the unknown state */
+ if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
+ {
+ int rn;
+ for (rn = 0; (rn < 32); rn++)
+ FPR_STATE[rn] = fmt_uninterpreted;
+ }
+
}
- }
-
- return;
-}
-
-
-unsigned32
-ifetch32 (SIM_DESC sd, address_word vaddr)
-{
- /* Copy the action of the LW instruction */
- address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
- address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
- unsigned64 value;
- address_word paddr;
- unsigned32 instruction;
- unsigned byte;
- int cca;
- AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL);
- paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
- LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL);
- byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
- instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
- return instruction;
-}
-
-
-/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
-/* Order loads and stores to synchronise shared memory. Perform the
- action necessary to make the effects of groups of synchronizable
- loads and stores indicated by stype occur in the same order for all
- processors. */
-void
-sync_operation(sd,stype)
- SIM_DESC sd;
- int stype;
-{
-#ifdef DEBUG
- sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
-#endif /* DEBUG */
- return;
}
/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
will never see a return from this function call. */
void
-signal_exception (SIM_DESC sd, int exception,...)
+signal_exception (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int exception,...)
{
int vector;
#ifdef DEBUG
- sim_io_printf(sd,"DBG: SignalException(%d) IPC = 0x%s\n",exception,pr_addr(IPC));
+ sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
#endif /* DEBUG */
/* Ensure that any active atomic read/modify/write operation will fail: */
ignore them at run-time.
Same for SYSCALL */
case Trap :
- sim_io_eprintf(sd,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(IPC));
+ sim_io_eprintf(sd,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(cia));
break;
case SystemCall :
code = (instruction >> 6) & 0xFFFFF;
sim_io_eprintf(sd,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
- code, pr_addr(IPC));
+ code, pr_addr(cia));
}
break;
CANCELDELAYSLOT();
Debug |= Debug_DBD; /* signaled from within in delay slot */
- DEPC = IPC - 4; /* reference the branch instruction */
+ DEPC = cia - 4; /* reference the branch instruction */
}
else
{
Debug &= ~Debug_DBD; /* not signaled from within a delay slot */
- DEPC = IPC;
+ DEPC = cia;
}
Debug |= Debug_DM; /* in debugging mode */
Debug |= Debug_DBp; /* raising a DBp exception */
PC = 0xBFC00200;
- sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA);
+ sim_engine_restart (SD, CPU, NULL, NULL_CIA);
}
break;
space with suitable instruction values. For systems were
actual trap instructions are used, we would not need to
perform this magic. */
- if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION) {
- sim_monitor(sd, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
- PC = RA; /* simulate the return from the vector entry */
- /* NOTE: This assumes that a branch-and-link style
- instruction was used to enter the vector (which is the
- case with the current IDT monitor). */
- sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA);
- }
+ if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
+ {
+ sim_monitor (SD, CPU, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
+ /* NOTE: This assumes that a branch-and-link style
+ instruction was used to enter the vector (which is the
+ case with the current IDT monitor). */
+ sim_engine_restart (SD, CPU, NULL, RA);
+ }
/* Look for the mips16 entry and exit instructions, and
simulate a handler for them. */
- else if ((IPC & 1) != 0
+ else if ((cia & 1) != 0
&& (instruction & 0xf81f) == 0xe809
- && (instruction & 0x0c0) != 0x0c0) {
- mips16_entry (instruction);
- sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA);
- } /* else fall through to normal exception processing */
- sim_io_eprintf(sd,"ReservedInstruction 0x%08X at IPC = 0x%s\n",instruction,pr_addr(IPC));
+ && (instruction & 0x0c0) != 0x0c0)
+ {
+ mips16_entry (SD, CPU, cia, instruction);
+ sim_engine_restart (sd, NULL, NULL, NULL_CIA);
+ }
+ /* else fall through to normal exception processing */
+ sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
}
case BreakPoint:
#ifdef DEBUG
- sim_io_printf(sd,"DBG: SignalException(%d) IPC = 0x%s\n",exception,pr_addr(IPC));
+ sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
#endif /* DEBUG */
/* Keep a copy of the current A0 in-case this is the program exit
breakpoint: */
va_end(ap);
/* Check for our special terminating BREAK: */
if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
+ sim_engine_halt (SD, CPU, NULL, cia,
sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
}
}
if (STATE & simDELAYSLOT)
- PC = IPC - 4; /* reference the branch instruction */
+ PC = cia - 4; /* reference the branch instruction */
else
- PC = IPC;
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGTRAP);
+ PC = cia;
+ sim_engine_halt (SD, CPU, NULL, cia,
+ sim_stopped, SIM_SIGTRAP);
default:
/* Store exception code into current exception id variable (used
{
STATE &= ~simDELAYSLOT;
CAUSE |= cause_BD;
- EPC = (IPC - 4); /* reference the branch instruction */
+ EPC = (cia - 4); /* reference the branch instruction */
}
else
- EPC = IPC;
+ EPC = cia;
/* FIXME: TLB et.al. */
vector = 0x180;
}
/* The following is so that the simulator will continue from the
exception address on breakpoint operations. */
PC = EPC;
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGBUS);
+ sim_engine_halt (SD, CPU, NULL, NULL_CIA,
+ sim_stopped, SIM_SIGBUS);
case ReservedInstruction:
case CoProcessorUnusable:
PC = EPC;
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGILL);
+ sim_engine_halt (SD, CPU, NULL, NULL_CIA,
+ sim_stopped, SIM_SIGILL);
case IntegerOverflow:
case FPE:
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGFPE);
+ sim_engine_halt (SD, CPU, NULL, NULL_CIA,
+ sim_stopped, SIM_SIGFPE);
case Trap:
case Watch:
case SystemCall:
PC = EPC;
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGTRAP);
+ sim_engine_halt (SD, CPU, NULL, NULL_CIA,
+ sim_stopped, SIM_SIGTRAP);
case BreakPoint:
PC = EPC;
- sim_engine_abort (sd, STATE_CPU (sd, 0), NULL_CIA,
+ sim_engine_abort (SD, CPU, NULL_CIA,
"FATAL: Should not encounter a breakpoint\n");
default : /* Unknown internal exception */
PC = EPC;
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGQUIT);
+ sim_engine_halt (SD, CPU, NULL, NULL_CIA,
+ sim_stopped, SIM_SIGABRT);
}
va_start(ap,exception);
msg = va_arg(ap,char *);
va_end(ap);
- sim_engine_abort (sd, STATE_CPU (sd, 0), NULL_CIA,
+ sim_engine_abort (SD, CPU, NULL_CIA,
"FATAL: Simulator error \"%s\"\n",msg);
}
}
simple, we just don't bother updating the destination register, so
the overall result will be undefined. If desired we can stop the
simulator by raising a pseudo-exception. */
+#define UndefinedResult() undefined_result (sd,cia)
static void
-UndefinedResult()
+undefined_result(sd,cia)
+ SIM_DESC sd;
+ address_word cia;
{
- sim_io_eprintf(sd,"UndefinedResult: IPC = 0x%s\n",pr_addr(IPC));
+ sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia));
#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
state |= simSTOP;
#endif
}
#endif /* WARN_RESULT */
-void
-cache_op(sd,op,pAddr,vAddr,instruction)
- SIM_DESC sd;
- int op;
- address_word pAddr;
- address_word vAddr;
- unsigned int instruction;
-{
-#if 1 /* stop warning message being displayed (we should really just remove the code) */
- static int icache_warning = 1;
- static int dcache_warning = 1;
-#else
- static int icache_warning = 0;
- static int dcache_warning = 0;
-#endif
-
- /* If CP0 is not useable (User or Supervisor mode) and the CP0
- enable bit in the Status Register is clear - a coprocessor
- unusable exception is taken. */
-#if 0
- sim_io_printf(sd,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(IPC));
-#endif
-
- switch (op & 0x3) {
- case 0: /* instruction cache */
- switch (op >> 2) {
- case 0: /* Index Invalidate */
- case 1: /* Index Load Tag */
- case 2: /* Index Store Tag */
- case 4: /* Hit Invalidate */
- case 5: /* Fill */
- case 6: /* Hit Writeback */
- if (!icache_warning)
- {
- sim_io_eprintf(sd,"Instruction CACHE operation %d to be coded\n",(op >> 2));
- icache_warning = 1;
- }
- break;
-
- default:
- SignalException(ReservedInstruction,instruction);
- break;
- }
- break;
-
- case 1: /* data cache */
- switch (op >> 2) {
- case 0: /* Index Writeback Invalidate */
- case 1: /* Index Load Tag */
- case 2: /* Index Store Tag */
- case 3: /* Create Dirty */
- case 4: /* Hit Invalidate */
- case 5: /* Hit Writeback Invalidate */
- case 6: /* Hit Writeback */
- if (!dcache_warning)
- {
- sim_io_eprintf(sd,"Data CACHE operation %d to be coded\n",(op >> 2));
- dcache_warning = 1;
- }
- break;
-
- default:
- SignalException(ReservedInstruction,instruction);
- break;
- }
- break;
-
- default: /* unrecognised cache ID */
- SignalException(ReservedInstruction,instruction);
- break;
- }
-
- return;
-}
-
/*-- FPU support routines ---------------------------------------------------*/
-#if defined(HASFPU) /* Only needed when building FPU aware simulators */
-
/* Numbers are held in normalized form. The SINGLE and DOUBLE binary
formats conform to ANSI/IEEE Std 754-1985. */
/* SINGLE precision floating:
#endif /* DEBUG */
uword64
-value_fpr(sd,fpr,fmt)
- SIM_DESC sd;
- int fpr;
- FP_formats fmt;
+value_fpr (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int fpr,
+ FP_formats fmt)
{
uword64 value = 0;
int err = 0;
#endif /* DEBUG */
}
if (fmt != FPR_STATE[fpr]) {
- sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(IPC));
+ sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia));
FPR_STATE[fpr] = fmt_unknown;
}
SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
#ifdef DEBUG
- printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(IPC),SizeFGR());
+ printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(cia),SizeFGR());
#endif /* DEBUG */
return(value);
}
void
-store_fpr(sd,fpr,fmt,value)
- SIM_DESC sd;
- int fpr;
- FP_formats fmt;
- uword64 value;
+store_fpr (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int fpr,
+ FP_formats fmt,
+ uword64 value)
{
int err = 0;
#ifdef DEBUG
- printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(IPC),SizeFGR());
+ printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(cia),SizeFGR());
#endif /* DEBUG */
if (SizeFGR() == 64) {
switch (fmt) {
+ case fmt_uninterpreted_32:
+ fmt = fmt_uninterpreted;
case fmt_single :
case fmt_word :
FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
FPR_STATE[fpr] = fmt;
break;
+ case fmt_uninterpreted_64:
+ fmt = fmt_uninterpreted;
case fmt_uninterpreted:
case fmt_double :
case fmt_long :
}
} else {
switch (fmt) {
+ case fmt_uninterpreted_32:
+ fmt = fmt_uninterpreted;
case fmt_single :
case fmt_word :
FGR[fpr] = (value & 0xFFFFFFFF);
FPR_STATE[fpr] = fmt;
break;
+ case fmt_uninterpreted_64:
+ fmt = fmt_uninterpreted;
case fmt_uninterpreted:
case fmt_double :
case fmt_long :
FP_formats fmt;
{
int boolean = 0;
-
- /* Check if (((E - bias) == (E_max + 1)) && (fraction != 0)). We
- know that the exponent field is biased... we we cheat and avoid
- removing the bias value. */
switch (fmt) {
case fmt_single:
- boolean = ((FP_S_be(op) == 0xFF) && (FP_S_f(op) != 0));
- /* We could use "FP_S_fb(1,op)" to ascertain whether we are
- dealing with a SNaN or QNaN */
- break;
- case fmt_double:
- boolean = ((FP_D_be(op) == 0x7FF) && (FP_D_f(op) != 0));
- /* We could use "FP_S_fb(1,op)" to ascertain whether we are
- dealing with a SNaN or QNaN */
- break;
case fmt_word:
- boolean = (op == FPQNaN_WORD);
- break;
+ {
+ sim_fpu wop;
+ sim_fpu_32to (&wop, op);
+ boolean = sim_fpu_is_nan (&wop);
+ break;
+ }
+ case fmt_double:
case fmt_long:
- boolean = (op == FPQNaN_LONG);
- break;
+ {
+ sim_fpu wop;
+ sim_fpu_64to (&wop, op);
+ boolean = sim_fpu_is_nan (&wop);
+ break;
+ }
default:
fprintf (stderr, "Bad switch\n");
abort ();
int boolean = 0;
#ifdef DEBUG
- printf("DBG: Infinity: format %s 0x%s (PC = 0x%s)\n",DOFMT(fmt),pr_addr(op),pr_addr(IPC));
+ printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
#endif /* DEBUG */
- /* Check if (((E - bias) == (E_max + 1)) && (fraction == 0)). We
- know that the exponent field is biased... we we cheat and avoid
- removing the bias value. */
switch (fmt) {
case fmt_single:
- boolean = ((FP_S_be(op) == 0xFF) && (FP_S_f(op) == 0));
- break;
+ {
+ sim_fpu wop;
+ sim_fpu_32to (&wop, op);
+ boolean = sim_fpu_is_infinity (&wop);
+ break;
+ }
case fmt_double:
- boolean = ((FP_D_be(op) == 0x7FF) && (FP_D_f(op) == 0));
- break;
+ {
+ sim_fpu wop;
+ sim_fpu_64to (&wop, op);
+ boolean = sim_fpu_is_infinity (&wop);
+ break;
+ }
default:
printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
break;
switch (fmt) {
case fmt_single:
{
- unsigned int wop1 = (unsigned int)op1;
- unsigned int wop2 = (unsigned int)op2;
- boolean = (*(float *)&wop1 < *(float *)&wop2);
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ boolean = sim_fpu_is_lt (&wop1, &wop2);
+ break;
}
- break;
case fmt_double:
- boolean = (*(double *)&op1 < *(double *)&op2);
- break;
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ boolean = sim_fpu_is_lt (&wop1, &wop2);
+ break;
+ }
default:
fprintf (stderr, "Bad switch\n");
abort ();
/* The format type should already have been checked: */
switch (fmt) {
case fmt_single:
- boolean = ((op1 & 0xFFFFFFFF) == (op2 & 0xFFFFFFFF));
- break;
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ boolean = sim_fpu_is_eq (&wop1, &wop2);
+ break;
+ }
case fmt_double:
- boolean = (op1 == op2);
- break;
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ boolean = sim_fpu_is_eq (&wop1, &wop2);
+ break;
+ }
default:
fprintf (stderr, "Bad switch\n");
abort ();
switch (fmt) {
case fmt_single:
{
- unsigned int wop = (unsigned int)op;
- float tmp = ((float)fabs((double)*(float *)&wop));
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop;
+ unsigned32 ans;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_abs (&wop, &wop);
+ sim_fpu_to32 (&ans, &wop);
+ result = ans;
+ break;
}
- break;
case fmt_double:
{
- double tmp = (fabs(*(double *)&op));
- result = *(uword64 *)&tmp;
+ sim_fpu wop;
+ unsigned64 ans;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_abs (&wop, &wop);
+ sim_fpu_to64 (&ans, &wop);
+ result = ans;
+ break;
}
default:
fprintf (stderr, "Bad switch\n");
switch (fmt) {
case fmt_single:
{
- unsigned int wop = (unsigned int)op;
- float tmp = ((float)0.0 - *(float *)&wop);
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop;
+ unsigned32 ans;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_neg (&wop, &wop);
+ sim_fpu_to32 (&ans, &wop);
+ result = ans;
+ break;
}
- break;
case fmt_double:
{
- double tmp = ((double)0.0 - *(double *)&op);
- result = *(uword64 *)&tmp;
+ sim_fpu wop;
+ unsigned64 ans;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_neg (&wop, &wop);
+ sim_fpu_to64 (&ans, &wop);
+ result = ans;
+ break;
}
- break;
default:
fprintf (stderr, "Bad switch\n");
abort ();
switch (fmt) {
case fmt_single:
{
- unsigned int wop1 = (unsigned int)op1;
- unsigned int wop2 = (unsigned int)op2;
- float tmp = (*(float *)&wop1 + *(float *)&wop2);
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_add (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
}
- break;
case fmt_double:
{
- double tmp = (*(double *)&op1 + *(double *)&op2);
- result = *(uword64 *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_add (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
}
- break;
default:
fprintf (stderr, "Bad switch\n");
abort ();
switch (fmt) {
case fmt_single:
{
- unsigned int wop1 = (unsigned int)op1;
- unsigned int wop2 = (unsigned int)op2;
- float tmp = (*(float *)&wop1 - *(float *)&wop2);
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_sub (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
}
break;
case fmt_double:
{
- double tmp = (*(double *)&op1 - *(double *)&op2);
- result = *(uword64 *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_sub (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
}
break;
default:
switch (fmt) {
case fmt_single:
{
- unsigned int wop1 = (unsigned int)op1;
- unsigned int wop2 = (unsigned int)op2;
- float tmp = (*(float *)&wop1 * *(float *)&wop2);
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_mul (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
}
- break;
case fmt_double:
{
- double tmp = (*(double *)&op1 * *(double *)&op2);
- result = *(uword64 *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_mul (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
}
- break;
default:
fprintf (stderr, "Bad switch\n");
abort ();
switch (fmt) {
case fmt_single:
{
- unsigned int wop1 = (unsigned int)op1;
- unsigned int wop2 = (unsigned int)op2;
- float tmp = (*(float *)&wop1 / *(float *)&wop2);
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ sim_fpu_div (&ans, &wop1, &wop2);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
}
- break;
case fmt_double:
{
- double tmp = (*(double *)&op1 / *(double *)&op2);
- result = *(uword64 *)&tmp;
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ sim_fpu_div (&ans, &wop1, &wop2);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
}
- break;
default:
fprintf (stderr, "Bad switch\n");
abort ();
switch (fmt) {
case fmt_single:
{
- unsigned int wop = (unsigned int)op;
- float tmp = ((float)1.0 / *(float *)&wop);
- result = (uword64)*(unsigned int *)&tmp;
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_inv (&ans, &wop);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
}
- break;
case fmt_double:
{
- double tmp = ((double)1.0 / *(double *)&op);
- result = *(uword64 *)&tmp;
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_inv (&ans, &wop);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
}
- break;
default:
fprintf (stderr, "Bad switch\n");
abort ();
switch (fmt) {
case fmt_single:
{
- unsigned int wop = (unsigned int)op;
-#ifdef HAVE_SQRT
- float tmp = ((float)sqrt((double)*(float *)&wop));
- result = (uword64)*(unsigned int *)&tmp;
-#else
- /* TODO: Provide square-root */
- result = (uword64)0;
-#endif
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned32 res;
+ sim_fpu_32to (&wop, op);
+ sim_fpu_sqrt (&ans, &wop);
+ sim_fpu_to32 (&res, &ans);
+ result = res;
+ break;
}
- break;
case fmt_double:
{
-#ifdef HAVE_SQRT
- double tmp = (sqrt(*(double *)&op));
- result = *(uword64 *)&tmp;
-#else
- /* TODO: Provide square-root */
- result = (uword64)0;
-#endif
+ sim_fpu wop;
+ sim_fpu ans;
+ unsigned64 res;
+ sim_fpu_64to (&wop, op);
+ sim_fpu_sqrt (&ans, &wop);
+ sim_fpu_to64 (&res, &ans);
+ result = res;
+ break;
}
- break;
default:
fprintf (stderr, "Bad switch\n");
abort ();
return(result);
}
+#if 0
uword64
-convert(sd,rm,op,from,to)
- SIM_DESC sd;
- int rm;
- uword64 op;
- FP_formats from;
- FP_formats to;
+Max (uword64 op1,
+ uword64 op2,
+ FP_formats fmt)
{
- uword64 result = 0;
+ int cmp;
+ unsigned64 result;
#ifdef DEBUG
- printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC));
+ printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
#endif /* DEBUG */
- /* The value "op" is converted to the destination format, rounding
- using mode "rm". When the destination is a fixed-point format,
- then a source value of Infinity, NaN or one which would round to
- an integer outside the fixed point range then an IEEE Invalid
- Operation condition is raised. */
- switch (to) {
- case fmt_single:
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
+
+ /* The format type should already have been checked: */
+ switch (fmt)
{
- float tmp;
- switch (from) {
- case fmt_double:
- tmp = (float)(*(double *)&op);
- break;
-
- case fmt_word:
- tmp = (float)((int)(op & 0xFFFFFFFF));
- break;
-
- case fmt_long:
- tmp = (float)((word64)op);
- break;
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
}
-
-#if 0
- /* FIXME: This code is incorrect. The rounding mode does not
- round to integral values; it rounds to the nearest
- representable value in the format. */
-
- switch (rm) {
- case FP_RM_NEAREST:
- /* Round result to nearest representable value. When two
- representable values are equally near, round to the value
- that has a least significant bit of zero (i.e. is even). */
-#ifdef HAVE_ANINT
- tmp = (float)anint((double)tmp);
-#else
- /* TODO: Provide round-to-nearest */
-#endif
- break;
-
- case FP_RM_TOZERO:
- /* Round result to the value closest to, and not greater in
- magnitude than, the result. */
-#ifdef HAVE_AINT
- tmp = (float)aint((double)tmp);
-#else
- /* TODO: Provide round-to-zero */
-#endif
- break;
-
- case FP_RM_TOPINF:
- /* Round result to the value closest to, and not less than,
- the result. */
- tmp = (float)ceil((double)tmp);
- break;
-
- case FP_RM_TOMINF:
- /* Round result to the value closest to, and not greater than,
- the result. */
- tmp = (float)floor((double)tmp);
- break;
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
}
-#endif /* 0 */
-
- result = (uword64)*(unsigned int *)&tmp;
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
}
- break;
-
- case fmt_double:
+
+ switch (cmp)
{
- double tmp;
- word64 xxx;
-
- switch (from) {
- case fmt_single:
- {
- unsigned int wop = (unsigned int)op;
- tmp = (double)(*(float *)&wop);
- }
- break;
-
- case fmt_word:
- xxx = SIGNEXTEND((op & 0xFFFFFFFF),32);
- tmp = (double)xxx;
- break;
+ case SIM_FPU_IS_SNAN:
+ case SIM_FPU_IS_QNAN:
+ result = op1;
+ case SIM_FPU_IS_NINF:
+ case SIM_FPU_IS_NNUMBER:
+ case SIM_FPU_IS_NDENORM:
+ case SIM_FPU_IS_NZERO:
+ result = op2; /* op1 - op2 < 0 */
+ case SIM_FPU_IS_PINF:
+ case SIM_FPU_IS_PNUMBER:
+ case SIM_FPU_IS_PDENORM:
+ case SIM_FPU_IS_PZERO:
+ result = op1; /* op1 - op2 > 0 */
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
- case fmt_long:
- tmp = (double)((word64)op);
- break;
+#ifdef DEBUG
+ printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
+#endif /* DEBUG */
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
+ return(result);
+}
+#endif
#if 0
- /* FIXME: This code is incorrect. The rounding mode does not
- round to integral values; it rounds to the nearest
- representable value in the format. */
-
- switch (rm) {
- case FP_RM_NEAREST:
-#ifdef HAVE_ANINT
- tmp = anint(*(double *)&tmp);
-#else
- /* TODO: Provide round-to-nearest */
-#endif
- break;
+uword64
+Min (uword64 op1,
+ uword64 op2,
+ FP_formats fmt)
+{
+ int cmp;
+ unsigned64 result;
- case FP_RM_TOZERO:
-#ifdef HAVE_AINT
- tmp = aint(*(double *)&tmp);
-#else
- /* TODO: Provide round-to-zero */
-#endif
- break;
+#ifdef DEBUG
+ printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
+#endif /* DEBUG */
- case FP_RM_TOPINF:
- tmp = ceil(*(double *)&tmp);
- break;
+ /* The registers must specify FPRs valid for operands of type
+ "fmt". If they are not valid, the result is undefined. */
- case FP_RM_TOMINF:
- tmp = floor(*(double *)&tmp);
- break;
+ /* The format type should already have been checked: */
+ switch (fmt)
+ {
+ case fmt_single:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_32to (&wop1, op1);
+ sim_fpu_32to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
}
-#endif /* 0 */
-
- result = *(uword64 *)&tmp;
+ case fmt_double:
+ {
+ sim_fpu wop1;
+ sim_fpu wop2;
+ sim_fpu_64to (&wop1, op1);
+ sim_fpu_64to (&wop2, op2);
+ cmp = sim_fpu_cmp (&wop1, &wop2);
+ break;
+ }
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ switch (cmp)
+ {
+ case SIM_FPU_IS_SNAN:
+ case SIM_FPU_IS_QNAN:
+ result = op1;
+ case SIM_FPU_IS_NINF:
+ case SIM_FPU_IS_NNUMBER:
+ case SIM_FPU_IS_NDENORM:
+ case SIM_FPU_IS_NZERO:
+ result = op1; /* op1 - op2 < 0 */
+ case SIM_FPU_IS_PINF:
+ case SIM_FPU_IS_PNUMBER:
+ case SIM_FPU_IS_PDENORM:
+ case SIM_FPU_IS_PZERO:
+ result = op2; /* op1 - op2 > 0 */
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
}
- break;
- case fmt_word:
- case fmt_long:
- if (Infinity(op,from) || NaN(op,from) || (1 == 0/*TODO: check range */)) {
- printf("DBG: TODO: update FCSR\n");
- SignalExceptionFPE ();
- } else {
- if (to == fmt_word) {
- int tmp = 0;
- switch (from) {
- case fmt_single:
- {
- unsigned int wop = (unsigned int)op;
- tmp = (int)*((float *)&wop);
- }
- break;
- case fmt_double:
- tmp = (int)*((double *)&op);
#ifdef DEBUG
- printf("DBG: from double %.30f (0x%s) to word: 0x%08X\n",*((double *)&op),pr_addr(op),tmp);
+ printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
#endif /* DEBUG */
- break;
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
- result = (uword64)tmp;
- } else { /* fmt_long */
- word64 tmp = 0;
- switch (from) {
- case fmt_single:
- {
- unsigned int wop = (unsigned int)op;
- tmp = (word64)*((float *)&wop);
- }
- break;
- case fmt_double:
- tmp = (word64)*((double *)&op);
- break;
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
- result = (uword64)tmp;
- }
+
+ return(result);
+}
+#endif
+
+uword64
+convert (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int rm,
+ uword64 op,
+ FP_formats from,
+ FP_formats to)
+{
+ sim_fpu wop;
+ sim_fpu_round round;
+ unsigned32 result32;
+ unsigned64 result64;
+
+#ifdef DEBUG
+ printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC));
+#endif /* DEBUG */
+
+ switch (rm)
+ {
+ case FP_RM_NEAREST:
+ /* Round result to nearest representable value. When two
+ representable values are equally near, round to the value
+ that has a least significant bit of zero (i.e. is even). */
+ round = sim_fpu_round_near;
+ break;
+ case FP_RM_TOZERO:
+ /* Round result to the value closest to, and not greater in
+ magnitude than, the result. */
+ round = sim_fpu_round_zero;
+ break;
+ case FP_RM_TOPINF:
+ /* Round result to the value closest to, and not less than,
+ the result. */
+ round = sim_fpu_round_up;
+ break;
+
+ case FP_RM_TOMINF:
+ /* Round result to the value closest to, and not greater than,
+ the result. */
+ round = sim_fpu_round_down;
+ break;
+ default:
+ round = 0;
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
+ /* Convert the input to sim_fpu internal format */
+ switch (from)
+ {
+ case fmt_double:
+ sim_fpu_64to (&wop, op);
+ break;
+ case fmt_single:
+ sim_fpu_32to (&wop, op);
+ break;
+ case fmt_word:
+ sim_fpu_i32to (&wop, op, round);
+ break;
+ case fmt_long:
+ sim_fpu_i64to (&wop, op, round);
+ break;
+ default:
+ fprintf (stderr, "Bad switch\n");
+ abort ();
}
- break;
- default:
- fprintf (stderr, "Bad switch\n");
- abort ();
- }
+ /* Convert sim_fpu format into the output */
+ /* The value WOP is converted to the destination format, rounding
+ using mode RM. When the destination is a fixed-point format, then
+ a source value of Infinity, NaN or one which would round to an
+ integer outside the fixed point range then an IEEE Invalid
+ Operation condition is raised. */
+ switch (to)
+ {
+ case fmt_single:
+ sim_fpu_round_32 (&wop, round, 0);
+ sim_fpu_to32 (&result32, &wop);
+ result64 = result32;
+ break;
+ case fmt_double:
+ sim_fpu_round_64 (&wop, round, 0);
+ sim_fpu_to64 (&result64, &wop);
+ break;
+ case fmt_word:
+ sim_fpu_to32i (&result32, &wop, round);
+ result64 = result32;
+ break;
+ case fmt_long:
+ sim_fpu_to64i (&result64, &wop, round);
+ break;
+ default:
+ result64 = 0;
+ fprintf (stderr, "Bad switch\n");
+ abort ();
+ }
+
#ifdef DEBUG
- printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result),DOFMT(to));
+ printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
#endif /* DEBUG */
- return(result);
+ return(result64);
}
-#endif /* HASFPU */
+
/*-- co-processor support routines ------------------------------------------*/
}
void
-cop_lw(sd,coproc_num,coproc_reg,memword)
- SIM_DESC sd;
- int coproc_num, coproc_reg;
- unsigned int memword;
+cop_lw (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg,
+ unsigned int memword)
{
- switch (coproc_num) {
-#if defined(HASFPU)
+ 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));
+ 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;
-#endif /* HASFPU */
+ StoreFPR(coproc_reg,fmt_word,(uword64)memword);
+ FPR_STATE[coproc_reg] = fmt_uninterpreted;
+ break;
+ }
default:
#if 0 /* this should be controlled by a configuration option */
- sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(IPC));
+ 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;
- }
+ break;
+ }
return;
}
void
-cop_ld(sd,coproc_num,coproc_reg,memword)
- SIM_DESC sd;
- int coproc_num, coproc_reg;
- uword64 memword;
+cop_ld (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg,
+ uword64 memword)
{
switch (coproc_num) {
-#if defined(HASFPU)
case 1:
- StoreFPR(coproc_reg,fmt_uninterpreted,memword);
- break;
-#endif /* HASFPU */
+ if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
+ {
+ StoreFPR(coproc_reg,fmt_uninterpreted,memword);
+ break;
+ }
default:
#if 0 /* this message should be controlled by a configuration option */
- sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(IPC));
+ 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;
}
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+void
+cop_lq (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg,
+ unsigned128 memword)
+{
+ switch (coproc_num)
+ {
+ case 2:
+ {
+ unsigned_16 xyzw;
+
+ while(vu0_busy())
+ vu0_issue(sd);
+
+ memcpy(& xyzw, & memword, sizeof(xyzw));
+ xyzw = H2T_16(xyzw);
+ /* one word at a time, argh! */
+ write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3));
+ write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2));
+ write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1));
+ write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0));
+ }
+ break;
+
+ default:
+ sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
+ coproc_num,coproc_reg,pr_addr(cia));
+ break;
+ }
+
+ return;
+}
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+
unsigned int
-cop_sw(sd,coproc_num,coproc_reg)
- SIM_DESC sd;
- int coproc_num, coproc_reg;
+cop_sw (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg)
{
unsigned int value = 0;
- switch (coproc_num) {
-#if defined(HASFPU)
+ switch (coproc_num)
+ {
case 1:
-#if 1
- {
- 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;
- }
-#else
-#if 1
- value = (unsigned int)ValueFPR(coproc_reg,FPR_STATE[coproc_reg]);
-#else
-#ifdef DEBUG
- printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(FPR_STATE[coproc_reg]));
-#endif /* DEBUG */
- value = (unsigned int)ValueFPR(coproc_reg,fmt_single);
-#endif
-#endif
- break;
-#endif /* HASFPU */
+ 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 /* should be controlled by configuration option */
- sim_io_printf(sd,"COP_SW(%d,%d) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(IPC));
+ 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;
- }
+ break;
+ }
return(value);
}
uword64
-cop_sd(sd,coproc_num,coproc_reg)
- SIM_DESC sd;
- int coproc_num, coproc_reg;
+cop_sd (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg)
{
uword64 value = 0;
- switch (coproc_num) {
-#if defined(HASFPU)
+ switch (coproc_num)
+ {
case 1:
-#if 1
- value = ValueFPR(coproc_reg,fmt_uninterpreted);
-#else
-#if 1
- value = ValueFPR(coproc_reg,FPR_STATE[coproc_reg]);
-#else
-#ifdef DEBUG
- printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(FPR_STATE[coproc_reg]));
-#endif /* DEBUG */
- value = ValueFPR(coproc_reg,fmt_double);
-#endif
-#endif
- break;
-#endif /* HASFPU */
+ if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
+ {
+ value = ValueFPR(coproc_reg,fmt_uninterpreted);
+ break;
+ }
default:
#if 0 /* should be controlled by configuration option */
- sim_io_printf(sd,"COP_SD(%d,%d) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(IPC));
+ 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;
- }
+ break;
+ }
+
+ return(value);
+}
+
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+unsigned128
+cop_sq (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ int coproc_num,
+ int coproc_reg)
+{
+ unsigned128 value = U16_8(0, 0);
+ switch (coproc_num)
+ {
+ case 2:
+ {
+ unsigned_16 xyzw;
+
+ while(vu0_busy())
+ vu0_issue(sd);
+
+ /* one word at a time, argh! */
+ read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3));
+ read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2));
+ read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1));
+ read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0));
+ xyzw = T2H_16(xyzw);
+ return xyzw;
+ }
+ break;
+
+ default:
+ sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",
+ coproc_num,coproc_reg,pr_addr(cia));
+ break;
+ }
return(value);
}
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
void
-decode_coproc(sd,instruction)
- SIM_DESC sd;
- unsigned int instruction;
+decode_coproc (SIM_DESC sd,
+ sim_cpu *cpu,
+ address_word cia,
+ unsigned int instruction)
{
int coprocnum = ((instruction >> 26) & 3);
break;
#else
/* 16 = Config R4000 VR4100 VR4300 */
+ case 16:
+ if (code == 0x00)
+ GPR[rt] = C0_CONFIG;
+ else
+ C0_CONFIG = GPR[rt];
+ break;
#endif
#ifdef SUBTARGET_R3900
/* 17 = Debug */
DSPC = DEPC;
}
else
- sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at IPC = 0x%s : No handler present\n",instruction,pr_addr(IPC));
+ sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
/* TODO: When executing an ERET or RFE instruction we should
clear LLBIT, to ensure that any out-standing atomic
read/modify/write sequence fails. */
}
break;
- case 2: /* undefined co-processor */
- sim_io_eprintf(sd,"COP2 instruction 0x%08X at IPC = 0x%s : No handler present\n",instruction,pr_addr(IPC));
- break;
-
+ case 2: /* co-processor 2 */
+ {
+ int handle = 0;
+
+ /* start-sanitize-sky */
+#ifdef TARGET_SKY
+ /* On the R5900, this refers to a "VU" vector co-processor. */
+
+ int i_25_21 = (instruction >> 21) & 0x1f;
+ int i_20_16 = (instruction >> 16) & 0x1f;
+ int i_20_6 = (instruction >> 6) & 0x7fff;
+ int i_15_11 = (instruction >> 11) & 0x1f;
+ int i_15_0 = instruction & 0xffff;
+ int i_10_1 = (instruction >> 1) & 0x3ff;
+ int i_10_0 = instruction & 0x7ff;
+ int i_10_6 = (instruction >> 6) & 0x1f;
+ int i_5_0 = instruction & 0x03f;
+ int interlock = instruction & 0x01;
+ /* setup for semantic.c-like actions below */
+ typedef unsigned_4 instruction_word;
+ int CIA = cia;
+ int NIA = cia + 4;
+ sim_cpu* CPU_ = cpu;
+
+ handle = 1;
+
+ /* test COP2 usability */
+ if(! (SR & status_CU2))
+ {
+ SignalException(CoProcessorUnusable,instruction);
+ /* NOTREACHED */
+ }
+
+ /* classify & execute basic COP2 instructions */
+ if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ }
+ else if(i_25_21 == 0x08 && i_20_16==0x02) /* BC2FL */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ else NULLIFY_NEXT_INSTRUCTION();
+ }
+ else if(i_25_21 == 0x08 && i_20_16 == 0x01) /* BC2T */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ }
+ else if(i_25_21 == 0x08 && i_20_16 == 0x03) /* BC2TL */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ else NULLIFY_NEXT_INSTRUCTION();
+ }
+ else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
+ (i_25_21 == 0x01)) /* QMFC2 */
+ {
+ int rt = i_20_16;
+ int id = i_15_11;
+
+ /* interlock checking */
+ /* POLICY: never busy in macro mode */
+ while(vu0_busy() && interlock)
+ vu0_issue(sd);
+
+ /* perform VU register address */
+ if(i_25_21 == 0x01) /* QMFC2 */
+ {
+ unsigned_16 xyzw;
+ /* one word at a time, argh! */
+ read_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3));
+ read_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2));
+ read_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1));
+ read_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0));
+ xyzw = T2H_16(xyzw);
+ memcpy(& GPR[rt], & xyzw, sizeof(xyzw));
+ }
+ else /* CFC2 */
+ {
+ unsigned_4 data;
+ /* enum + int calculation, argh! */
+ id = VU_REG_MST + 16 * id;
+ read_vu_misc_reg(&(vu0_device.regs), id, & data);
+ GPR[rt] = EXTEND32(T2H_4(data));
+ }
+ }
+ else if((i_25_21 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
+ (i_25_21 == 0x05)) /* QMTC2 */
+ {
+ int rt = i_20_16;
+ int id = i_15_11;
+
+ /* interlock checking */
+ /* POLICY: never busy in macro mode */
+ if(vu0_busy() && interlock)
+ {
+ while(! vu0_micro_interlock_released())
+ vu0_issue(sd);
+ }
+
+ /* perform VU register address */
+ if(i_25_21 == 0x05) /* QMTC2 */
+ {
+ unsigned_16 xyzw;
+ memcpy(& xyzw, & GPR[rt], sizeof(xyzw));
+ xyzw = H2T_16(xyzw);
+ /* one word at a time, argh! */
+ write_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3));
+ write_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2));
+ write_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1));
+ write_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0));
+ }
+ else /* CTC2 */
+ {
+ unsigned_4 data = H2T_4(GPR[rt]);
+ /* enum + int calculation, argh! */
+ id = VU_REG_MST + 16 * id;
+ write_vu_misc_reg(&(vu0_device.regs), id, & data);
+ }
+ }
+ else if(i_10_0 == 0x3bf) /* VWAITQ */
+ {
+ while(vu0_q_busy())
+ vu0_issue(sd);
+ }
+ else if(i_5_0 == 0x38) /* VCALLMS */
+ {
+ unsigned_4 data = H2T_2(i_20_6);
+
+ while(vu0_busy())
+ vu0_issue(sd);
+
+ /* write to reserved CIA register to get VU0 moving */
+ write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
+
+ ASSERT(vu0_busy());
+ }
+ else if(i_5_0 == 0x39) /* VCALLMSR */
+ {
+ unsigned_4 data;
+
+ while(vu0_busy())
+ vu0_issue(sd);
+
+ read_vu_special_reg(& vu0_device, VU_REG_CMSAR0, & data);
+ /* write to reserved CIA register to get VU0 moving */
+ write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
+
+ ASSERT(vu0_busy());
+ }
+ /* handle all remaining UPPER VU instructions in one block */
+ else if((i_5_0 < 0x30) || /* VADDx .. VMINI */
+ (i_5_0 >= 0x3c && i_10_6 < 0x0c)) /* VADDAx .. VNOP */
+ {
+ unsigned_4 vu_upper, vu_lower;
+ vu_upper =
+ 0x00000000 | /* bits 31 .. 25 */
+ (instruction & 0x01ffffff); /* bits 24 .. 0 */
+ vu_lower = 0x8000033c; /* NOP */
+
+ /* POLICY: never busy in macro mode */
+ while(vu0_busy())
+ vu0_issue(sd);
+
+ vu0_macro_issue(vu_upper, vu_lower);
+
+ /* POLICY: wait for completion of macro-instruction */
+ while(vu0_busy())
+ vu0_issue(sd);
+ }
+ /* handle all remaining LOWER VU instructions in one block */
+ else if((i_5_0 >= 0x30 && i_5_0 <= 0x35) || /* VIADD .. VIOR */
+ (i_5_0 >= 0x3c && i_10_6 >= 0x0c)) /* VMOVE .. VRXOR */
+ { /* N.B.: VWAITQ already covered by prior case */
+ unsigned_4 vu_upper, vu_lower;
+ vu_upper = 0x000002ff; /* NOP/NOP */
+ vu_lower =
+ 0x80000000 | /* bits 31 .. 25 */
+ (instruction & 0x01ffffff); /* bits 24 .. 0 */
+
+ /* POLICY: never busy in macro mode */
+ while(vu0_busy())
+ vu0_issue(sd);
+
+ vu0_macro_issue(vu_upper, vu_lower);
+
+ /* POLICY: wait for completion of macro-instruction */
+ while(vu0_busy())
+ vu0_issue(sd);
+ }
+ /* ... no other COP2 instructions ... */
+ else
+ {
+ SignalException(ReservedInstruction, instruction);
+ /* NOTREACHED */
+ }
+
+ /* cleanup for semantic.c-like actions above */
+ PC = NIA;
+
+#endif /* TARGET_SKY */
+ /* end-sanitize-sky */
+
+ 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: /* should not occur (FPU co-processor) */
case 3: /* should not occur (FPU co-processor) */
SignalException(ReservedInstruction,instruction);
return;
}
+
/*-- instruction simulation -------------------------------------------------*/
/* When the IGEN simulator is being built, the function below is be
#if (WITH_IGEN > 1)
void old_engine_run PARAMS ((SIM_DESC sd, int next_cpu_nr, int siggnal));
void
-old_engine_run (sd, next_cpu_nr, siggnal)
+old_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
#else
void
-sim_engine_run (sd, next_cpu_nr, siggnal)
+sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
#endif
SIM_DESC sd;
int next_cpu_nr; /* ignore */
+ int nr_cpus; /* ignore */
int siggnal; /* ignore */
{
+ sim_cpu *cpu = STATE_CPU (sd, 0); /* hardwire to cpu 0 */
#if !defined(FASTSIM)
unsigned int pipeline_count = 1;
#endif
/* main controlling loop */
while (1) {
- /* Fetch the next instruction from the simulator memory: */
- address_word vaddr = (uword64)PC;
+ /* vaddr is slowly being replaced with cia - current instruction
+ address */
+ address_word cia = (uword64)PC;
+ address_word vaddr = cia;
address_word paddr;
int cca;
unsigned int instruction; /* uword64? what's this used for? FIXME! */
sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
#endif /* DEBUG */
- if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
+ /* Fetch the next instruction from the simulator memory: */
+ if (AddressTranslation(cia,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
if ((vaddr & 1) == 0) {
/* Copy the action of the LW instruction */
unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
sim_io_printf(sd,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction,pr_addr(PC));
#endif /* DEBUG */
- IPC = PC; /* copy PC for this instruction */
/* This is required by exception processing, to ensure that we can
cope with exceptions in the delay slots of branches that may
already have changed the PC. */
[NOTE: pipeline_count has been replaced the event queue] */
-#if defined(HASFPU)
- /* Set previous flag, depending on current: */
- if (STATE & simPCOC0)
- STATE |= simPCOC1;
- else
- STATE &= ~simPCOC1;
- /* and update the current value: */
- if (GETFCC(0))
- STATE |= simPCOC0;
- else
- STATE &= ~simPCOC0;
-#endif /* HASFPU */
+ /* shuffle the floating point status pipeline state */
+ ENGINE_ISSUE_PREFIX_HOOK();
/* NOTE: For multi-context simulation environments the "instruction"
variable should be local to this routine. */
#if (WITH_TARGET_WORD_BITSIZE != GPRLEN)
#error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN"
#endif
-#if (WITH_FLOATING_POINT == HARD_FLOATING_POINT != defined (HASFPU))
+#if ((WITH_FLOATING_POINT == HARD_FLOATING_POINT) != defined (HASFPU))
#error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
#endif
small. */
if (ZERO != 0) {
#if defined(WARN_ZERO)
- sim_io_eprintf(sd,"The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)\n",pr_addr(ZERO),pr_addr(IPC));
+ sim_io_eprintf(sd,"The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)\n",pr_addr(ZERO),pr_addr(cia));
#endif /* WARN_ZERO */
ZERO = 0; /* reset back to zero before next instruction */
}
CANCELDELAYSLOT();
}
- if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */
- /* Deal with pending register updates: */
-#ifdef DEBUG
- printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
-#endif /* DEBUG */
- if (PENDING_OUT != PENDING_IN) {
- int loop;
- int index = PENDING_OUT;
- int total = PENDING_TOTAL;
- if (PENDING_TOTAL == 0) {
- fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
- exit(1);
- }
- for (loop = 0; (loop < total); loop++) {
-#ifdef DEBUG
- printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
-#endif /* DEBUG */
- if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) {
-#ifdef DEBUG
- printf("pending_slot_count[%d] = %d\n",index,PENDING_SLOT_COUNT[index]);
-#endif /* DEBUG */
- if (--(PENDING_SLOT_COUNT[index]) == 0) {
-#ifdef DEBUG
- printf("pending_slot_reg[%d] = %d\n",index,PENDING_SLOT_REG[index]);
- printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(PENDING_SLOT_VALUE[index]));
-#endif /* DEBUG */
- if (PENDING_SLOT_REG[index] == COCIDX) {
-#if defined(HASFPU)
- SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
-#else
- ;
-#endif
- } else {
- REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index];
-#if defined(HASFPU)
- /* The only time we have PENDING updates to FPU
- registers, is when performing binary transfers. This
- means we should update the register type field. */
- if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32)))
- FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted;
-#endif /* HASFPU */
- }
-#ifdef DEBUG
- printf("registers[%d] = 0x%s\n",PENDING_SLOT_REG[index],pr_addr(REGISTERS[PENDING_SLOT_REG[index]]));
-#endif /* DEBUG */
- PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1);
- PENDING_OUT++;
- if (PENDING_OUT == PSLOTS)
- PENDING_OUT = 0;
- PENDING_TOTAL--;
- }
- }
-#ifdef DEBUG
- printf("DBG: AFTER index = %d, loop = %d\n",index,loop);
-#endif /* DEBUG */
- index++;
- if (index == PSLOTS)
- index = 0;
- }
- }
-#ifdef DEBUG
- printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);
-#endif /* DEBUG */
- }
+ if (MIPSISA < 4)
+ PENDING_TICK();
#if !defined(FASTSIM)
if (sim_events_tickn (sd, pipeline_count))
}
+
/*---------------------------------------------------------------------------*/
/*> EOF interp.c <*/