#define PROFILE (1)
#endif
+#include "config.h"
+
#include <stdio.h>
#include <stdarg.h>
#include <ansidecl.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
#include "getopt.h"
#include "libiberty.h"
#include "support.h" /* internal support manifests */
+#include "sysdep.h"
+
+#ifndef SIGBUS
+#define SIGBUS SIGSEGV
+#endif
+
/* Get the simulator engine description, without including the code: */
#define SIM_MANIFESTS
#include "engine.c"
#undef SIM_MANIFESTS
+/* This variable holds the GDB view of the target endianness: */
+extern int target_byte_order;
+
/* The following reserved instruction value is used when a simulator
trap is required. NOTE: Care must be taken, since this value may be
used in later revisions of the MIPS ISA. */
static host_callback *callback = NULL; /* handle onto the current callback structure */
-/* The warning system should be improved, to allow more information to
- be passed about the cause: */
-#define WARNING(m) { callback->printf_filtered(callback,"SIM Warning: %s\n",(m)); }
-
/* This is nasty, since we have to rely on matching the register
numbers used by GDB. Unfortunately, depending on the MIPS target
GDB uses different register numbers. We cannot just include the
/* To keep this default simulator simple, and fast, we use a direct
vector of registers. The internal simulator engine then uses
manifests to access the correct slot. */
-ut_reg registers[LAST_EMBED_REGNUM + 1];
-int register_widths[LAST_EMBED_REGNUM + 1];
+static ut_reg registers[LAST_EMBED_REGNUM + 1];
+static int register_widths[LAST_EMBED_REGNUM + 1];
#define GPR (®isters[0])
#if defined(HASFPU)
#define SP (registers[29])
#define RA (registers[31])
-ut_reg EPC = 0; /* Exception PC */
+static ut_reg EPC = 0; /* Exception PC */
#if defined(HASFPU)
/* Keep the current format state for each register: */
-FP_formats fpr_state[32];
+static FP_formats fpr_state[32];
#endif /* HASFPU */
/* VR4300 CP0 configuration register: */
-unsigned int CONFIG = 0;
+static unsigned int CONFIG = 0;
/* The following are internal simulator state variables: */
-ut_reg IPC = 0; /* internal Instruction PC */
-ut_reg DSPC = 0; /* delay-slot PC */
+static ut_reg IPC = 0; /* internal Instruction PC */
+static ut_reg DSPC = 0; /* delay-slot PC */
/* TODO : these should be the bitmasks for these bits within the
the register update to be delayed for a single instruction
cycle. */
#define PSLOTS (5) /* Maximum number of instruction cycles */
-int pending_in;
-int pending_out;
-int pending_total;
-int pending_slot_count[PSLOTS];
-int pending_slot_reg[PSLOTS];
-ut_reg pending_slot_value[PSLOTS];
+static int pending_in;
+static int pending_out;
+static int pending_total;
+static int pending_slot_count[PSLOTS];
+static int pending_slot_reg[PSLOTS];
+static ut_reg pending_slot_value[PSLOTS];
/* The following are not used for MIPS IV onwards: */
#define PENDING_FILL(r,v) {\
-printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);\
+/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total); */\
if (pending_slot_reg[pending_in] != (LAST_EMBED_REGNUM + 1))\
- callback->printf_filtered(callback,"SIM Warning: Attempt to over-write pending value\n");\
+ sim_warning("Attempt to over-write pending value");\
pending_slot_count[pending_in] = 2;\
pending_slot_reg[pending_in] = (r);\
- pending_slot_value[pending_in] = (v);\
-printf("DBG: FILL reg %d value = 0x%08X%08X\n",(r),(unsigned int)(((unsigned long long)(v))>>32),(unsigned int)((v)&0xFFFFFFFF));\
+ pending_slot_value[pending_in] = (uword64)(v);\
+/*printf("DBG: FILL reg %d value = 0x%08X%08X\n",(r),WORD64HI(v),WORD64LO(v));*/\
pending_total++;\
pending_in++;\
if (pending_in == PSLOTS)\
pending_in = 0;\
-printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);\
+/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);*/\
}
-int LLBIT = 0;
+static int LLBIT = 0;
/* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
read-write instructions. It is set when a linked load occurs. It is
tested and cleared by the conditional store. It is cleared (during
be atomic. In particular, it is cleared by exception return
instructions. */
-int HIACCESS = 0;
-int LOACCESS = 0;
+static int HIACCESS = 0;
+static int LOACCESS = 0;
/* The HIACCESS and LOACCESS counts are used to ensure that
corruptions caused by using the HI or LO register to close to a
following operation are spotted. */
+static ut_reg HLPC = 0;
+/* TODO: The 4300 has interlocks so we should not need to warn of the possible over-write (CHECK THIS) */
/* If either of the preceding two instructions have accessed the HI or
LO registers, then the values they see should be
undefined. However, to keep the simulator world simple, we just let
them use the value read and raise a warning to notify the user: */
#define CHECKHILO(s) {\
if ((HIACCESS != 0) || (LOACCESS != 0))\
- callback->printf_filtered(callback,"SIM Warning: %s over-writing HI and LO registers values\n",(s));\
- /* Set the access counts, since we are about\
- to update the HI and LO registers: */\
- HIACCESS = LOACCESS = 3; /* 3rd instruction will be safe */\
+ sim_warning("%s over-writing HI and LO registers values (PC = 0x%08X%08X HLPC = 0x%08X%08X)\n",(s),(unsigned int)(PC>>32),(unsigned int)(PC&0xFFFFFFFF),(unsigned int)(HLPC>>32),(unsigned int)(HLPC&0xFFFFFFFF));\
}
/* NOTE: We keep the following status flags as bit values (1 for true,
/* At the moment these values will be the same, since we do not have
access to the pipeline cycle count information from the simulator
engine. */
-unsigned int instruction_fetches = 0;
-unsigned int pipeline_ticks = 0;
+static unsigned int instruction_fetches = 0;
+static unsigned int instruction_fetch_overflow = 0;
+static unsigned int pipeline_ticks = 0;
#endif
/* Flags in the "state" variable: */
#define simEXCEPTION (1 << 26) /* 0 = no exception; 1 = exception has occurred */
#define simEXIT (1 << 27) /* 0 = do nothing; 1 = run-time exit() processing */
-unsigned int state = (0 | simBE); /* big-endian simulator by default */
-unsigned int rcexit = 0; /* _exit() reason code holder */
+static unsigned int state = 0;
+static unsigned int rcexit = 0; /* _exit() reason code holder */
#define DELAYSLOT() {\
- if (state & simDELAYSLOT) callback->printf_filtered(callback,"SIM Warning: Delay slot already activated (branch in delay slot?)\n");\
+ if (state & simDELAYSLOT)\
+ sim_warning("Delay slot already activated (branch in delay slot?)");\
state |= simDELAYSLOT;\
}
state |= simSKIPNEXT;\
}
+#define K0BASE (0x80000000)
+#define K0SIZE (0x20000000)
+#define K1BASE (0xA0000000)
+#define K1SIZE (0x20000000)
+
/* Very simple memory model to start with: */
-unsigned char *membank = NULL;
-ut_reg membank_base = 0xA0000000;
-unsigned membank_size = (1 << 20); /* (16 << 20); */ /* power-of-2 */
+static unsigned char *membank = NULL;
+static ut_reg membank_base = K1BASE;
+static unsigned membank_size = (1 << 20); /* (16 << 20); */ /* power-of-2 */
/* Simple run-time monitor support */
-unsigned char *monitor = NULL;
-ut_reg monitor_base = 0xBFC00000;
-unsigned monitor_size = (1 << 9); /* power-of-2 */
+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;
#if defined(TRACE)
-char *tracefile = "trace.din"; /* default filename for trace log */
-FILE *tracefh = NULL;
+static char *tracefile = "trace.din"; /* default filename for trace log */
+static FILE *tracefh = NULL;
#endif /* TRACE */
#if defined(PROFILE)
-unsigned profile_frequency = 256;
-unsigned profile_nsamples = (128 << 10);
-unsigned short *profile_hist = NULL;
-ut_reg profile_minpc;
-ut_reg profile_maxpc;
-int profile_shift = 0; /* address shift amount */
+static unsigned profile_frequency = 256;
+static unsigned profile_nsamples = (128 << 10);
+static unsigned short *profile_hist = NULL;
+static ut_reg profile_minpc;
+static ut_reg profile_maxpc;
+static int profile_shift = 0; /* address shift amount */
#endif /* PROFILE */
+/* The following are used to provide shortcuts to the required version
+ of host<->target copying. This avoids run-time conditionals, which
+ would slow the simulator throughput. */
+typedef unsigned int (*fnptr_read_word) PARAMS((unsigned char *memory));
+typedef unsigned int (*fnptr_swap_word) PARAMS((unsigned int data));
+typedef uword64 (*fnptr_read_long) PARAMS((unsigned char *memory));
+typedef uword64 (*fnptr_swap_long) PARAMS((uword64 data));
+
+static fnptr_read_word host_read_word;
+static fnptr_read_long host_read_long;
+static fnptr_swap_word host_swap_word;
+static fnptr_swap_long host_swap_long;
+
/*---------------------------------------------------------------------------*/
/*-- GDB simulator interface ------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void dotrace PARAMS((FILE *tracefh,int type,unsigned int address,int width,char *comment,...));
+static void sim_warning PARAMS((char *fmt,...));
extern void sim_error PARAMS((char *fmt,...));
static void ColdReset PARAMS((void));
-static int AddressTranslation PARAMS((unsigned long long vAddr,int IorD,int LorS,unsigned long long *pAddr,int *CCA,int host,int raw));
-static void StoreMemory PARAMS((int CCA,int AccessLength,unsigned long long MemElem,unsigned long long pAddr,unsigned long long vAddr,int raw));
-static unsigned long long LoadMemory PARAMS((int CCA,int AccessLength,unsigned long long pAddr,unsigned long long vAddr,int IorD,int raw));
+static int AddressTranslation PARAMS((uword64 vAddr,int IorD,int LorS,uword64 *pAddr,int *CCA,int host,int raw));
+static void StoreMemory PARAMS((int CCA,int AccessLength,uword64 MemElem,uword64 pAddr,uword64 vAddr,int raw));
+static uword64 LoadMemory PARAMS((int CCA,int AccessLength,uword64 pAddr,uword64 vAddr,int IorD,int raw));
static void SignalException PARAMS((int exception,...));
static void simulate PARAMS((void));
-static long getnum(char *value);
-extern void sim_size(unsigned int newsize);
-extern void sim_set_profile(int frequency);
-static unsigned int power2(unsigned int value);
+static long getnum PARAMS((char *value));
+extern void sim_size PARAMS((unsigned int newsize));
+extern void sim_set_profile PARAMS((int frequency));
+static unsigned int power2 PARAMS((unsigned int value));
+
+/*---------------------------------------------------------------------------*/
void
sim_open (args)
trust the explicit manifests held in the source: */
{
unsigned int s[2];
- s[0] = 0x40805A5A;
- s[1] = 0x00000000;
- if (((float)4.01102924346923828125 != *(float *)s) || ((double)523.2939453125 != *(double *)s)) {
+ s[state & simHOSTBE ? 0 : 1] = 0x40805A5A;
+ s[state & simHOSTBE ? 1 : 0] = 0x00000000;
+
+ /* 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. */
+
+ if (((float)4.01102924346923828125 != *(float *)(s + ((state & simHOSTBE) ? 0 : 1))) || ((double)523.2939453125 != *(double *)s)) {
fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n");
+ fprintf(stderr,"*(float *)s = %.20f (4.01102924346923828125)\n",*(float *)s);
+ fprintf(stderr,"*(double *)s = %.20f (523.2939453125)\n",*(double *)s);
exit(1);
}
}
int argc;
static struct option cmdline[] = {
{"help", 0,0,'h'},
+ {"log", 1,0,'l'},
{"name", 1,0,'n'},
{"profile", 0,0,'p'},
{"size", 1,0,'s'},
switch (c) {
case 'h':
callback->printf_filtered(callback,"Usage:\n\t\
-target sim [-h] [--name=<model>] [--size=<amount>]");
+target sim [-h] [--log=<file>] [--name=<model>] [--size=<amount>]");
#if defined(TRACE)
callback->printf_filtered(callback," [-t [--tracefile=<name>]]");
#endif /* TRACE */
callback->printf_filtered(callback,"\n");
break;
+ case 'l':
+ if (optarg != NULL) {
+ char *tmp;
+ tmp = (char *)malloc(strlen(optarg) + 1);
+ if (tmp == NULL)
+ callback->printf_filtered(callback,"Failed to allocate buffer for logfile name \"%s\"\n",optarg);
+ else {
+ strcpy(tmp,optarg);
+ logfile = tmp;
+ }
+ }
+ break;
+
case 'n':
callback->printf_filtered(callback,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg);
break;
}
}
+#if 0
if (optind < argc) {
callback->printf_filtered(callback,"Warning: Ignoring spurious non-option arguments ");
while (optind < argc)
callback->printf_filtered(callback,"\"%s\" ",argv[optind++]);
callback->printf_filtered(callback,"\n");
}
+#endif
freeargv(argv);
}
+ if (logfile != NULL) {
+ if (strcmp(logfile,"-") == 0)
+ logfh = stdout;
+ else {
+ logfh = fopen(logfile,"wb+");
+ if (logfh == NULL) {
+ callback->printf_filtered(callback,"Failed to create file \"%s\", writing log information to stderr.\n",tracefile);
+ logfh = stderr;
+ }
+ }
+ }
+
/* 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
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) {
- unsigned long long vaddr = (monitor_base + loop);
- unsigned long long paddr;
+ uword64 vaddr = (monitor_base + loop);
+ uword64 paddr;
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
- StoreMemory(cca,AccessLength_WORD,(RSVD_INSTRUCTION | (loop >> 2)),paddr,vaddr,isRAW);
+ StoreMemory(cca,AccessLength_WORD,(RSVD_INSTRUCTION | ((loop >> 2) & RSVD_INSTRUCTION_AMASK)),paddr,vaddr,isRAW);
}
+ /* 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
+ instructions within the monitor space. This relies on the IDT
+ monitor not using the locations from 0xBFC00500 onwards as its
+ entry points.*/
+ for (loop = 0; (loop < 24); loop++)
+ {
+ uword64 vaddr = (monitor_base + 0x500 + (loop * 4));
+ uword64 paddr;
+ int cca;
+ unsigned int 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;
+ }
+ value = (monitor_base + (value * 8));
+ if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
+ StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
+ else
+ sim_error("Failed to write to monitor space 0x%08X%08X",WORD64HI(vaddr),WORD64LO(vaddr));
+ }
}
#if defined(TRACE)
if (state & simTRACE) {
tracefh = fopen(tracefile,"wb+");
if (tracefh == NULL) {
- callback->printf_filtered(callback,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile);
+ sim_warning("Failed to create file \"%s\", writing trace information to stderr.",tracefile);
tracefh = stderr;
}
}
buff[3] = ((val >> 24) & 0xFF);
}
if (fwrite(buff,4,1,fh) != 1) {
- callback->printf_filtered(callback,"Failed to write 4bytes to the profile file\n");
+ sim_warning("Failed to write 4bytes to the profile file");
res = 0;
}
return(res);
buff[1] = ((val >> 8) & 0xFF);
}
if (fwrite(buff,2,1,fh) != 1) {
- callback->printf_filtered(callback,"Failed to write 2bytes to the profile file\n");
+ sim_warning("Failed to write 2bytes to the profile file");
res = 0;
}
return(res);
int loop;
if (pf == NULL)
- callback->printf_filtered(callback,"Failed to open \"gmon.out\" profile file\n");
+ sim_warning("Failed to open \"gmon.out\" profile file");
else {
int ok;
#ifdef DEBUG
state &= ~simTRACE;
#endif /* TRACE */
+ if (logfh != NULL && logfh != stdout && logfh != stderr)
+ fclose(logfh);
+ logfh = NULL;
+
if (membank)
- cfree(membank);
+ free(membank); /* cfree not available on all hosts */
membank = NULL;
return;
int size;
{
int index = size;
- unsigned long long vaddr = (unsigned long long)addr;
+ uword64 vaddr = (uword64)addr;
/* Return the number of bytes written, or zero if error. */
#ifdef DEBUG
- callback->printf_filtered(callback,"sim_write(0x%08X%08X,buffer,%d);\n",(unsigned int)((unsigned long long)(addr)>>32),(unsigned int)(addr&0xFFFFFFFF),size);
+ callback->printf_filtered(callback,"sim_write(0x%08X%08X,buffer,%d);\n",WORD64HI(addr),WORD64LO(addr),size);
#endif
/* We provide raw read and write routines, since we do not want to
way. We can then perform doubleword transfers to and from the
simulator memory for optimum performance. */
if (index && (index & 1)) {
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- unsigned long long value = ((unsigned long long)(*buffer++));
+ uword64 value = ((uword64)(*buffer++));
StoreMemory(cca,AccessLength_BYTE,value,paddr,vaddr,isRAW);
}
vaddr++;
index &= ~1; /* logical operations usually quicker than arithmetic on RISC systems */
}
if (index && (index & 2)) {
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- unsigned long long value;
+ 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 = ((unsigned long long)(*buffer++) << 8);
- value |= ((unsigned long long)(*buffer++) << 0);
+ value = ((uword64)(*buffer++) << 8);
+ value |= ((uword64)(*buffer++) << 0);
} else {
- value = ((unsigned long long)(*buffer++) << 0);
- value |= ((unsigned long long)(*buffer++) << 8);
+ value = ((uword64)(*buffer++) << 0);
+ value |= ((uword64)(*buffer++) << 8);
}
StoreMemory(cca,AccessLength_HALFWORD,value,paddr,vaddr,isRAW);
}
index &= ~2;
}
if (index && (index & 4)) {
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- unsigned long long value;
+ uword64 value;
if (BigEndianMem) {
- value = ((unsigned long long)(*buffer++) << 24);
- value |= ((unsigned long long)(*buffer++) << 16);
- value |= ((unsigned long long)(*buffer++) << 8);
- value |= ((unsigned long long)(*buffer++) << 0);
+ value = ((uword64)(*buffer++) << 24);
+ value |= ((uword64)(*buffer++) << 16);
+ value |= ((uword64)(*buffer++) << 8);
+ value |= ((uword64)(*buffer++) << 0);
} else {
- value = ((unsigned long long)(*buffer++) << 0);
- value |= ((unsigned long long)(*buffer++) << 8);
- value |= ((unsigned long long)(*buffer++) << 16);
- value |= ((unsigned long long)(*buffer++) << 24);
+ value = ((uword64)(*buffer++) << 0);
+ value |= ((uword64)(*buffer++) << 8);
+ value |= ((uword64)(*buffer++) << 16);
+ value |= ((uword64)(*buffer++) << 24);
}
StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
}
index &= ~4;
}
for (;index; index -= 8) {
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
- unsigned long long value;
+ uword64 value;
if (BigEndianMem) {
- value = ((unsigned long long)(*buffer++) << 56);
- value |= ((unsigned long long)(*buffer++) << 48);
- value |= ((unsigned long long)(*buffer++) << 40);
- value |= ((unsigned long long)(*buffer++) << 32);
- value |= ((unsigned long long)(*buffer++) << 24);
- value |= ((unsigned long long)(*buffer++) << 16);
- value |= ((unsigned long long)(*buffer++) << 8);
- value |= ((unsigned long long)(*buffer++) << 0);
+ 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 = ((unsigned long long)(*buffer++) << 0);
- value |= ((unsigned long long)(*buffer++) << 8);
- value |= ((unsigned long long)(*buffer++) << 16);
- value |= ((unsigned long long)(*buffer++) << 24);
- value |= ((unsigned long long)(*buffer++) << 32);
- value |= ((unsigned long long)(*buffer++) << 40);
- value |= ((unsigned long long)(*buffer++) << 48);
- value |= ((unsigned long long)(*buffer++) << 56);
+ 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,paddr,vaddr,isRAW);
}
/* Return the number of bytes read, or zero if error. */
#ifdef DEBUG
- callback->printf_filtered(callback,"sim_read(0x%08X%08X,buffer,%d);\n",(unsigned int)((unsigned long long)(addr)>>32),(unsigned int)(addr&0xFFFFFFFF),size);
+ callback->printf_filtered(callback,"sim_read(0x%08X%08X,buffer,%d);\n",WORD64HI(addr),WORD64LO(addr),size);
#endif /* DEBUG */
/* TODO: Perform same optimisation as the sim_write() code
to ensure that the source physical address is doubleword aligned
before, and then deal with trailing bytes. */
for (index = 0; (index < size); index++) {
- unsigned long long vaddr,paddr,value;
+ uword64 vaddr,paddr,value;
int cca;
- vaddr = (unsigned long long)addr + index;
+ vaddr = (uword64)addr + index;
if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&cca,isTARGET,isRAW)) {
value = LoadMemory(cca,AccessLength_BYTE,paddr,vaddr,isDATA,isRAW);
buffer[index] = (unsigned char)(value&0xFF);
numbering one. We need to know what the width of each logical
register number is for the architecture being simulated. */
if (register_widths[rn] == 0)
- callback->printf_filtered(callback,"Warning: Invalid register width for %d (register store ignored)\n",rn);
+ sim_warning("Invalid register width for %d (register store ignored)",rn);
else {
if (register_widths[rn] == 32)
- registers[rn] = *((unsigned int *)memory);
+ registers[rn] = host_read_word(memory);
else
- registers[rn] = *((unsigned long long *)memory);
+ registers[rn] = host_read_long(memory);
}
return;
unsigned char *memory;
{
#ifdef DEBUG
- callback->printf_filtered(callback,"sim_fetch_register(%d=0x%08X%08X,mem) : place simulator registers into memory\n",rn,(unsigned int)(registers[rn]>>32),(unsigned int)(registers[rn]&0xFFFFFFFF));
+ callback->printf_filtered(callback,"sim_fetch_register(%d=0x%08X%08X,mem) : place simulator registers into memory\n",rn,WORD64HI(registers[rn]),WORD64LO(registers[rn]));
#endif /* DEBUG */
if (register_widths[rn] == 0)
- callback->printf_filtered(callback,"Warning: Invalid register width for %d (register fetch ignored)\n",rn);
+ sim_warning("Invalid register width for %d (register fetch ignored)",rn);
else {
if (register_widths[rn] == 32)
- *((unsigned int *)memory) = (registers[rn] & 0xFFFFFFFF);
+ *((unsigned int *)memory) = host_swap_word(registers[rn] & 0xFFFFFFFF);
else /* 64bit register */
- *((unsigned long long *)memory) = registers[rn];
+ *((uword64 *)memory) = host_swap_long(registers[rn]);
}
return;
}
break;
}
} else if (state & simEXIT) {
+#if 0
printf("DBG: simEXIT (%d)\n",rcexit);
+#endif
*reason = sim_exited;
*sigrc = rcexit;
} else { /* assume single-stepping */
callback->printf_filtered(callback,"%s endian memory model\n",(BigEndianMem ? "Big" : "Little"));
- callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%08X%08X\n",(unsigned int)membank_size,(unsigned int)(membank_base>>32),(unsigned int)(membank_base&0xFFFFFFFF));
+ callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%08X%08X\n",(unsigned int)membank_size,WORD64HI(membank_base),WORD64LO(membank_base));
#if !defined(FASTSIM)
- callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches);
+ if (instruction_fetch_overflow != 0)
+ callback->printf_filtered(callback,"Instruction fetches = 0x%08X%08X\n",instruction_fetch_overflow,instruction_fetches);
+ else
+ callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches);
callback->printf_filtered(callback,"Pipeline ticks = %d\n",pipeline_ticks);
/* It would be a useful feature, if when performing multi-cycle
simulations (rather than single-stepping) we keep the start and
/* argv and env are NULL terminated lists of pointers */
#if 1
- PC = (unsigned long long)start_address;
+ PC = (uword64)start_address;
#else
/* TODO: Sort this properly. SIM_ADDR may already be a 64bit value: */
PC = SIGNEXTEND(start_address,32);
used by other clients of the simulator. */
if (argv || env) {
+#if 0 /* def DEBUG */
callback->printf_filtered(callback,"sim_create_inferior() : passed arguments ignored\n");
-#if 1 /* def DEBUG */
{
char **cptr;
for (cptr = argv; (cptr && *cptr); cptr++)
{
struct t_sim_command *cptr;
+ if (callback == NULL) {
+ fprintf(stderr,"Simulator not enabled: \"target sim\" should be used to activate\n");
+ return;
+ }
+
if (!(cmd && *cmd != '\0'))
cmd = "help";
else
profile_hist = (unsigned short *)realloc(profile_hist,bsize);
if (profile_hist == NULL) {
- callback->printf_filtered(callback,"Failed to allocate VM for profiling buffer (0x%08X bytes)\n",bsize);
+ sim_warning("Failed to allocate VM for profiling buffer (0x%08X bytes)",bsize);
state &= ~simPROFILE;
}
}
{
char *new;
/* Used by "run", and internally, to set the simulated memory size */
+ if (newsize == 0) {
+ callback->printf_filtered(callback,"Zero not valid: Memory size still 0x%08X bytes\n",membank_size);
+ return;
+ }
newsize = power2(newsize);
if (membank == NULL)
new = (char *)calloc(64,(membank_size / 64));
new = (char *)realloc(membank,newsize);
if (new == NULL) {
if (membank == NULL)
- callback->printf_filtered(callback,"Not enough VM for simulation memory of 0x%08X bytes\n",membank_size);
+ sim_error("Not enough VM for simulation memory of 0x%08X bytes",membank_size);
else
- callback->printf_filtered(callback,"Failed to resize memory (still 0x%08X bytes)\n",membank_size);
+ sim_warning("Failed to resize memory (still 0x%08X bytes)",membank_size);
} else {
membank_size = (unsigned)newsize;
membank = new;
- callback->printf_filtered(callback,"Memory size now 0x%08X bytes\n",membank_size);
#if defined(PROFILE)
/* Ensure that we sample across the new memory range */
sim_set_profile_size(profile_nsamples);
/*-- Private simulator support interface ------------------------------------*/
/*---------------------------------------------------------------------------*/
+/* Simple monitor interface (currently setup for the IDT and PMON monitors) */
static void
sim_monitor(reason)
unsigned int reason;
case 6: /* int open(char *path,int flags) */
{
const char *ptr;
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
V0 = callback->open(callback,(char *)((int)paddr),(int)A1);
else
- callback->printf_filtered(callback,"WARNING: Attempt to pass pointer that does not reference simulated memory\n");
+ sim_error("Attempt to pass pointer that does not reference simulated memory");
}
break;
case 7: /* int read(int file,char *ptr,int len) */
{
const char *ptr;
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
V0 = callback->read(callback,(int)A0,(char *)((int)paddr),(int)A2);
else
- callback->printf_filtered(callback,"WARNING: Attempt to pass pointer that does not reference simulated memory\n");
+ sim_error("Attempt to pass pointer that does not reference simulated memory");
}
break;
case 8: /* int write(int file,char *ptr,int len) */
{
const char *ptr;
- unsigned long long paddr;
+ uword64 paddr;
int cca;
if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
V0 = callback->write(callback,(int)A0,(const char *)((int)paddr),(int)A2);
else
- callback->printf_filtered(callback,"WARNING: Attempt to pass pointer that does not reference simulated memory\n");
+ sim_error("Attempt to pass pointer that does not reference simulated memory");
}
break;
{
char tmp;
if (callback->read_stdin(callback,&tmp,sizeof(char)) != sizeof(char)) {
- callback->printf_filtered(callback,"WARNING: Invalid return from character read\n");
+ sim_error("Invalid return from character read");
V0 = -1;
}
else
break;
case 17: /* void _exit() */
- callback->printf_filtered(callback,"sim_monitor(17): _exit(int reason) to be coded\n");
+ sim_warning("sim_monitor(17): _exit(int reason) to be coded");
state |= (simSTOP | simEXIT); /* stop executing code */
rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
break;
/* [A0 + 4] = instruction cache size */
/* [A0 + 8] = data cache size */
{
- unsigned long long vaddr = A0;
- unsigned long long paddr, value;
+ uword64 vaddr = A0;
+ uword64 paddr, value;
int cca;
int failed = 0;
/* Memory size */
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) {
- value = (unsigned long long)membank_size;
+ value = (uword64)membank_size;
StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
/* We re-do the address translations, in-case the block
overlaps a memory boundary: */
failed = -1;
if (failed)
- callback->printf_filtered(callback,"WARNING: Invalid pointer passed into monitor call\n");
+ sim_error("Invalid pointer passed into monitor call");
+ }
+ break;
+
+ case 158 : /* PMON printf */
+ /* in: A0 = pointer to format string */
+ /* A1 = optional argument 1 */
+ /* A2 = optional argument 2 */
+ /* A3 = optional argument 3 */
+ /* out: void */
+ /* The following is based on the PMON printf source */
+ {
+ uword64 paddr;
+ int cca;
+ /* 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);
+ ut_reg *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;
+ int base = 10;
+ 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 == '%') {
+ callback->printf_filtered(callback,"%%");
+ } else if (*s == 's') {
+ if ((int)*ap != 0) {
+ if (AddressTranslation(*ap++,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
+ char *p = (char *)((int)paddr);;
+ callback->printf_filtered(callback,p);
+ } else {
+ ap++;
+ sim_error("Attempt to pass pointer that does not reference simulated memory");
+ }
+ }
+ else
+ callback->printf_filtered(callback,"(null)");
+ } else if (*s == 'c') {
+ int n = (int)*ap++;
+ callback->printf_filtered(callback,"%c",n);
+ } else {
+ if (*s == 'l') {
+ if (*++s == 'l') {
+ longlong = 1;
+ ++s;
+ }
+ }
+ if (strchr ("dobxXu", *s)) {
+ long long lv = (long long)*ap++;
+ if (*s == 'b')
+ callback->printf_filtered(callback,"<binary not supported>");
+ else {
+ sprintf(tmp,"%%%s%c",longlong ? "ll" : "",*s);
+ if (longlong)
+ callback->printf_filtered(callback,tmp,lv);
+ else
+ callback->printf_filtered(callback,tmp,(int)lv);
+ }
+ } else if (strchr ("eEfgG", *s)) {
+ double dbl = (double)*ap++;
+ sprintf(tmp,"%%%d.%d%c",width,trunc,*s);
+ callback->printf_filtered(callback,tmp,dbl);
+ trunc = 0;
+ }
+ }
+ s++;
+ } else
+ callback->printf_filtered(callback,"%c",*s++);
+ }
+ } else
+ sim_error("Attempt to pass pointer that does not reference simulated memory");
}
break;
default:
- callback->printf_filtered(callback,"TODO: sim_monitor(%d) : PC = 0x%08X%08X\n",reason,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
- callback->printf_filtered(callback,"(Arguments : A0 = 0x%08X%08X : A1 = 0x%08X%08X : A2 = 0x%08X%08X : A3 = 0x%08X%08X)\n",(unsigned int)(A0>>32),(unsigned int)(A0&0xFFFFFFFF),(unsigned int)(A1>>32),(unsigned int)(A1&0xFFFFFFFF),(unsigned int)(A2>>32),(unsigned int)(A2&0xFFFFFFFF),(unsigned int)(A3>>32),(unsigned int)(A3&0xFFFFFFFF));
+ sim_warning("TODO: sim_monitor(%d) : PC = 0x%08X%08X",reason,WORD64HI(IPC),WORD64LO(IPC));
+ sim_warning("(Arguments : A0 = 0x%08X%08X : A1 = 0x%08X%08X : A2 = 0x%08X%08X : A3 = 0x%08X%08X)",WORD64HI(A0),WORD64LO(A0),WORD64HI(A1),WORD64LO(A1),WORD64HI(A2),WORD64LO(A2),WORD64HI(A3),WORD64LO(A3));
break;
}
return;
}
+void
+sim_warning(fmt)
+ char *fmt;
+{
+ va_list ap;
+ va_start(ap,fmt);
+ if (logfh != NULL) {
+#if 1
+ fprintf(logfh,"SIM Warning: ");
+ fprintf(logfh,fmt,ap);
+ fprintf(logfh,"\n");
+#else /* we should provide a method of routing log messages to the simulator output stream */
+ callback->printf_filtered(callback,"SIM Warning: ");
+ callback->printf_filtered(callback,fmt,ap);
+#endif
+ }
+ va_end(ap);
+ SignalException(SimulatorFault,"");
+ return;
+}
+
void
sim_error(fmt)
char *fmt;
}
#endif /* TRACE */
+/*---------------------------------------------------------------------------*/
+/*-- host<->target transfers ------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* The following routines allow conditionals to be avoided during the
+ simulation, at the cost of increasing the image and source size. */
+
+static unsigned int
+xfer_direct_word(memory)
+ unsigned char *memory;
+{
+ return *((unsigned int *)memory);
+}
+
+static uword64
+xfer_direct_long(memory)
+ unsigned char *memory;
+{
+ return *((uword64 *)memory);
+}
+
+static unsigned int
+swap_direct_word(data)
+ unsigned int data;
+{
+ return data;
+}
+
+static uword64
+swap_direct_long(data)
+ uword64 data;
+{
+ return data;
+}
+
+static unsigned int
+xfer_big_word(memory)
+ unsigned char *memory;
+{
+ return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]);
+}
+
+static uword64
+xfer_big_long(memory)
+ unsigned char *memory;
+{
+ return (((uword64)memory[0] << 56) | ((uword64)memory[1] << 48)
+ | ((uword64)memory[2] << 40) | ((uword64)memory[3] << 32)
+ | (memory[4] << 24) | (memory[5] << 16) | (memory[6] << 8) | memory[7]);
+}
+
+static unsigned int
+xfer_little_word(memory)
+ unsigned char *memory;
+{
+ return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
+}
+
+static uword64
+xfer_little_long(memory)
+ unsigned char *memory;
+{
+ return (((uword64)memory[7] << 56) | ((uword64)memory[6] << 48)
+ | ((uword64)memory[5] << 40) | ((uword64)memory[4] << 32)
+ | (memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
+}
+
+static unsigned int
+swap_word(data)
+ unsigned int data;
+{
+ unsigned int result;
+ result = data ^ ((data << 16) | (data >> 16));
+ result &= ~0x00FF0000;
+ data = (data << 24) | (data >> 8);
+ return data ^ (result >> 8);
+}
+
+static uword64
+swap_long(data)
+ uword64 data;
+{
+ unsigned int tmphi = WORD64HI(data);
+ unsigned int tmplo = WORD64LO(data);
+ tmphi = swap_word(tmphi);
+ tmplo = swap_word(tmplo);
+ /* Now swap the HI and LO parts */
+ return SET64LO(tmphi) | SET64HI(tmplo);
+}
+
/*---------------------------------------------------------------------------*/
/*-- simulator engine -------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
ColdReset()
{
/* RESET: Fixed PC address: */
- PC = (((unsigned long long)0xFFFFFFFF<<32) | 0xBFC00000);
+ PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
/* The reset vector address is in the unmapped, uncached memory space. */
SR &= ~(status_SR | status_TS | status_RP);
}
#endif /* HASFPU */
+ /* In reality this check should be performed at various points
+ within the simulation, since it is possible to change the
+ endianness of user programs. However, we perform the check here
+ to ensure that the start-of-day values agree: */
+ state |= (BigEndianCPU ? simBE : 0);
+ if ((target_byte_order == 1234) != !(state & simBE)) {
+ fprintf(stderr,"ColdReset: GDB (%s) and simulator (%s) do not agree on target endianness\n",
+ target_byte_order == 1234 ? "little" : "big",
+ state & simBE ? "big" : "little");
+ exit(1);
+ }
+
+ if (!(state & simHOSTBE) == !(state & simBE)) {
+ host_read_word = xfer_direct_word;
+ host_read_long = xfer_direct_long;
+ host_swap_word = swap_direct_word;
+ host_swap_long = swap_direct_long;
+ } else if (state & simHOSTBE) {
+ host_read_word = xfer_little_word;
+ host_read_long = xfer_little_long;
+ host_swap_word = swap_word;
+ host_swap_long = swap_long;
+ } else { /* HOST little-endian */
+ host_read_word = xfer_big_word;
+ host_read_long = xfer_big_long;
+ host_swap_word = swap_word;
+ host_swap_long = swap_long;
+ }
+
return;
}
static int
AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
- unsigned long long vAddr;
+ uword64 vAddr;
int IorD;
int LorS;
- unsigned long long *pAddr;
+ uword64 *pAddr;
int *CCA;
int host;
int raw;
int res = -1; /* TRUE : Assume good return */
#ifdef DEBUG
- callback->printf_filtered(callback,"AddressTranslation(0x%08X%08X,%s,%s,...);\n",(unsigned int)(vAddr >> 32),(unsigned int)(vAddr & 0xFFFFFFFF),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
+ callback->printf_filtered(callback,"AddressTranslation(0x%08X%08X,%s,%s,...);\n",WORD64HI(vAddr),WORD64LO(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 ((membank_base == 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 & (membank_size - 1)));
+
*pAddr = vAddr; /* default for isTARGET */
*CCA = Uncached; /* not used for isHOST */
*pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
} else {
#if 1 /* def DEBUG */
- callback->printf_filtered(callback,"Failed: AddressTranslation(0x%08X%08X,%s,%s,...);\n",(unsigned int)(vAddr >> 32),(unsigned int)(vAddr & 0xFFFFFFFF),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"));
+ sim_warning("Failed: AddressTranslation(0x%08X%08X,%s,%s,...) IPC = 0x%08X%08X",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),WORD64HI(IPC),WORD64LO(IPC));
#endif /* DEBUG */
res = 0; /* AddressTranslation has failed */
*pAddr = -1;
if (!raw) /* only generate exceptions on real memory transfers */
SignalException((LorS == isSTORE) ? AddressStore : AddressLoad);
else
- callback->printf_filtered(callback,"AddressTranslation for %s %s from 0x%08X%08X failed\n",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),(unsigned int)(vAddr>>32),(unsigned int)(vAddr&0xFFFFFFFF));
+ sim_warning("AddressTranslation for %s %s from 0x%08X%08X failed",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),WORD64HI(vAddr),WORD64LO(vAddr));
}
return(res);
static void
Prefetch(CCA,pAddr,vAddr,DATA,hint)
int CCA;
- unsigned long long pAddr;
- unsigned long long vAddr;
+ uword64 pAddr;
+ uword64 vAddr;
int DATA;
int hint;
{
#ifdef DEBUG
- callback->printf_filtered(callback,"Prefetch(%d,0x%08X%08X,0x%08X%08X,%d,%d);\n",CCA,(unsigned int)(pAddr >> 32),(unsigned int)(pAddr & 0xFFFFFFFF),(unsigned int)(vAddr >> 32),(unsigned int)(vAddr & 0xFFFFFFFF),DATA,hint);
+ callback->printf_filtered(callback,"Prefetch(%d,0x%08X%08X,0x%08X%08X,%d,%d);\n",CCA,WORD64HI(pAddr),WORD64LO(pAddr),WORD64HI(vAddr),WORD64LO(vAddr),DATA,hint);
#endif /* DEBUG */
/* For our simple memory model we do nothing */
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. */
-static unsigned long long
+static uword64
LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
int CCA;
int AccessLength;
- unsigned long long pAddr;
- unsigned long long vAddr;
+ uword64 pAddr;
+ uword64 vAddr;
int IorD;
int raw;
{
- unsigned long long value;
+ uword64 value;
#ifdef DEBUG
if (membank == NULL)
- callback->printf_filtered(callback,"DBG: LoadMemory(%d,%d,0x%08X%08X,0x%08X%08X,%s,%s)\n",CCA,AccessLength,(unsigned int)(pAddr >> 32),(unsigned int)(pAddr & 0xFFFFFFFF),(unsigned int)(vAddr >> 32),(unsigned int)(vAddr & 0xFFFFFFFF),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL"));
+ callback->printf_filtered(callback,"DBG: LoadMemory(%d,%d,0x%08X%08X,0x%08X%08X,%s,%s)\n",CCA,AccessLength,WORD64HI(pAddr),WORD64LO(pAddr),WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL"));
#endif /* DEBUG */
#if defined(WARN_MEM)
if (CCA != uncached)
- callback->printf_filtered(callback,"SIM Warning: LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
+ sim_warning("LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
/* In reality this should be a Bus Error */
- sim_error("AccessLength of %d would extend over 64bit aligned boundary for physical address 0x%08X%08X\n",AccessLength,(unsigned int)(pAddr>>32),(unsigned int)(pAddr&0xFFFFFFFF));
+ sim_error("AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%08X%08X\n",AccessLength,(LOADDRMASK + 1)<<2,WORD64HI(pAddr),WORD64LO(pAddr));
}
#endif /* WARN_MEM */
unsigned int index;
unsigned char *mem = NULL;
- /* TODO: #assert (isRAW) - check that our boolean is the correct way around */
-
#if defined(TRACE)
if (!raw)
dotrace(tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
mem = monitor;
}
if (mem == NULL)
- sim_error("Simulator memory not found for physical address 0x%08X%08X\n",(unsigned int)(pAddr>>32),(unsigned int)(pAddr&0xFFFFFFFF));
+ sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(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
if (BigEndianMem)
switch (AccessLength) { /* big-endian memory */
case AccessLength_DOUBLEWORD :
- value |= ((unsigned long long)mem[index++] << 56);
+ value |= ((uword64)mem[index++] << 56);
case AccessLength_SEPTIBYTE :
- value |= ((unsigned long long)mem[index++] << 48);
+ value |= ((uword64)mem[index++] << 48);
case AccessLength_SEXTIBYTE :
- value |= ((unsigned long long)mem[index++] << 40);
+ value |= ((uword64)mem[index++] << 40);
case AccessLength_QUINTIBYTE :
- value |= ((unsigned long long)mem[index++] << 32);
+ value |= ((uword64)mem[index++] << 32);
case AccessLength_WORD :
value |= ((unsigned int)mem[index++] << 24);
case AccessLength_TRIPLEBYTE :
index += (AccessLength + 1);
switch (AccessLength) { /* little-endian memory */
case AccessLength_DOUBLEWORD :
- value |= ((unsigned long long)mem[--index] << 56);
+ value |= ((uword64)mem[--index] << 56);
case AccessLength_SEPTIBYTE :
- value |= ((unsigned long long)mem[--index] << 48);
+ value |= ((uword64)mem[--index] << 48);
case AccessLength_SEXTIBYTE :
- value |= ((unsigned long long)mem[--index] << 40);
+ value |= ((uword64)mem[--index] << 40);
case AccessLength_QUINTIBYTE :
- value |= ((unsigned long long)mem[--index] << 32);
+ value |= ((uword64)mem[--index] << 32);
case AccessLength_WORD :
- value |= ((unsigned long long)mem[--index] << 24);
+ value |= ((uword64)mem[--index] << 24);
case AccessLength_TRIPLEBYTE :
- value |= ((unsigned long long)mem[--index] << 16);
+ value |= ((uword64)mem[--index] << 16);
case AccessLength_HALFWORD :
- value |= ((unsigned long long)mem[--index] << 8);
+ value |= ((uword64)mem[--index] << 8);
case AccessLength_BYTE :
- value |= ((unsigned long long)mem[--index] << 0);
+ value |= ((uword64)mem[--index] << 0);
break;
}
}
#ifdef DEBUG
- printf("DBG: LoadMemory() : (offset %d) : value = 0x%08X%08X\n",(int)(pAddr & LOADDRMASK),(unsigned int)(value>>32),(unsigned int)(value&0xFFFFFFFF));
+ printf("DBG: LoadMemory() : (offset %d) : value = 0x%08X%08X\n",(int)(pAddr & LOADDRMASK),WORD64HI(value),WORD64LO(value));
#endif /* DEBUG */
/* TODO: We could try and avoid the shifts when dealing with raw
}
#ifdef DEBUG
- printf("DBG: LoadMemory() : shifted value = 0x%08X%08X\n",(unsigned int)(value>>32),(unsigned int)(value&0xFFFFFFFF));
-#endif DEBUG
+ printf("DBG: LoadMemory() : shifted value = 0x%08X%08X\n",WORD64HI(value),WORD64LO(value));
+#endif /* DEBUG */
}
}
StoreMemory(CCA,AccessLength,MemElem,pAddr,vAddr,raw)
int CCA;
int AccessLength;
- unsigned long long MemElem;
- unsigned long long pAddr;
- unsigned long long vAddr;
+ uword64 MemElem;
+ uword64 pAddr;
+ uword64 vAddr;
int raw;
{
#ifdef DEBUG
- callback->printf_filtered(callback,"DBG: StoreMemory(%d,%d,0x%08X%08X,0x%08X%08X,0x%08X%08X,%s)\n",CCA,AccessLength,(unsigned int)(MemElem >> 32),(unsigned int)(MemElem & 0xFFFFFFFF),(unsigned int)(pAddr >> 32),(unsigned int)(pAddr & 0xFFFFFFFF),(unsigned int)(vAddr >> 32),(unsigned int)(vAddr & 0xFFFFFFFF),(raw ? "isRAW" : "isREAL"));
+ callback->printf_filtered(callback,"DBG: StoreMemory(%d,%d,0x%08X%08X,0x%08X%08X,0x%08X%08X,%s)\n",CCA,AccessLength,WORD64HI(MemElem),WORD64LO(MemElem),WORD64HI(pAddr),WORD64LO(pAddr),WORD64HI(vAddr),WORD64LO(vAddr),(raw ? "isRAW" : "isREAL"));
#endif /* DEBUG */
#if defined(WARN_MEM)
if (CCA != uncached)
- callback->printf_filtered(callback,"SIM Warning: StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
+ sim_warning("StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
- sim_error("AccessLength of %d would extend over 64bit aligned boundary for physical address 0x%08X%08X\n",AccessLength,(unsigned int)(pAddr>>32),(unsigned int)(pAddr&0xFFFFFFFF));
+ sim_error("AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%08X%08X\n",AccessLength,(LOADDRMASK + 1)<<2,WORD64HI(pAddr),WORD64LO(pAddr));
#endif /* WARN_MEM */
#if defined(TRACE)
}
if (mem == NULL)
- sim_error("Simulator memory not found for physical address 0x%08X%08X\n",(unsigned int)(pAddr>>32),(unsigned int)(pAddr&0xFFFFFFFF));
+ sim_error("Simulator memory not found for physical address 0x%08X%08X\n",WORD64HI(pAddr),WORD64LO(pAddr));
else {
int shift = 0;
#ifdef DEBUG
- printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr & LOADDRMASK),(unsigned int)(MemElem>>32),(unsigned int)(MemElem&0xFFFFFFFF));
+ printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr & LOADDRMASK),WORD64HI(MemElem),WORD64LO(MemElem));
#endif /* DEBUG */
if (BigEndianMem) {
}
#ifdef DEBUG
- printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift,(unsigned int)(MemElem>>32),(unsigned int)(MemElem&0xFFFFFFFF));
+ printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift,WORD64HI(MemElem),WORD64LO(MemElem));
#endif /* DEBUG */
if (BigEndianMem) {
reality we should either simulate them, or allow the user to
ignore them at run-time. */
case Trap :
- callback->printf_filtered(callback,"Ignoring instruction TRAP (PC 0x%08X%08X)\n",(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ sim_warning("Ignoring instruction TRAP (PC 0x%08X%08X)",WORD64HI(IPC),WORD64LO(IPC));
break;
case ReservedInstruction :
case with the current IDT monitor). */
break; /* out of the switch statement */
} /* else fall through to normal exception processing */
- callback->printf_filtered(callback,"DBG: ReservedInstruction 0x%08X at IPC = 0x%08X%08X\n",instruction,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ sim_warning("ReservedInstruction 0x%08X at IPC = 0x%08X%08X",instruction,WORD64HI(IPC),WORD64LO(IPC));
}
default:
#if 1 /* def DEBUG */
- callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ if (exception != BreakPoint)
+ callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception,WORD64HI(IPC),WORD64LO(IPC));
#endif /* DEBUG */
/* Store exception code into current exception id variable (used
by exit code): */
/* TODO: If not simulating exceptions then stop the simulator
execution. At the moment we always stop the simulation. */
+#if 1 /* bodge to allow exit() code to be returned, by assuming that a breakpoint exception after a monitor exit() call should be silent */
+/* further bodged since the standard libgloss/mips world doesn't use the _exit() monitor call, it just uses a break instruction */
+ if (exception == BreakPoint /* && state & simEXIT */)
+ {
+ state |= simSTOP;
+#if 1 /* since the _exit() monitor call may not be called */
+ state |= simEXIT;
+ rcexit = (unsigned int)(A0 & 0xFFFFFFFF);
+#endif
+ }
+ else
+ state |= (simSTOP | simEXCEPTION);
+#else
state |= (simSTOP | simEXCEPTION);
+#endif
CAUSE = (exception << 2);
if (state & simDELAYSLOT) {
CAUSE |= cause_BD;
static void
UndefinedResult()
{
- callback->printf_filtered(callback,"UndefinedResult: IPC = 0x%08X%08X\n",(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ sim_warning("UndefinedResult: IPC = 0x%08X%08X",WORD64HI(IPC),WORD64LO(IPC));
#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
state |= simSTOP;
#endif
static void
CacheOp(op,pAddr,vAddr,instruction)
int op;
- unsigned long long pAddr;
- unsigned long long vAddr;
+ uword64 pAddr;
+ uword64 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. */
- callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+#if 0
+ callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",WORD64HI(IPC),WORD64LO(IPC));
+#endif
switch (op & 0x3) {
case 0: /* instruction cache */
case 4: /* Hit Invalidate */
case 5: /* Fill */
case 6: /* Hit Writeback */
- callback->printf_filtered(callback,"SIM Warning: Instruction CACHE operation %d to be coded\n",(op >> 2));
+ if (!icache_warning)
+ {
+ sim_warning("Instruction CACHE operation %d to be coded",(op >> 2));
+ icache_warning = 1;
+ }
break;
default:
case 4: /* Hit Invalidate */
case 5: /* Hit Writeback Invalidate */
case 6: /* Hit Writeback */
- callback->printf_filtered(callback,"SIM Warning: Data CACHE operation %d to be coded\n",(op >> 2));
+ if (!dcache_warning)
+ {
+ sim_warning("Data CACHE operation %d to be coded",(op >> 2));
+ dcache_warning = 1;
+ }
break;
default:
/* Extract sign-bit: */
#define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
-#define FP_D_s(v) (((v) & ((unsigned long long)1 << 63)) ? 1 : 0)
+#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
/* Extract biased exponent: */
#define FP_S_be(v) (((v) >> 23) & 0xFF)
#define FP_D_be(v) (((v) >> 52) & 0x7FF)
#define FP_D_e(v) (FP_D_be(v) - 0x3FF)
/* Extract complete fraction field: */
#define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
-#define FP_D_f(v) ((v) & ~((unsigned long long)0xFFF << 52))
+#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
/* Extract numbered fraction bit: */
#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
/* Explicit QNaN values used when value required: */
#define FPQNaN_SINGLE (0x7FBFFFFF)
#define FPQNaN_WORD (0x7FFFFFFF)
-#define FPQNaN_DOUBLE (((unsigned long long)0x7FF7FFFF << 32) | 0xFFFFFFFF)
-#define FPQNaN_LONG (((unsigned long long)0x7FFFFFFF << 32) | 0xFFFFFFFF)
+#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
+#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
/* Explicit Infinity values used when required: */
#define FPINF_SINGLE (0x7F800000)
-#define FPINF_DOUBLE (((unsigned long long)0x7FF00000 << 32) | 0x00000000)
+#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
#if 1 /* def DEBUG */
#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
#define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : "<format error>"))))))
#endif /* DEBUG */
-static unsigned long long
+static uword64
ValueFPR(fpr,fmt)
int fpr;
FP_formats fmt;
{
- unsigned long long value;
+ uword64 value;
int err = 0;
/* Treat unused register values, as fixed-point 64bit values: */
#endif /* DEBUG */
}
if (fmt != fpr_state[fpr]) {
- callback->printf_filtered(callback,"Warning: FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%08X%08X)\n",fpr,DOFMT(fpr_state[fpr]),DOFMT(fmt),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ sim_warning("FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%08X%08X)",fpr,DOFMT(fpr_state[fpr]),DOFMT(fmt),WORD64HI(IPC),WORD64LO(IPC));
fpr_state[fpr] = fmt_unknown;
}
case fmt_uninterpreted:
case fmt_double:
case fmt_long:
- value = ((FGR[fpr+1] << 32) | (FGR[fpr] & 0xFFFFFFFF));
+ value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
break;
default :
SignalException(SimulatorFault,"Unrecognised FP format in ValueFPR()");
#ifdef DEBUG
- printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%08X%08X : PC = 0x%08X%08X : SizeFGR() = %d\n",fpr,DOFMT(fmt),(unsigned int)(value>>32),(unsigned int)(value&0xFFFFFFFF),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF),SizeFGR());
+ printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%08X%08X : PC = 0x%08X%08X : SizeFGR() = %d\n",fpr,DOFMT(fmt),WORD64HI(value),WORD64LO(value),WORD64HI(IPC),WORD64LO(IPC),SizeFGR());
#endif /* DEBUG */
return(value);
StoreFPR(fpr,fmt,value)
int fpr;
FP_formats fmt;
- unsigned long long value;
+ uword64 value;
{
int err = 0;
#ifdef DEBUG
- printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%08X%08X : PC = 0x%08X%08X : SizeFGR() = %d\n",fpr,DOFMT(fmt),(unsigned int)(value>>32),(unsigned int)(value&0xFFFFFFFF),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF),SizeFGR());
+ printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%08X%08X : PC = 0x%08X%08X : SizeFGR() = %d\n",fpr,DOFMT(fmt),WORD64HI(value),WORD64LO(value),WORD64HI(IPC),WORD64LO(IPC),SizeFGR());
#endif /* DEBUG */
if (SizeFGR() == 64) {
switch (fmt) {
case fmt_single :
case fmt_word :
- FGR[fpr] = (((unsigned long long)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
+ FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
fpr_state[fpr] = fmt;
break;
err = -1;
break;
}
- } else
- UndefinedResult();
+ }
+#if defined(WARN_RESULT)
+ else
+ UndefinedResult();
+#endif /* WARN_RESULT */
if (err)
SignalException(SimulatorFault,"Unrecognised FP format in StoreFPR()");
#ifdef DEBUG
- printf("DBG: StoreFPR: fpr[%d] = 0x%08X%08X (format %s)\n",fpr,(unsigned int)(FGR[fpr]>>32),(unsigned int)(FGR[fpr]&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: StoreFPR: fpr[%d] = 0x%08X%08X (format %s)\n",fpr,WORD64HI(FGR[fpr]),WORD64LO(FGR[fpr]),DOFMT(fmt));
#endif /* DEBUG */
return;
static int
NaN(op,fmt)
- unsigned long long op;
+ uword64 op;
FP_formats fmt;
{
int boolean = 0;
}
#ifdef DEBUG
-printf("DBG: NaN: returning %d for 0x%08X%08X (format = %s)\n",boolean,(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF),DOFMT(fmt));
+printf("DBG: NaN: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
#endif /* DEBUG */
return(boolean);
static int
Infinity(op,fmt)
- unsigned long long op;
+ uword64 op;
FP_formats fmt;
{
int boolean = 0;
#ifdef DEBUG
- printf("DBG: Infinity: format %s 0x%08X%08X (PC = 0x%08X%08X)\n",DOFMT(fmt),(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ printf("DBG: Infinity: format %s 0x%08X%08X (PC = 0x%08X%08X)\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op),WORD64HI(IPC),WORD64LO(IPC));
#endif /* DEBUG */
/* Check if (((E - bias) == (E_max + 1)) && (fraction == 0)). We
}
#ifdef DEBUG
- printf("DBG: Infinity: returning %d for 0x%08X%08X (format = %s)\n",boolean,(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: Infinity: returning %d for 0x%08X%08X (format = %s)\n",boolean,WORD64HI(op),WORD64LO(op),DOFMT(fmt));
#endif /* DEBUG */
return(boolean);
static int
Less(op1,op2,fmt)
- unsigned long long op1;
- unsigned long long op2;
+ uword64 op1;
+ uword64 op2;
FP_formats fmt;
{
int boolean = 0;
+ /* Argument checking already performed by the FPCOMPARE code */
+
#ifdef DEBUG
- printf("DBG: Less: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op1>>32),(unsigned int)(op1&0xFFFFFFFF),(unsigned int)(op2>>32),(unsigned int)(op2&0xFFFFFFFF));
+ printf("DBG: Less: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
-
/* The format type should already have been checked: */
switch (fmt) {
case fmt_single:
static int
Equal(op1,op2,fmt)
- unsigned long long op1;
- unsigned long long op2;
+ uword64 op1;
+ uword64 op2;
FP_formats fmt;
{
int boolean = 0;
+ /* Argument checking already performed by the FPCOMPARE code */
+
#ifdef DEBUG
- printf("DBG: Equal: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op1>>32),(unsigned int)(op1&0xFFFFFFFF),(unsigned int)(op2>>32),(unsigned int)(op2&0xFFFFFFFF));
+ printf("DBG: Equal: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
-
/* The format type should already have been checked: */
switch (fmt) {
case fmt_single:
return(boolean);
}
-static unsigned long long
+static uword64
+AbsoluteValue(op,fmt)
+ uword64 op;
+ FP_formats fmt;
+{
+ uword64 result;
+
+#ifdef DEBUG
+ printf("DBG: AbsoluteValue: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
+#endif /* DEBUG */
+
+ /* The format type should already have been checked: */
+ switch (fmt) {
+ case fmt_single:
+ {
+ unsigned int wop = (unsigned int)op;
+ float tmp = ((float)fabs((double)*(float *)&wop));
+ result = (uword64)*(unsigned int *)&tmp;
+ }
+ break;
+ case fmt_double:
+ {
+ double tmp = (fabs(*(double *)&op));
+ result = *(uword64 *)&tmp;
+ }
+ }
+
+ return(result);
+}
+
+static uword64
Negate(op,fmt)
- unsigned long long op;
+ uword64 op;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Negate: %s: op = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF));
+ printf("DBG: Negate: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
#endif /* DEBUG */
/* The format type should already have been checked: */
{
unsigned int wop = (unsigned int)op;
float tmp = ((float)0.0 - *(float *)&wop);
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = ((double)0.0 - *(double *)&op);
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
return(result);
}
-static unsigned long long
+static uword64
Add(op1,op2,fmt)
- unsigned long long op1;
- unsigned long long op2;
+ uword64 op1;
+ uword64 op2;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Add: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op1>>32),(unsigned int)(op1&0xFFFFFFFF),(unsigned int)(op2>>32),(unsigned int)(op2&0xFFFFFFFF));
+ printf("DBG: Add: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
+ /* 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) {
unsigned int wop1 = (unsigned int)op1;
unsigned int wop2 = (unsigned int)op2;
float tmp = (*(float *)&wop1 + *(float *)&wop2);
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = (*(double *)&op1 + *(double *)&op2);
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
#ifdef DEBUG
- printf("DBG: Add: returning 0x%08X%08X (format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: Add: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
#endif /* DEBUG */
return(result);
}
-static unsigned long long
+static uword64
Sub(op1,op2,fmt)
- unsigned long long op1;
- unsigned long long op2;
+ uword64 op1;
+ uword64 op2;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op1>>32),(unsigned int)(op1&0xFFFFFFFF),(unsigned int)(op2>>32),(unsigned int)(op2&0xFFFFFFFF));
+ printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
+ /* 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) {
unsigned int wop1 = (unsigned int)op1;
unsigned int wop2 = (unsigned int)op2;
float tmp = (*(float *)&wop1 - *(float *)&wop2);
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = (*(double *)&op1 - *(double *)&op2);
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
#ifdef DEBUG
- printf("DBG: Sub: returning 0x%08X%08X (format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: Sub: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
#endif /* DEBUG */
return(result);
}
-static unsigned long long
+static uword64
Multiply(op1,op2,fmt)
- unsigned long long op1;
- unsigned long long op2;
+ uword64 op1;
+ uword64 op2;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Multiply: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op1>>32),(unsigned int)(op1&0xFFFFFFFF),(unsigned int)(op2>>32),(unsigned int)(op2&0xFFFFFFFF));
+ printf("DBG: Multiply: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
+ /* 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) {
unsigned int wop1 = (unsigned int)op1;
unsigned int wop2 = (unsigned int)op2;
float tmp = (*(float *)&wop1 * *(float *)&wop2);
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = (*(double *)&op1 * *(double *)&op2);
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
#ifdef DEBUG
- printf("DBG: Multiply: returning 0x%08X%08X (format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: Multiply: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
#endif /* DEBUG */
return(result);
}
-static unsigned long long
+static uword64
Divide(op1,op2,fmt)
- unsigned long long op1;
- unsigned long long op2;
+ uword64 op1;
+ uword64 op2;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Divide: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op1>>32),(unsigned int)(op1&0xFFFFFFFF),(unsigned int)(op2>>32),(unsigned int)(op2&0xFFFFFFFF));
+ printf("DBG: Divide: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
+ /* 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) {
unsigned int wop1 = (unsigned int)op1;
unsigned int wop2 = (unsigned int)op2;
float tmp = (*(float *)&wop1 / *(float *)&wop2);
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = (*(double *)&op1 / *(double *)&op2);
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
#ifdef DEBUG
- printf("DBG: Divide: returning 0x%08X%08X (format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: Divide: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
#endif /* DEBUG */
return(result);
}
-static unsigned long long
+static uword64
Recip(op,fmt)
- unsigned long long op;
+ uword64 op;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Recip: %s: op = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF));
+ printf("DBG: Recip: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
+ /* 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) {
{
unsigned int wop = (unsigned int)op;
float tmp = ((float)1.0 / *(float *)&wop);
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = ((double)1.0 / *(double *)&op);
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
#ifdef DEBUG
- printf("DBG: Recip: returning 0x%08X%08X (format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: Recip: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
#endif /* DEBUG */
return(result);
}
-static unsigned long long
+static uword64
SquareRoot(op,fmt)
- unsigned long long op;
+ uword64 op;
FP_formats fmt;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: SquareRoot: %s: op = 0x%08X%08X\n",DOFMT(fmt),(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF));
+ printf("DBG: SquareRoot: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
#endif /* DEBUG */
- /* TODO: Perform argument error checking */
+ /* 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) {
{
unsigned int wop = (unsigned int)op;
float tmp = ((float)sqrt((double)*(float *)&wop));
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp = (sqrt(*(double *)&op));
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
}
#ifdef DEBUG
- printf("DBG: SquareRoot: returning 0x%08X%08X (format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(fmt));
+ printf("DBG: SquareRoot: returning 0x%08X%08X (format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(fmt));
#endif /* DEBUG */
return(result);
}
-static unsigned long long
+static uword64
Convert(rm,op,from,to)
int rm;
- unsigned long long op;
+ uword64 op;
FP_formats from;
FP_formats to;
{
- unsigned long long result;
+ uword64 result;
#ifdef DEBUG
- printf("DBG: Convert: mode %s : op 0x%08X%08X : from %s : to %s : (PC = 0x%08X%08X)\n",RMMODE(rm),(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF),DOFMT(from),DOFMT(to),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ printf("DBG: Convert: mode %s : op 0x%08X%08X : from %s : to %s : (PC = 0x%08X%08X)\n",RMMODE(rm),WORD64HI(op),WORD64LO(op),DOFMT(from),DOFMT(to),WORD64HI(IPC),WORD64LO(IPC));
#endif /* DEBUG */
/* The value "op" is converted to the destination format, rounding
switch (rm) {
case FP_RM_NEAREST:
- printf("TODO: FPConvert: round(float)\n");
+ /* 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:
- printf("TODO: FPConvert: trunc(float)\n");
+ /* 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:
- printf("TODO: FPConvert: ceil(float)\n");
+ /* Round result to the value closest to, and not less than,
+ the result. */
+ tmp = (float)ceil((double)tmp);
break;
case FP_RM_TOMINF:
- printf("TODO: FPConvert: floor(float)\n");
+ /* Round result to the value closest to, and not greater than,
+ the result. */
+ tmp = (float)floor((double)tmp);
break;
}
- result = (unsigned long long)*(unsigned int *)&tmp;
+ result = (uword64)*(unsigned int *)&tmp;
}
break;
case fmt_double:
{
double tmp;
+ word64 xxx;
switch (from) {
case fmt_single:
break;
case fmt_word:
- tmp = (double)((long long)SIGNEXTEND((op & 0xFFFFFFFF),32));
+ xxx = SIGNEXTEND((op & 0xFFFFFFFF),32);
+ tmp = xxx;
break;
case fmt_long:
- tmp = (double)((long long)op);
+ tmp = (double)((word64)op);
break;
}
+
switch (rm) {
case FP_RM_NEAREST:
- printf("TODO: FPConvert: round(double)\n");
+#ifdef HAVE_ANINT
+ tmp = anint(*(double *)&tmp);
+#else
+ /* TODO: Provide round-to-nearest */
+#endif
break;
case FP_RM_TOZERO:
- printf("TODO: FPConvert: trunc(double)\n");
+#ifdef HAVE_AINT
+ tmp = aint(*(double *)&tmp);
+#else
+ /* TODO: Provide round-to-zero */
+#endif
break;
case FP_RM_TOPINF:
tmp = floor(*(double *)&tmp);
break;
}
- result = *(unsigned long long *)&tmp;
+ result = *(uword64 *)&tmp;
}
break;
case fmt_double:
tmp = (unsigned int)*((double *)&op);
#ifdef DEBUG
- printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op),(unsigned int)(op>>32),(unsigned int)(op&0xFFFFFFFF),tmp);
+ printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op),WORD64HI(op),WORD64LO(op),tmp);
#endif /* DEBUG */
break;
}
- result = (unsigned long long)tmp;
+ result = (uword64)tmp;
} else { /* fmt_long */
switch (from) {
case fmt_single:
{
unsigned int wop = (unsigned int)op;
- result = (unsigned long long)*((float *)&wop);
+ result = (uword64)*((float *)&wop);
}
break;
case fmt_double:
- result = (unsigned long long)*((double *)&op);
+ result = (uword64)*((double *)&op);
break;
}
}
}
#ifdef DEBUG
- printf("DBG: Convert: returning 0x%08X%08X (to format = %s)\n",(unsigned int)(result>>32),(unsigned int)(result&0xFFFFFFFF),DOFMT(to));
+ printf("DBG: Convert: returning 0x%08X%08X (to format = %s)\n",WORD64HI(result),WORD64LO(result),DOFMT(to));
#endif /* DEBUG */
return(result);
#if defined(HASFPU)
case 1:
#ifdef DEBUG
- printf("DBG: COP_LW: memword = 0x%08X (unsigned long long)memword = 0x%08X%08X\n",memword,(unsigned int)(((unsigned long long)memword)>>32),(unsigned int)(((unsigned long long)memword)&0xFFFFFFFF));
+ printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%08X%08X\n",memword,WORD64HI(memword),WORD64LO(memword));
#endif
- StoreFPR(coproc_reg,fmt_uninterpreted,(unsigned long long)memword);
+ StoreFPR(coproc_reg,fmt_uninterpreted,(uword64)memword);
break;
#endif /* HASFPU */
default:
- callback->printf_filtered(callback,"COP_LW(%d,%d,0x%08X) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+#if 0 /* this should be controlled by a configuration option */
+ callback->printf_filtered(callback,"COP_LW(%d,%d,0x%08X) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,WORD64HI(IPC),WORD64LO(IPC));
+#endif
break;
}
static void
COP_LD(coproc_num,coproc_reg,memword)
int coproc_num, coproc_reg;
- unsigned long long memword;
+ uword64 memword;
{
switch (coproc_num) {
#if defined(HASFPU)
#endif /* HASFPU */
default:
- callback->printf_filtered(callback,"COP_LD(%d,%d,0x%08X%08X) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,(unsigned int)(memword >> 32),(unsigned int)(memword & 0xFFFFFFFF),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+#if 0 /* this message should be controlled by a configuration option */
+ callback->printf_filtered(callback,"COP_LD(%d,%d,0x%08X%08X) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,WORD64HI(memword),WORD64LO(memword),WORD64HI(IPC),WORD64LO(IPC));
+#endif
break;
}
#endif /* HASFPU */
default:
- callback->printf_filtered(callback,"COP_SW(%d,%d) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+#if 0 /* should be controlled by configuration option */
+ callback->printf_filtered(callback,"COP_SW(%d,%d) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,WORD64HI(IPC),WORD64LO(IPC));
+#endif
break;
}
return(value);
}
-static unsigned long long
+static uword64
COP_SD(coproc_num,coproc_reg)
int coproc_num, coproc_reg;
{
- unsigned long long value = 0;
+ uword64 value = 0;
switch (coproc_num) {
#if defined(HASFPU)
case 1:
#endif /* HASFPU */
default:
- callback->printf_filtered(callback,"COP_SD(%d,%d) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+#if 0 /* should be controlled by configuration option */
+ callback->printf_filtered(callback,"COP_SD(%d,%d) at IPC = 0x%08X%08X : TODO (architecture specific)\n",coproc_num,coproc_reg,WORD64HI(IPC),WORD64LO(IPC));
+#endif
break;
}
int rt = ((instruction >> 16) & 0x1F);
int rd = ((instruction >> 11) & 0x1F);
if (code == 0x00) { /* MF : move from */
+#if 0 /* message should be controlled by configuration option */
callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
+#endif
GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
} else { /* MT : move to */
/* CPR[0,rd] = GPR[rt]; */
+#if 0 /* should be controlled by configuration option */
callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
+#endif
}
} else
- callback->printf_filtered(callback,"Warning: Unrecognised COP0 instruction 0x%08X at IPC = 0x%08X%08X : No handler present\n",instruction,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
- /* TODO: When executed an ERET or RFE instruction we should
+ sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
+ /* 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 */
- callback->printf_filtered(callback,"Warning: COP2 instruction 0x%08X at IPC = 0x%08X%08X : No handler present\n",instruction,(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ sim_warning("COP2 instruction 0x%08X at IPC = 0x%08X%08X : No handler present",instruction,WORD64HI(IPC),WORD64LO(IPC));
break;
case 1: /* should not occur (FPU co-processor) */
/* main controlling loop */
do {
/* Fetch the next instruction from the simulator memory: */
- unsigned long long vaddr = (unsigned long long)PC;
- unsigned long long paddr;
+ uword64 vaddr = (uword64)PC;
+ uword64 paddr;
int cca;
unsigned int instruction;
int dsstate = (state & simDELAYSLOT);
#ifdef DEBUG
if (dsstate)
- callback->printf_filtered(callback,"DBG: DSPC = 0x%08X%08X\n",(unsigned int)(DSPC>>32),(unsigned int)(DSPC&0xFFFFFFFF));
+ callback->printf_filtered(callback,"DBG: DSPC = 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
#endif /* DEBUG */
if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) { /* Copy the action of the LW instruction */
- unsigned int reverse = (ReverseEndian ? 1 : 0);
- unsigned int bigend = (BigEndianCPU ? 1 : 0);
- unsigned long long value;
+ unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
+ unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
+ uword64 value;
unsigned int byte;
- paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 2)));
+ paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
value = LoadMemory(cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL);
- byte = ((vaddr & 0x7) ^ (bigend << 2));
+ byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
} else {
- fprintf(stderr,"Cannot translate address for PC = 0x%08X%08X failed\n",(unsigned int)(PC>>32),(unsigned int)(PC&0xFFFFFFFF));
+ fprintf(stderr,"Cannot translate address for PC = 0x%08X%08X failed\n",WORD64HI(PC),WORD64LO(PC));
exit(1);
}
#ifdef DEBUG
- callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction,(unsigned int)(PC>>32),(unsigned int)(PC&0xFFFFFFFF));
+ callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction,WORD64HI(PC),WORD64LO(PC));
#endif /* DEBUG */
#if !defined(FASTSIM) || defined(PROFILE)
instruction_fetches++;
+ /* Since we increment above, the value should only ever be zero if
+ we have just overflowed: */
+ if (instruction_fetches == 0)
+ instruction_fetch_overflow++;
#if defined(PROFILE)
if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
int n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
if (!(state & simSKIPNEXT)) {
/* Include the simulator engine */
#include "engine.c"
-#if ((GPRLEN == 64) && !defined(PROCESSOR_64BIT)) || ((GPRLEN == 32) && defined(PROCESSOR_64BIT))
+#if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
#error "Mismatch between run-time simulator code and simulation engine"
#endif
than within the simulator, since it will help keep the simulator
small. */
if (ZERO != 0) {
- callback->printf_filtered(callback,"SIM Warning: The ZERO register has been updated with 0x%08X%08X (PC = 0x%08X%08X)\nSIM Warning: Resetting back to zero\n",(unsigned int)(ZERO>>32),(unsigned int)(ZERO&0xFFFFFFFF),(unsigned int)(IPC>>32),(unsigned int)(IPC&0xFFFFFFFF));
+ sim_warning("The ZERO register has been updated with 0x%08X%08X (PC = 0x%08X%08X) (reset back to zero)",WORD64HI(ZERO),WORD64LO(ZERO),WORD64HI(IPC),WORD64LO(IPC));
ZERO = 0; /* reset back to zero before next instruction */
}
#endif /* WARN_ZERO */
executed, then update the PC to its new value: */
if (dsstate) {
#ifdef DEBUG
- printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",(unsigned int)(DSPC>>32),(unsigned int)(DSPC&0xFFFFFFFF));
+ printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
#endif /* DEBUG */
PC = DSPC;
state &= ~simDELAYSLOT;
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%08X%08X\n",index,(unsigned int)(pending_slot_value[index]>>32),(unsigned int)(pending_slot_value[index]&0xFFFFFFFF));
+ printf("pending_slot_value[%d] = 0x%08X%08X\n",index,WORD64HI(pending_slot_value[index]),WORD64LO(pending_slot_value[index]));
#endif /* DEBUG */
if (pending_slot_reg[index] == COCIDX) {
SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
#endif /* HASFPU */
}
#ifdef DEBUG
- printf("registers[%d] = 0x%08X%08X\n",pending_slot_reg[index],(unsigned int)(registers[pending_slot_reg[index]]>>32),(unsigned int)(registers[pending_slot_reg[index]]&0xFFFFFFFF));
+ printf("registers[%d] = 0x%08X%08X\n",pending_slot_reg[index],WORD64HI(registers[pending_slot_reg[index]]),WORD64LO(registers[pending_slot_reg[index]]));
#endif /* DEBUG */
pending_slot_reg[index] = (LAST_EMBED_REGNUM + 1);
pending_out++;