summaryrefslogtreecommitdiff
path: root/sim/w65/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/w65/interp.c')
-rw-r--r--sim/w65/interp.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/sim/w65/interp.c b/sim/w65/interp.c
new file mode 100644
index 00000000000..36c4e322c9c
--- /dev/null
+++ b/sim/w65/interp.c
@@ -0,0 +1,388 @@
+/* Simulator for the WDC 65816 architecture.
+
+ Written by Steve Chamberlain of Cygnus Support.
+ sac@cygnus.com
+
+ This file is part of W65 sim
+
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ Cygnus offers the following for use in the public domain. Cygnus
+ makes no warranty with regard to the software or it's performance
+ and the user accepts the software "AS IS" with all faults.
+
+ CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
+ THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <signal.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/param.h>
+#include "bfd.h"
+#include "callback.h"
+#include "remote-sim.h"
+#include "../../newlib/libc/sys/w65/sys/syscall.h"
+
+#include "interp.h"
+
+saved_state_type saved_state;
+
+int
+get_now ()
+{
+ return time ((long *) 0);
+}
+void
+control_c (sig, code, scp, addr)
+ int sig;
+ int code;
+ char *scp;
+ char *addr;
+{
+ saved_state.exception = SIGINT;
+}
+
+wai ()
+{
+ saved_state.exception = SIGTRAP;
+}
+
+
+
+wdm (acc, x)
+ int acc;
+ int x;
+
+{
+int cycles;
+ /* The x points to where the registers live, acc has code */
+
+#define R(arg) (x + arg * 2)
+unsigned R0 = R(0);
+unsigned R4 = R(4);
+unsigned R5 = R(5);
+unsigned R6 = R(6);
+unsigned R7 = R(7);
+unsigned R8 = R(8);
+unsigned char *memory = saved_state.memory;
+ int a1 = fetch16 (R (4));
+ switch (a1)
+ {
+ case SYS_write:
+ {
+ int file = fetch16 (R5);
+ unsigned char *buf = fetch24 (R6) + memory;
+ int len = fetch16 (R8);
+ int res = write (file, buf, len);
+ store16 (R0, res);
+ break;
+ }
+ case 0:
+ printf ("%c", acc);
+ fflush (stdout);
+ break;
+ case 1:
+ saved_state.exception = SIGTRAP;
+ break;
+ default:
+ saved_state.exception = SIGILL;
+ break;
+ }
+}
+
+
+void
+sim_resume (step, insignal)
+ int step;
+ int insignal;
+{
+ void (*prev) ();
+ register unsigned char *memory;
+ if (step)
+ {
+ saved_state.exception = SIGTRAP;
+ }
+ else
+ {
+ saved_state.exception = 0;
+ }
+
+
+ prev = signal (SIGINT, control_c);
+ do
+ {
+ int x = (saved_state.p >> 4) & 1;
+ int m = (saved_state.p >> 5) & 1;
+ if (x == 0 && m == 0)
+ {
+ ifunc_X0_M0 ();
+ }
+ else if (x == 0 && m == 1)
+ {
+ ifunc_X0_M1 ();
+ }
+ else if (x == 1 && m == 0)
+ {
+ ifunc_X1_M0 ();
+ }
+ else if (x == 1 && m == 1)
+ {
+ ifunc_X1_M1 ();
+ }
+ }
+ while (saved_state.exception == 0);
+
+ signal (SIGINT, prev);
+}
+
+
+
+
+init_pointers ()
+{
+ if (!saved_state.memory)
+ {
+ saved_state.memory = calloc (64 * 1024, NUMSEGS);
+ }
+}
+
+int
+sim_write (addr, buffer, size)
+ SIM_ADDR addr;
+ unsigned char *buffer;
+ int size;
+{
+ int i;
+ init_pointers ();
+
+ for (i = 0; i < size; i++)
+ {
+ saved_state.memory[(addr + i) & MMASK] = buffer[i];
+ }
+ return size;
+}
+
+int
+sim_read (addr, buffer, size)
+ SIM_ADDR addr;
+ unsigned char *buffer;
+ int size;
+{
+ int i;
+
+ init_pointers ();
+
+ for (i = 0; i < size; i++)
+ {
+ buffer[i] = saved_state.memory[(addr + i) & MMASK];
+ }
+ return size;
+}
+
+
+
+struct
+{
+ unsigned int *ptr;
+ int size;
+}
+rinfo[] =
+
+{
+ &saved_state.r[0], 2,
+ &saved_state.r[1], 2,
+ &saved_state.r[2], 2,
+ &saved_state.r[3], 2,
+ &saved_state.r[4], 2,
+ &saved_state.r[5], 2,
+ &saved_state.r[6], 2,
+ &saved_state.r[7], 2,
+ &saved_state.r[8], 2,
+ &saved_state.r[9], 2,
+ &saved_state.r[10], 2,
+ &saved_state.r[11], 2,
+ &saved_state.r[12], 2,
+ &saved_state.r[13], 2,
+ &saved_state.r[14], 2,
+ &saved_state.r[15], 4,
+ &saved_state.pc, 4,
+ &saved_state.a, 4,
+ &saved_state.x, 4,
+ &saved_state.y, 4,
+ &saved_state.dbr, 4,
+ &saved_state.d, 4,
+ &saved_state.s, 4,
+ &saved_state.p, 4,
+ &saved_state.ticks, 4,
+ &saved_state.cycles, 4,
+ &saved_state.insts, 4,
+ 0
+};
+
+int
+sim_store_register (rn, value, length)
+ int rn;
+ unsigned char *value;
+ int length;
+{
+ unsigned int val;
+ int i;
+ val = 0;
+ for (i = 0; i < rinfo[rn].size; i++)
+ {
+ val |= (*value++) << (i * 8);
+ }
+
+ *(rinfo[rn].ptr) = val;
+ return -1;
+}
+
+int
+sim_fetch_register (rn, buf, length)
+ int rn;
+ unsigned char *buf;
+ int length;
+{
+ unsigned int val = *(rinfo[rn].ptr);
+ int i;
+
+ for (i = 0; i < rinfo[rn].size; i++)
+ {
+ *buf++ = val;
+ val = val >> 8;
+ }
+ return -1;
+}
+
+
+sim_reg_size (n)
+{
+ return rinfo[n].size;
+}
+int
+sim_trace ()
+{
+ return 0;
+}
+
+void
+sim_stop_reason (reason, sigrc)
+ enum sim_stop *reason;
+ int *sigrc;
+{
+ *reason = sim_stopped;
+ *sigrc = saved_state.exception;
+}
+
+int
+sim_set_pc (x)
+ SIM_ADDR x;
+{
+ saved_state.pc = x;
+ return 0;
+}
+
+
+void
+sim_info (verbose)
+ int verbose;
+{
+ double timetaken = (double) saved_state.ticks;
+ double virttime = saved_state.cycles / 2.0e6;
+
+ printf ("\n\n# instructions executed %10d\n", saved_state.insts);
+ printf ("# cycles %10d\n", saved_state.cycles);
+ printf ("# real time taken %10.4f\n", timetaken);
+ printf ("# virtual time taken %10.4f\n", virttime);
+
+ if (timetaken != 0)
+ {
+ printf ("# cycles/second %10d\n", (int) (saved_state.cycles / timetaken));
+ printf ("# simulation ratio %10.4f\n", virttime / timetaken);
+ }
+
+}
+
+
+
+void
+sim_open (kind, cb, abfd, argv)
+ SIM_OPEN_KIND kind;
+ host_callback *cb;
+ struct _bfd *abfd;
+ char **argv;
+{
+}
+
+
+
+#undef fetch8
+fetch8func (x)
+{
+ if (x & ~MMASK)
+ {
+ saved_state.exception = SIGBUS;
+ return 0;
+ }
+ return saved_state.memory[x];
+}
+
+fetch8 (x)
+{
+return fetch8func(x);
+}
+
+void
+sim_close (quitting)
+ int quitting;
+{
+ /* nothing to do */
+}
+
+int
+sim_load (prog, from_tty)
+ char *prog;
+ int from_tty;
+{
+ /* Return nonzero so gdb will handle it. */
+ return 1;
+}
+
+
+void
+sim_create_inferior (abfd, argv, env)
+ struct _bfd *abfd;
+ char **argv;
+ char **env;
+{
+ SIM_ADDR start_address;
+ int pc;
+ if (abfd != NULL)
+ start_address = bfd_get_start_address (abfd);
+ else
+ start_address = 0; /*??*/
+ /* ??? We assume this is a 4 byte quantity. */
+ pc = start_address;
+ sim_store_register (16, (unsigned char *) &pc);
+}
+
+void
+sim_set_callbacks (ptr)
+struct host_callback_struct *ptr;
+{
+
+}