diff options
Diffstat (limited to 'sim/mips/interp.c')
-rw-r--r-- | sim/mips/interp.c | 202 |
1 files changed, 144 insertions, 58 deletions
diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 18f79ba..27b7746 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -15,7 +15,7 @@ $Revision$ $Author$ - $Date$ + $Date$ NOTEs: @@ -63,8 +63,8 @@ code on the hardware. #include "getopt.h" #include "libiberty.h" -#include "remote-sim.h" /* GDB simulator interface */ #include "callback.h" /* GDB simulator callback interface */ +#include "remote-sim.h" /* GDB simulator interface */ #include "support.h" /* internal support manifests */ @@ -186,7 +186,9 @@ static host_callback *callback = NULL; /* handle onto the current callback struc order that the tools are built, we cannot rely on a configured GDB world whilst constructing the simulator. This means we have to assume the GDB register number mapping. */ +#ifndef TM_MIPS_H #define LAST_EMBED_REGNUM (89) +#endif /* To keep this default simulator simple, and fast, we use a direct vector of registers. The internal simulator engine then uses @@ -322,6 +324,26 @@ static int pending_slot_count[PSLOTS]; static int pending_slot_reg[PSLOTS]; static ut_reg pending_slot_value[PSLOTS]; +/*---------------------------------------------------------------------------*/ +/*-- GDB simulator interface ------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +static void dotrace PARAMS((FILE *tracefh,int type,SIM_ADDR 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((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 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)); + +/*---------------------------------------------------------------------------*/ + /* 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); */\ @@ -484,22 +506,6 @@ 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((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 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) char *args; @@ -752,7 +758,7 @@ Re-compile simulator with \"-DPROFILE\" to enable this option.\n"); if (!monitor) { fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n",monitor_size); } else { - int loop; + unsigned loop; /* Entry into the IDT monitor is via fixed address vectors, and not using machine instructions. To avoid clashing with use of the MIPS TRAP system, we place our own (simulator specific) @@ -802,7 +808,8 @@ Re-compile simulator with \"-DPROFILE\" to enable this option.\n"); value = 17; break; } - value = (monitor_base + (value * 8)); + /* 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,paddr,vaddr,isRAW); else @@ -895,7 +902,7 @@ sim_close (quitting) if ((state & simPROFILE) && (profile_hist != NULL)) { unsigned short *p = profile_hist; FILE *pf = fopen("gmon.out","wb"); - int loop; + unsigned loop; if (pf == NULL) sim_warning("Failed to open \"gmon.out\" profile file"); @@ -929,8 +936,9 @@ sim_close (quitting) #endif /* PROFILE */ #if defined(TRACE) - if (tracefh != stderr) + if (tracefh != NULL && tracefh != stderr) fclose(tracefh); + tracefh = NULL; state &= ~simTRACE; #endif /* TRACE */ @@ -1145,7 +1153,7 @@ sim_fetch_register (rn,memory) sim_warning("Invalid register width for %d (register fetch ignored)",rn); else { if (register_widths[rn] == 32) - *((unsigned int *)memory) = host_swap_word(registers[rn] & 0xFFFFFFFF); + *((unsigned int *)memory) = host_swap_word((unsigned int)(registers[rn] & 0xFFFFFFFF)); else /* 64bit register */ *((uword64 *)memory) = host_swap_long(registers[rn]); } @@ -1326,7 +1334,7 @@ sim_kill () return; } -int +ut_reg sim_get_quit_code () { /* The standard MIPS PCS (Procedure Calling Standard) uses V0(r2) as @@ -1541,7 +1549,6 @@ sim_monitor(reason) switch (reason) { case 6: /* int open(char *path,int flags) */ { - const char *ptr; uword64 paddr; int cca; if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) @@ -1553,7 +1560,6 @@ sim_monitor(reason) case 7: /* int read(int file,char *ptr,int len) */ { - const char *ptr; uword64 paddr; int cca; if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) @@ -1565,7 +1571,6 @@ sim_monitor(reason) case 8: /* int write(int file,char *ptr,int len) */ { - const char *ptr; uword64 paddr; int cca; if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) @@ -1584,10 +1589,10 @@ sim_monitor(reason) char tmp; if (callback->read_stdin(callback,&tmp,sizeof(char)) != sizeof(char)) { sim_error("Invalid return from character read"); - V0 = -1; + V0 = (ut_reg)-1; } else - V0 = tmp; + V0 = (ut_reg)tmp; } break; @@ -1722,7 +1727,7 @@ sim_monitor(reason) } } if (strchr ("dobxXu", *s)) { - long long lv = (long long)*ap++; + word64 lv = (word64) *ap++; if (*s == 'b') callback->printf_filtered(callback,"<binary not supported>"); else { @@ -1733,7 +1738,11 @@ sim_monitor(reason) callback->printf_filtered(callback,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); callback->printf_filtered(callback,tmp,dbl); trunc = 0; @@ -1757,8 +1766,12 @@ sim_monitor(reason) } void +#ifdef _MSC_VER +sim_warning(char *fmt,...) +#else sim_warning(fmt) char *fmt; +#endif { va_list ap; va_start(ap,fmt); @@ -1778,8 +1791,12 @@ sim_warning(fmt) } void +#ifdef _MSC_VER +sim_error(char *fmt,...) +#else sim_error(fmt) char *fmt; +#endif { va_list ap; va_start(ap,fmt); @@ -1869,17 +1886,23 @@ getnum(value) to construct an end product, rather than a processor). They currently have an ARM version of their tool called ChARM. */ + static +#ifdef _MSC_VER +void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...) +#else void dotrace(tracefh,type,address,width,comment) FILE *tracefh; int type; - unsigned int address; + SIM_ADDR address; int width; char *comment; +#endif { if (state & simTRACE) { va_list ap; - fprintf(tracefh,"%d %08x ; width %d ; ",type,address,width); + fprintf(tracefh,"%d %08x%08x ; width %d ; ", + type,(unsigned long)(address>>32),(unsigned long)(address&0xffffffff),width); va_start(ap,comment); fprintf(tracefh,comment,ap); va_end(ap); @@ -1910,68 +1933,106 @@ void dotrace(tracefh,type,address,width,comment) simulation, at the cost of increasing the image and source size. */ static unsigned int +#ifdef _MSC_VER +xfer_direct_word(unsigned char *memory) +#else xfer_direct_word(memory) unsigned char *memory; +#endif { return *((unsigned int *)memory); } static uword64 +#ifdef _MSC_VER +xfer_direct_long(unsigned char *memory) +#else xfer_direct_long(memory) unsigned char *memory; +#endif { return *((uword64 *)memory); } static unsigned int +#ifdef _MSC_VER +swap_direct_word(unsigned int data) +#else swap_direct_word(data) unsigned int data; +#endif { return data; } static uword64 +#ifdef _MSC_VER +swap_direct_long(uword64 data) +#else swap_direct_long(data) uword64 data; +#endif { return data; } static unsigned int +#ifdef _MSC_VER +xfer_big_word(unsigned char *memory) +#else xfer_big_word(memory) unsigned char *memory; +#endif { return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]); } static uword64 +#ifdef _MSC_VER +xfer_big_long(unsigned char *memory) +#else xfer_big_long(memory) unsigned char *memory; +#endif { 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]); + | ((uword64)memory[4] << 24) | ((uword64)memory[5] << 16) + | ((uword64)memory[6] << 8) | ((uword64)memory[7])); } static unsigned int +#ifdef _MSC_VER +xfer_little_word(unsigned char *memory) +#else xfer_little_word(memory) unsigned char *memory; +#endif { return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]); } static uword64 +#ifdef _MSC_VER +xfer_little_long(unsigned char *memory) +#else xfer_little_long(memory) unsigned char *memory; +#endif { 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]); + | ((uword64)memory[3] << 24) | ((uword64)memory[2] << 16) + | ((uword64)memory[1] << 8) | (uword64)memory[0]); } static unsigned int +#ifdef _MSC_VER +swap_word(unsigned int data) +#else swap_word(data) unsigned int data; +#endif { unsigned int result; result = data ^ ((data << 16) | (data >> 16)); @@ -1981,8 +2042,12 @@ swap_word(data) } static uword64 +#ifdef _MSC_VER +swap_long(uword64 data) +#else swap_long(data) uword64 data; +#endif { unsigned int tmphi = WORD64HI(data); unsigned int tmplo = WORD64LO(data); @@ -2134,7 +2199,7 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) 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; + *pAddr = (SIM_ADDR)-1; if (!raw) /* only generate exceptions on real memory transfers */ SignalException((LorS == isSTORE) ? AddressStore : AddressLoad); else @@ -2472,8 +2537,12 @@ SyncOperation(stype) that aborts the instruction. The instruction operation pseudocode will never see a return from this function call. */ static void +#ifdef _MSC_VER +SignalException (int exception,...) +#else SignalException(exception) int exception; +#endif { /* Ensure that any active atomic read/modify/write operation will fail: */ LLBIT = 0; @@ -2514,7 +2583,7 @@ SignalException(exception) } default: -#if 1 /* def DEBUG */ +#ifdef DEBUG if (exception != BreakPoint) callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%08X%08X\n",exception,WORD64HI(IPC),WORD64LO(IPC)); #endif /* DEBUG */ @@ -2523,21 +2592,26 @@ SignalException(exception) /* 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 + + /* Keep a copy of the current A0 in-case this is the program exit + breakpoint: */ + if (exception == BreakPoint) { + va_list ap; + unsigned int instruction; + va_start(ap,exception); + instruction = va_arg(ap,unsigned int); + va_end(ap); + /* Check for our special terminating BREAK: */ + if ((instruction & 0x03FFFFC0) == 0x03ff0000) { + rcexit = (unsigned int)(A0 & 0xFFFFFFFF); + state &= ~simEXCEPTION; + state |= simEXIT; + } + } + + /* Store exception code into current exception id variable (used + by exit code): */ CAUSE = (exception << 2); if (state & simDELAYSLOT) { CAUSE |= cause_BD; @@ -3309,14 +3383,24 @@ SquareRoot(op,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 } break; case fmt_double: { +#ifdef HAVE_SQRT double tmp = (sqrt(*(double *)&op)); result = *(uword64 *)&tmp; +#else + /* TODO: Provide square-root */ + result = (uword64)0; +#endif } break; } @@ -3360,7 +3444,7 @@ Convert(rm,op,from,to) break; case fmt_long: - tmp = (float)((int)op); + tmp = (float)((word64)op); break; } @@ -3424,7 +3508,7 @@ Convert(rm,op,from,to) case fmt_word: xxx = SIGNEXTEND((op & 0xFFFFFFFF),32); - tmp = xxx; + tmp = (double)xxx; break; case fmt_long: @@ -3475,16 +3559,16 @@ Convert(rm,op,from,to) SignalException(FPE); } else { if (to == fmt_word) { - unsigned int tmp; + int tmp; switch (from) { case fmt_single: { unsigned int wop = (unsigned int)op; - tmp = (unsigned int)*((float *)&wop); + tmp = (int)*((float *)&wop); } break; case fmt_double: - tmp = (unsigned int)*((double *)&op); + tmp = (int)*((double *)&op); #ifdef DEBUG printf("DBG: from double %.30f (0x%08X%08X) to word: 0x%08X\n",*((double *)&op),WORD64HI(op),WORD64LO(op),tmp); #endif /* DEBUG */ @@ -3492,17 +3576,19 @@ Convert(rm,op,from,to) } result = (uword64)tmp; } else { /* fmt_long */ + word64 tmp; switch (from) { case fmt_single: { unsigned int wop = (unsigned int)op; - result = (uword64)*((float *)&wop); + tmp = (word64)*((float *)&wop); } break; case fmt_double: - result = (uword64)*((double *)&op); + tmp = (word64)*((double *)&op); break; } + result = (uword64)tmp; } } break; @@ -3797,7 +3883,7 @@ simulate () 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)); + unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2)); if (n < profile_nsamples) { /* NOTE: The counts for the profiling bins are only 16bits wide */ if (profile_hist[n] != USHRT_MAX) |