aboutsummaryrefslogtreecommitdiff
path: root/sim/sh/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/sh/interp.c')
-rw-r--r--sim/sh/interp.c599
1 files changed, 402 insertions, 197 deletions
diff --git a/sim/sh/interp.c b/sim/sh/interp.c
index 0f3e5d5..d6a528d 100644
--- a/sim/sh/interp.c
+++ b/sim/sh/interp.c
@@ -27,7 +27,7 @@
#include "../../newlib/libc/sys/sh/sys/syscall.h"
#define O_RECOMPILE 85
#define DEFINE_TABLE
-
+/*#define ACE_FAST*/
#define DISASSEMBLER_TABLE
#define SBIT(x) ((x)&sbit)
@@ -51,19 +51,21 @@
#define PC pc
#define C cycles
-char *fail()
+int
+fail ()
{
-
+ abort ();
}
-
+#define BUSERROR(addr, mask) \
+ if (addr & ~mask) { saved_state.asregs.exception = SIGBUS;}
/* Define this to enable register lifetime checking.
- The compiler generates "add #0,rn" insns to mark registers as invalid,
+ The compiler generates "add #0,rn" insns to mark registers as invalid,
the simulator uses this info to call fail if it finds a ref to an invalid
register before a def
-
+
#define PARANOID
*/
@@ -78,61 +80,221 @@ int valid[16];
#define UNDEF(x)
#endif
-
-#ifdef TARGET_BIG_ENDIAN
-#if 0
-#define LMEM(x) *((long *)(memory+((x)&maskl)))
-#define BMEM(x) *((char *)(memory+((x)&maskb)))
-#define UWMEM(x) *((unsigned short *)(memory+((x)&maskw)))
-#define SWMEM(x) *((short *)(memory+((x)&maskw)))
-#define WLAT(x,value) (LMEM(x) = value)
-#define RLAT(x) (LMEM(x))
-#define WWAT(x,value) (UWMEM(x) = value)
-#define RSWAT(x) (SWMEM(x))
-#define RUWAT(x) (UWMEM(x))
-#define WBAT(x,value) (BMEM(x) = value)
-#define RBAT(x) (BMEM(x))
+#ifdef __GNUC__
+#define INLINE inline
#else
-#define LMEM(x) ((x)&maskl ? fail() : *((long *)(memory+((x)&maskl))))
-#define BMEM(x) ((x) &maskb ? fail() : *((char *)(memory+((x)&maskb))))
-#define UWMEM(x) ((x)&maskw ? fail() : *((unsigned short *)(memory+((x)&maskw))))
-#define SWMEM(x) ((x)&maskw ? fail() : *((short *)(memory+((x)&maskw))))
-#define WLAT(x,value) (LMEM(x) = value)
-#define RLAT(x) (LMEM(x))
-#define WWAT(x,value) (UWMEM(x) = value)
-#define RSWAT(x) (SWMEM(x))
-#define RUWAT(x) (UWMEM(x))
-#define WBAT(x,value) (BMEM(x) = value)
-#define RBAT(x) (BMEM(x))
+#define INLINE
#endif
-#else
-/* For little endian or unknown host machines */
-#define WLAT(x,value)\
-{ int v = value; unsigned char *p = memory + ((x) & maskl);\
- p[0] =v>>24;p[1] = v>>16;p[2]=v>>8;p[3]=v; }
-#define WWAT(x,value)\
-{ int v = value; unsigned char *p = memory + (x & maskw);p[0] =v>>8;p[1] = v ;}
+/* These variables are at file scope so that functions other than
+ sim_resume can use the fetch/store macros */
-#define WBAT(x,value)\
-{ unsigned char *p = memory + (x & maskb);p[0] =value;}
+static int little_endian;
-#define RLAT(x)\
- ((memory[x&maskl]<<24)|(memory[(x&maskl)+1]<<16)|(memory[(x&maskl)+2]<<8)| (memory[(x&maskl)+3]))
+#if 1
+static int maskl = ~0;
+static int maskw = ~0;
+#endif
+typedef union
+{
-#define RWAT(x)\
- ((memory[x&maskw]<<8)|(memory[(x&maskw)+1]))
+ struct
+ {
-#define RBAT(x)\
- ((memory[x&maskb]))
+ int regs[16];
+ int pc;
+ int pr;
-#define RUWAT(x) (RWAT(x) & 0xffff)
-#define RSWAT(x) ((short)(RWAT(x)))
-#define RSBAT(x) (SEXT(RBAT(x)))
+ int gbr;
+ int vbr;
+ int mach;
+ int macl;
+
+
+ union
+ {
+ struct
+ {
+ unsigned int d0:22;
+ unsigned int m:1;
+ unsigned int q:1;
+ unsigned int i:4;
+ unsigned int d1:2;
+ unsigned int s:1;
+ unsigned int t:1;
+ }
+ bits;
+ int word;
+ }
+ sr;
+ int ticks;
+ int stalls;
+ int cycles;
+ int insts;
+
+
+ int prevlock;
+ int thislock;
+ int exception;
+ int msize;
+#define PROFILE_FREQ 1
+#define PROFILE_SHIFT 2
+ int profile;
+ unsigned short *profile_hist;
+ unsigned char *memory;
+
+ }
+ asregs;
+ int asints[28];
+
+} saved_state_type;
+saved_state_type saved_state;
+
+static void INLINE
+wlat_little (memory, x, value, maskl)
+ unsigned char *memory;
+{
+ int v = value;
+ unsigned char *p = memory + ((x) & maskl);
+ BUSERROR(x, maskl);
+ p[3] = v >> 24;
+ p[2] = v >> 16;
+ p[1] = v >> 8;
+ p[0] = v;
+}
+
+static void INLINE
+wwat_little (memory, x, value, maskw)
+ unsigned char *memory;
+{
+ int v = value;
+ unsigned char *p = memory + ((x) & maskw);
+ BUSERROR(x, maskw);
+
+ p[1] = v >> 8;
+ p[0] = v;
+}
+
+
+static void INLINE
+wbat_any (memory, x, value, maskb)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + (x & maskb);
+ if (x > 0x5000000)
+ IOMEM (x, 1, value);
+ BUSERROR(x, maskb);
+
+ p[0] = value;
+}
-#endif
+static void INLINE
+wlat_big (memory, x, value, maskl)
+ unsigned char *memory;
+{
+ int v = value;
+ unsigned char *p = memory + ((x) & maskl);
+ BUSERROR(x, maskl);
+
+ p[0] = v >> 24;
+ p[1] = v >> 16;
+ p[2] = v >> 8;
+ p[3] = v;
+}
+
+static void INLINE
+wwat_big (memory, x, value, maskw)
+ unsigned char *memory;
+{
+ int v = value;
+ unsigned char *p = memory + ((x) & maskw);
+ BUSERROR(x, maskw);
+
+ p[0] = v >> 8;
+ p[1] = v;
+}
+
+
+static void INLINE
+wbat_big (memory, x, value, maskb)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + (x & maskb);
+ BUSERROR(x, maskb);
+
+ if (x > 0x5000000)
+ IOMEM (x, 1, value);
+ p[0] = value;
+}
+
+
+
+/* Read functions */
+static int INLINE
+rlat_little (memory, x, maskl)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + ((x) & maskl);
+ BUSERROR(x, maskl);
+
+ return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
+
+}
+
+static int INLINE
+rwat_little (memory, x, maskw)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + ((x) & maskw);
+ BUSERROR(x, maskw);
+
+ return (p[1] << 8) | p[0];
+}
+
+static int INLINE
+rbat_any (memory, x, maskb)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + ((x) & maskb);
+ BUSERROR(x, maskb);
+
+ return p[0];
+}
+
+static int INLINE
+rlat_big (memory, x, maskl)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + ((x) & maskl);
+ BUSERROR(x, maskl);
+
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+
+}
+
+static int INLINE
+rwat_big (memory, x, maskw)
+ unsigned char *memory;
+{
+ unsigned char *p = memory + ((x) & maskw);
+ BUSERROR(x, maskw);
+
+ return (p[0] << 8) | p[1];
+}
+
+
+#define RWAT(x) (little_endian ? rwat_little(memory, x, maskw): rwat_big(memory, x, maskw))
+#define RLAT(x) (little_endian ? rlat_little(memory, x, maskl): rlat_big(memory, x, maskl))
+#define RBAT(x) (rbat_any (memory, x, maskb))
+#define WWAT(x,v) (little_endian ? wwat_little(memory, x, v, maskw): wwat_big(memory, x, v, maskw))
+#define WLAT(x,v) (little_endian ? wlat_little(memory, x, v, maskl): wlat_big(memory, x, v, maskl))
+#define WBAT(x,v) (wbat_any (memory, x, v, maskb))
+
+#define RUWAT(x) (RWAT(x) & 0xffff)
+#define RSWAT(x) ((short)(RWAT(x)))
+#define RSBAT(x) (SEXT(RBAT(x)))
#define SEXT(x) (((x&0xff) ^ (~0x7f))+0x80)
#define SEXTW(y) ((int)((short)y))
@@ -154,69 +316,60 @@ int sim_memory_size = 24;
static int sim_profile_size = 17;
static int nsamples;
-static int sim_timeout;
-typedef union
-{
-
- struct
- {
+#undef TB
+#define TB(x,y)
- int regs[16];
- int pc;
- int pr;
+#define SMR1 (0x05FFFEC8) /* Channel 1 serial mode register */
+#define BRR1 (0x05FFFEC9) /* Channel 1 bit rate register */
+#define SCR1 (0x05FFFECA) /* Channel 1 serial control register */
+#define TDR1 (0x05FFFECB) /* Channel 1 transmit data register */
+#define SSR1 (0x05FFFECC) /* Channel 1 serial status register */
+#define RDR1 (0x05FFFECD) /* Channel 1 receive data register */
- int gbr;
- int vbr;
- int mach;
- int macl;
+#define SCI_RDRF 0x40 /* Recieve data register full */
+#define SCI_TDRE 0x80 /* Transmit data register empty */
+static int
+IOMEM (addr, write, value)
+ int addr;
+ int write;
+ int value;
+{
+ static int io;
+ static char ssr1;
+ int x;
+ static char lastchar;
- union
+ if (write)
+ {
+ switch (addr)
{
- struct
+ case TDR1:
+ if (value != '\r')
{
- unsigned int d0:22;
- unsigned int m:1;
- unsigned int q:1;
- unsigned int i:4;
- unsigned int d1:2;
- unsigned int s:1;
- unsigned int t:1;
+ putchar (value);
+ fflush (stdout);
}
- bits;
- int word;
+ break;
+ }
+ }
+ else
+ {
+ switch (addr)
+ {
+ case RDR1:
+ return getchar ();
}
- sr;
- int ticks;
- int stalls;
- int cycles;
- int insts;
-
-
- int prevlock;
- int thislock;
- int exception;
- int msize;
-#define PROFILE_FREQ 1
-#define PROFILE_SHIFT 2
- int profile;
- unsigned short *profile_hist;
- unsigned char *memory;
-
}
- asregs;
- int asints[28];
-
}
-saved_state_type;
-saved_state_type saved_state;
+
static int
get_now ()
{
- return time((long*)0);
+ return time ((long *) 0);
}
static int
@@ -229,23 +382,19 @@ now_persec ()
static FILE *profile_file;
-static void
-swap (b, n)
- unsigned char *b;
+static void
+swap (memory, n)
+ unsigned char *memory;
int n;
{
- b[0] = n >> 24;
- b[1] = n >> 16;
- b[2] = n >> 8;
- b[3] = n >> 0;
+ WLAT (0, n);
}
-static void
-swap16 (b, n)
- unsigned char *b;
+static void
+swap16 (memory, n)
+ unsigned char *memory;
int n;
{
- b[0] = n >> 8;
- b[1] = n >> 0;
+ WWAT (0, n);
}
static void
@@ -279,32 +428,13 @@ ptr (x)
return (char *) (x + saved_state.asregs.memory);
}
-static char *wwat(ptr, val)
-char *ptr;
-int val;
-{
- ptr[0] = val >> 8;
- ptr[1] = val;
- return ptr+2;
-}
-
-static char *wlat(ptr,val)
-char *ptr;
-int val;
-{
- ptr[0] = val>> 24;
- ptr[1] = val >> 16;
- ptr[2] = val >>8;
- ptr[3] = val;
- return ptr+4;
-}
/* Simulate a monitor trap, put the result into r0 and errno into r1 */
-
static void
-trap (i, regs)
+trap (i, regs, memory, maskl, maskw, little_endian)
int i;
int *regs;
+ unsigned char *memory;
{
switch (i)
{
@@ -314,6 +444,23 @@ trap (i, regs)
case 2:
saved_state.asregs.exception = SIGQUIT;
break;
+#if 0
+ case 8:
+ trap8 (ptr (regs[4]));
+ break;
+ case 9:
+ trap9 (ptr (regs[4]));
+ break;
+ case 10:
+ trap10 ();
+ break;
+ case 11:
+ regs[0] = trap11 ();
+ break;
+ case 12:
+ regs[0] = trap12 ();
+ break;
+#endif
case 3:
{
extern int errno;
@@ -322,35 +469,38 @@ trap (i, regs)
switch (regs[4])
{
+
#ifndef __GO32__
- case SYS_fork:
- regs[0] = fork();
- break;
+ case SYS_fork:
+ regs[0] = fork ();
+ break;
case SYS_execve:
- regs[0] = execve(ptr(regs[5]), ptr(regs[6]), ptr(regs[7]));
+ regs[0] = execve (ptr (regs[5]), ptr (regs[6]), ptr (regs[7]));
break;
case SYS_execv:
- regs[0] = execv(ptr(regs[5]), ptr(regs[6]));
+ regs[0] = execv (ptr (regs[5]), ptr (regs[6]));
break;
case SYS_pipe:
{
- char* buf;
+ char *buf;
int host_fd[2];
- buf = ptr(regs[5]);
+ buf = ptr (regs[5]);
- regs[0] = pipe(host_fd);
+ regs[0] = pipe (host_fd);
- buf = wlat(buf, host_fd[0]);
- buf = wlat(buf, host_fd[1]);
+ WLAT (buf, host_fd[0]);
+ buf += 4;
+ WLAT (buf, host_fd[1]);
}
break;
- case SYS_wait:
- regs[0] = wait(ptr(regs[5]));
+ case SYS_wait:
+ regs[0] = wait (ptr (regs[5]));
break;
#endif
+
case SYS_read:
regs[0] = read (regs[5], ptr (regs[6]), regs[7]);
break;
@@ -367,53 +517,65 @@ trap (i, regs)
regs[0] = open (ptr (regs[5]), regs[6]);
break;
case SYS_exit:
- /* EXIT */
+ /* EXIT - caller can look in r5 to work out the
+ reason */
saved_state.asregs.exception = SIGQUIT;
- errno = regs[5];
break;
-
- case SYS_stat: /* added at hmsi */
+
+ case SYS_stat: /* added at hmsi */
/* stat system call */
- {
+ {
struct stat host_stat;
char *buf;
- regs[0] = stat( ptr(regs[5]), &host_stat);
-
- buf = ptr(regs[6]);
-
- buf = wwat(buf, host_stat.st_dev);
- buf = wwat(buf, host_stat.st_ino);
-
- buf = wlat(buf, host_stat.st_mode);
-
- buf = wwat(buf, host_stat.st_nlink);
- buf = wwat(buf, host_stat.st_uid);
- buf = wwat(buf, host_stat.st_gid);
- buf = wwat(buf, host_stat.st_rdev);
-
- buf = wlat(buf, host_stat.st_size);
- buf = wlat(buf, host_stat.st_atime);
- buf = wlat(buf, 0);
- buf = wlat(buf, host_stat.st_mtime);
- buf = wlat(buf, 0);
- buf = wlat(buf, host_stat.st_ctime);
- buf = wlat(buf, 0);
- buf = wlat(buf, host_stat.st_blksize);
- buf = wlat(buf, host_stat.st_blocks);
- }
- break;
+ regs[0] = stat (ptr (regs[5]), &host_stat);
+
+ buf = ptr (regs[6]);
+
+ WWAT (buf, host_stat.st_dev);
+ buf += 2;
+ WWAT (buf, host_stat.st_ino);
+ buf += 2;
+ WLAT (buf, host_stat.st_mode);
+ buf += 4;
+ WWAT (buf, host_stat.st_nlink);
+ buf += 2;
+ WWAT (buf, host_stat.st_uid);
+ buf += 2;
+ WWAT (buf, host_stat.st_gid);
+ buf += 2;
+ WWAT (buf, host_stat.st_rdev);
+ buf += 2;
+ WLAT (buf, host_stat.st_size);
+ buf += 4;
+ WLAT (buf, host_stat.st_atime);
+ buf += 4;
+ WLAT (buf, 0);
+ buf += 4;
+ WLAT (buf, host_stat.st_mtime);
+ buf += 4;
+ WLAT (buf, 0);
+ buf += 4;
+ WLAT (buf, host_stat.st_ctime);
+ buf += 4;
+ WLAT (buf, 0);
+ buf += 4;
+ WLAT (buf, 0);
+ buf += 4;
+ WLAT (buf, 0);
+ buf += 4;
+ }
+ break;
- case SYS_chown:
- regs[0] = chown( ptr(regs[5]), regs[6], regs[7] );
+ case SYS_chown:
+ regs[0] = chown (ptr (regs[5]), regs[6], regs[7]);
break;
case SYS_chmod:
- regs[0] = chmod( ptr(regs[5]), regs[6]);
- break;
- case SYS_utime:
- regs[0] = utime (ptr(regs[5]), ptr(regs[6]));
+ regs[0] = chmod (ptr (regs[5]), regs[6]);
+ break;
+ case SYS_utime:
+ regs[0] = utime (ptr (regs[5]), ptr (regs[6]));
break;
-
default:
abort ();
}
@@ -423,9 +585,9 @@ trap (i, regs)
break;
+ case 0xc3:
case 255:
saved_state.asregs.exception = SIGTRAP;
- saved_state.asregs.exception = 5;
break;
}
@@ -530,7 +692,7 @@ div1 (R, iRn2, iRn1, T)
}
-static void
+static void
dmul (sign, rm, rn)
int sign;
unsigned int rm;
@@ -569,7 +731,16 @@ dmul (sign, rm, rn)
else
{
+#ifdef __GNUC__
+ long long res;
+ long long a = rn;
+ long long b = rm;
+ res = a * b;
+ MACH = res >> 32;
+ MACL = res & 0xffffffff;
+#else
abort ();
+#endif
}
}
@@ -598,7 +769,7 @@ sim_size (power)
if (!saved_state.asregs.memory)
{
fprintf (stderr,
- "Not enough VM for simuation of %d bytes of RAM\n",
+ "Not enough VM for simulation of %d bytes of RAM\n",
saved_state.asregs.msize);
saved_state.asregs.msize = 1;
@@ -607,11 +778,21 @@ sim_size (power)
}
+extern int target_byte_order;
+
+static void
+set_static_little_endian(x)
+int x;
+{
+ little_endian = x;
+}
static
void
init_pointers ()
{
+ register int little_endian = target_byte_order == 1234;
+ set_static_little_endian (little_endian);
if (saved_state.asregs.msize != 1 << sim_memory_size)
{
sim_size (sim_memory_size);
@@ -662,7 +843,7 @@ dump_profile ()
}
-static int
+static int
gotcall (from, to)
int from;
int to;
@@ -674,6 +855,7 @@ gotcall (from, to)
#define MMASKB ((saved_state.asregs.msize -1) & ~0)
+
void
sim_resume (step, siggnal)
int step, siggnal;
@@ -685,6 +867,11 @@ sim_resume (step, siggnal)
register int prevlock;
register int thislock;
register unsigned int doprofile;
+#ifdef __GO32__
+ register int pollcount = 0;
+#endif
+ register int little_endian = target_byte_order == 1234;
+
int tick_start = get_now ();
void (*prev) ();
@@ -699,7 +886,7 @@ sim_resume (step, siggnal)
register int maskb = ((saved_state.asregs.msize - 1) & ~0);
register int maskw = ((saved_state.asregs.msize - 1) & ~1);
register int maskl = ((saved_state.asregs.msize - 1) & ~3);
- register unsigned char *memory ;
+ register unsigned char *memory;
register unsigned int sbit = (1 << 31);
prev = signal (SIGINT, control_c);
@@ -733,23 +920,38 @@ sim_resume (step, siggnal)
{
register unsigned int iword = RUWAT (pc);
register unsigned int ult;
-
+#ifndef ACE_FAST
insts++;
+#endif
top:
#include "code.c"
pc += 2;
+
+#ifdef __GO32__
+ pollcount++;
+ if (pollcount > 1000)
+ {
+ pollcount = 0;
+ if (kbhit()) {
+ int k = getkey();
+ if (k == 1)
+ saved_state.asregs.exception = SIGINT;
+
+ }
+ }
+#endif
+
+#ifndef ACE_FAST
prevlock = thislock;
thislock = 30;
cycles++;
if (cycles >= doprofile)
{
- if (cycles > sim_timeout)
- saved_state.asregs.exception = SIGQUIT;
-
+
saved_state.asregs.cycles += doprofile;
cycles -= doprofile;
if (saved_state.asregs.profile_hist)
@@ -764,10 +966,13 @@ sim_resume (step, siggnal)
}
}
+#endif
}
while (!saved_state.asregs.exception);
- if (saved_state.asregs.exception == SIGILL)
+ if (saved_state.asregs.exception == SIGILL
+ || saved_state.asregs.exception == SIGBUS
+ || (saved_state.asregs.exception == SIGTRAP && !step))
{
pc -= 2;
}
@@ -830,21 +1035,21 @@ sim_read (addr, buffer, size)
void
-sim_store_register (rn, value)
+sim_store_register (rn, memory)
int rn;
- unsigned char *value;
+ unsigned char *memory;
{
- saved_state.asregs.regs[rn] = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3]);
+ init_pointers();
+ saved_state.asregs.regs[rn]=RLAT(0);
}
void
-sim_fetch_register (rn, buf)
+sim_fetch_register (rn, memory)
int rn;
- unsigned char *buf;
+ unsigned char *memory;
{
- int value = ((int *) (&saved_state))[rn];
-
- swap (buf, value);
+ init_pointers();
+ WLAT (0, saved_state.asregs.regs[rn]);
}