Add code to support building mn10300 simulator with the common simulator
authorJoyce Janczyn <janczyn@cygnus>
Tue, 24 Mar 1998 20:26:06 +0000 (20:26 +0000)
committerJoyce Janczyn <janczyn@cygnus>
Tue, 24 Mar 1998 20:26:06 +0000 (20:26 +0000)
framework.

sim/mn10300/interp.c

index e3a77450be22483764886982bc35f3215596ce92..039bd177a6644405a03a8f85885a38ba586c00fd 100644 (file)
@@ -1,14 +1,46 @@
 #include <signal.h>
+
+#if WITH_COMMON
+#include "sim-main.h"
+#else
+#include "mn10300_sim.h"
+#endif
+
 #include "sysdep.h"
 #include "bfd.h"
+#include "sim-assert.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 "bfd.h"
+
+#ifndef INLINE
+#ifdef __GNUC__
+#define INLINE inline
+#else
+#define INLINE
+#endif
+#endif
 
-#include "mn10300_sim.h"
 
 host_callback *mn10300_callback;
 int mn10300_debug;
 static SIM_OPEN_KIND sim_kind;
 static char *myname;
 
+#if WITH_COMMON
+#else
 static void dispatch PARAMS ((uint32, uint32, int));
 static long hash PARAMS ((long));
 static void init_system PARAMS ((void));
@@ -169,63 +201,6 @@ dispatch (insn, extension, length)
   PC += length;
 }
 
-/* FIXME These would more efficient to use than load_mem/store_mem,
-   but need to be changed to use the memory map.  */
-
-uint8
-get_byte (x)
-     uint8 *x;
-{
-  return *x;
-}
-
-uint16
-get_half (x)
-     uint8 *x;
-{
-  uint8 *a = x;
-  return (a[1] << 8) + (a[0]);
-}
-
-uint32
-get_word (x)
-      uint8 *x;
-{
-  uint8 *a = x;
-  return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
-}
-
-void
-put_byte (addr, data)
-     uint8 *addr;
-     uint8 data;
-{
-  uint8 *a = addr;
-  a[0] = data;
-}
-
-void
-put_half (addr, data)
-     uint8 *addr;
-     uint16 data;
-{
-  uint8 *a = addr;
-  a[0] = data & 0xff;
-  a[1] = (data >> 8) & 0xff;
-}
-
-void
-put_word (addr, data)
-     uint8 *addr;
-     uint32 data;
-{
-  uint8 *a = addr;
-  a[0] = data & 0xff;
-  a[1] = (data >> 8) & 0xff;
-  a[2] = (data >> 16) & 0xff;
-  a[3] = (data >> 24) & 0xff;
-}
-
 void
 sim_size (power)
      int power;
@@ -283,6 +258,7 @@ compare_simops (arg1, arg2)
   return 0;
 }
 
+
 SIM_DESC
 sim_open (kind, cb, abfd, argv)
      SIM_OPEN_KIND kind;
@@ -825,11 +801,16 @@ sim_info (sd, verbose)
 }
 
 SIM_RC
-sim_create_inferior (sd, argv, env)
+sim_create_inferior (sd, abfd, argv, env)
      SIM_DESC sd;
+     struct _bfd *abfd;
      char **argv;
      char **env;
 {
+  if (abfd != NULL)
+    PC = bfd_get_start_address (abfd);
+  else
+    PC = 0;
   return SIM_RC_OK;
 }
 
@@ -860,24 +841,6 @@ sim_stop_reason (sd, reason, sigrc)
     *sigrc = State.exception;
 }
 
-void
-sim_fetch_register (sd, rn, memory)
-     SIM_DESC sd;
-     int rn;
-     unsigned char *memory;
-{
-  put_word (memory, State.regs[rn]);
-}
-void
-sim_store_register (sd, rn, memory)
-     SIM_DESC sd;
-     int rn;
-     unsigned char *memory;
-{
-  State.regs[rn] = get_word (memory);
-}
-
 int
 sim_read (sd, addr, buffer, size)
      SIM_DESC sd;
@@ -911,11 +874,367 @@ sim_load (sd, prog, abfd, from_tty)
   bfd *prog_bfd;
 
   prog_bfd = sim_load_file (sd, myname, mn10300_callback, prog, abfd,
-                           sim_kind == SIM_OPEN_DEBUG);
+                           sim_kind == SIM_OPEN_DEBUG,
+                           0, sim_write);
   if (prog_bfd == NULL)
     return SIM_RC_FAIL;
-  PC = bfd_get_start_address (prog_bfd);
   if (abfd == NULL)
     bfd_close (prog_bfd);
   return SIM_RC_OK;
 } 
+#endif  /* not WITH_COMMON */
+
+
+#if WITH_COMMON
+
+/* For compatibility */
+SIM_DESC simulator;
+
+/* mn10300 interrupt model */
+
+enum interrupt_type
+{
+  int_reset,
+  int_nmi,
+  int_intov1,
+  int_intp10,
+  int_intp11,
+  int_intp12,
+  int_intp13,
+  int_intcm4,
+  num_int_types
+};
+
+char *interrupt_names[] = {
+  "reset",
+  "nmi",
+  "intov1",
+  "intp10",
+  "intp11",
+  "intp12",
+  "intp13",
+  "intcm4",
+  NULL
+};
+
+
+static void
+do_interrupt (sd, data)
+     SIM_DESC sd;
+     void *data;
+{
+#if 0
+  char **interrupt_name = (char**)data;
+  enum interrupt_type inttype;
+  inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
+
+  /* For a hardware reset, drop everything and jump to the start
+     address */
+  if (inttype == int_reset)
+    {
+      PC = 0;
+      PSW = 0x20;
+      ECR = 0;
+      sim_engine_restart (sd, NULL, NULL, NULL_CIA);
+    }
+
+  /* Deliver an NMI when allowed */
+  if (inttype == int_nmi)
+    {
+      if (PSW & PSW_NP)
+       {
+         /* We're already working on an NMI, so this one must wait
+            around until the previous one is done.  The processor
+            ignores subsequent NMIs, so we don't need to count them.
+            Just keep re-scheduling a single NMI until it manages to
+            be delivered */
+         if (STATE_CPU (sd, 0)->pending_nmi != NULL)
+           sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
+         STATE_CPU (sd, 0)->pending_nmi =
+           sim_events_schedule (sd, 1, do_interrupt, data);
+         return;
+       }
+      else
+       {
+         /* NMI can be delivered.  Do not deschedule pending_nmi as
+             that, if still in the event queue, is a second NMI that
+             needs to be delivered later. */
+         FEPC = PC;
+         FEPSW = PSW;
+         /* Set the FECC part of the ECR. */
+         ECR &= 0x0000ffff;
+         ECR |= 0x10;
+         PSW |= PSW_NP;
+         PSW &= ~PSW_EP;
+         PSW |= PSW_ID;
+         PC = 0x10;
+         sim_engine_restart (sd, NULL, NULL, NULL_CIA);
+       }
+    }
+
+  /* deliver maskable interrupt when allowed */
+  if (inttype > int_nmi && inttype < num_int_types)
+    {
+      if ((PSW & PSW_NP) || (PSW & PSW_ID))
+       {
+         /* Can't deliver this interrupt, reschedule it for later */
+         sim_events_schedule (sd, 1, do_interrupt, data);
+         return;
+       }
+      else
+       {
+         /* save context */
+         EIPC = PC;
+         EIPSW = PSW;
+         /* Disable further interrupts.  */
+         PSW |= PSW_ID;
+         /* Indicate that we're doing interrupt not exception processing.  */
+         PSW &= ~PSW_EP;
+         /* Clear the EICC part of the ECR, will set below. */
+         ECR &= 0xffff0000;
+         switch (inttype)
+           {
+           case int_intov1:
+             PC = 0x80;
+             ECR |= 0x80;
+             break;
+           case int_intp10:
+             PC = 0x90;
+             ECR |= 0x90;
+             break;
+           case int_intp11:
+             PC = 0xa0;
+             ECR |= 0xa0;
+             break;
+           case int_intp12:
+             PC = 0xb0;
+             ECR |= 0xb0;
+             break;
+           case int_intp13:
+             PC = 0xc0;
+             ECR |= 0xc0;
+             break;
+           case int_intcm4:
+             PC = 0xd0;
+             ECR |= 0xd0;
+             break;
+           default:
+             /* Should never be possible.  */
+             sim_engine_abort (sd, NULL, NULL_CIA,
+                               "do_interrupt - internal error - bad switch");
+             break;
+           }
+       }
+      sim_engine_restart (sd, NULL, NULL, NULL_CIA);
+    }
+  
+  /* some other interrupt? */
+  sim_engine_abort (sd, NULL, NULL_CIA,
+                   "do_interrupt - internal error - interrupt %d unknown",
+                   inttype);
+#endif  /* 0 */
+}
+
+/* These default values correspond to expected usage for the chip.  */
+
+SIM_DESC
+sim_open (kind, cb, abfd, argv)
+     SIM_OPEN_KIND kind;
+     host_callback *cb;
+     struct _bfd *abfd;
+     char **argv;
+{
+  SIM_DESC sd = sim_state_alloc (kind, cb);
+  int mach;
+  mn10300_callback = cb;
+
+  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+
+  /* for compatibility */
+  simulator = sd;
+
+  /* FIXME: should be better way of setting up interrupts */
+  STATE_WATCHPOINTS (sd)->pc = &(PC);
+  STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
+  STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
+  STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
+
+  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
+    return 0;
+
+  /* Allocate core managed memory */
+
+  /* "Mirror" the ROM addresses below 1MB. */
+  sim_do_command (sd, "memory region 0,0x100000");
+
+  /* getopt will print the error message so we just have to exit if this fails.
+     FIXME: Hmmm...  in the case of gdb we need getopt to call
+     print_filtered.  */
+  if (sim_parse_args (sd, argv) != SIM_RC_OK)
+    {
+      /* Uninstall the modules to avoid memory leaks,
+        file descriptor leaks, etc.  */
+      sim_module_uninstall (sd);
+      return 0;
+    }
+
+  /* check for/establish the a reference program image */
+  if (sim_analyze_program (sd,
+                          (STATE_PROG_ARGV (sd) != NULL
+                           ? *STATE_PROG_ARGV (sd)
+                           : NULL),
+                          abfd) != SIM_RC_OK)
+    {
+      sim_module_uninstall (sd);
+      return 0;
+    }
+
+  /* establish any remaining configuration options */
+  if (sim_config (sd) != SIM_RC_OK)
+    {
+      sim_module_uninstall (sd);
+      return 0;
+    }
+
+  if (sim_post_argv_init (sd) != SIM_RC_OK)
+    {
+      /* Uninstall the modules to avoid memory leaks,
+        file descriptor leaks, etc.  */
+      sim_module_uninstall (sd);
+      return 0;
+    }
+
+
+  /* set machine specific configuration */
+/*   STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
+/*                          | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
+
+  return sd;
+}
+
+
+void
+sim_close (sd, quitting)
+     SIM_DESC sd;
+     int quitting;
+{
+  sim_module_uninstall (sd);
+}
+
+
+SIM_RC
+sim_create_inferior (sd, prog_bfd, argv, env)
+     SIM_DESC sd;
+     struct _bfd *prog_bfd;
+     char **argv;
+     char **env;
+{
+  memset (&State, 0, sizeof (State));
+  if (prog_bfd != NULL) {
+    PC = bfd_get_start_address (prog_bfd);
+  } else {
+    PC = 0;
+  }
+  CIA_SET (STATE_CPU (sd, 0), (unsigned64) PC);
+
+  return SIM_RC_OK;
+}
+
+void
+sim_do_command (sd, cmd)
+     SIM_DESC sd;
+     char *cmd;
+{
+  char *mm_cmd = "memory-map";
+  char *int_cmd = "interrupt";
+
+  if (sim_args_command (sd, cmd) != SIM_RC_OK)
+    {
+      if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
+       sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
+      else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
+       sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
+      else
+       sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
+    }
+}
+#endif  /* WITH_COMMON */
+
+/* FIXME These would more efficient to use than load_mem/store_mem,
+   but need to be changed to use the memory map.  */
+
+uint8
+get_byte (x)
+     uint8 *x;
+{
+  return *x;
+}
+
+uint16
+get_half (x)
+     uint8 *x;
+{
+  uint8 *a = x;
+  return (a[1] << 8) + (a[0]);
+}
+
+uint32
+get_word (x)
+      uint8 *x;
+{
+  uint8 *a = x;
+  return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
+}
+
+void
+put_byte (addr, data)
+     uint8 *addr;
+     uint8 data;
+{
+  uint8 *a = addr;
+  a[0] = data;
+}
+
+void
+put_half (addr, data)
+     uint8 *addr;
+     uint16 data;
+{
+  uint8 *a = addr;
+  a[0] = data & 0xff;
+  a[1] = (data >> 8) & 0xff;
+}
+
+void
+put_word (addr, data)
+     uint8 *addr;
+     uint32 data;
+{
+  uint8 *a = addr;
+  a[0] = data & 0xff;
+  a[1] = (data >> 8) & 0xff;
+  a[2] = (data >> 16) & 0xff;
+  a[3] = (data >> 24) & 0xff;
+}
+
+int
+sim_fetch_register (sd, rn, memory, length)
+     SIM_DESC sd;
+     int rn;
+     unsigned char *memory;
+     int length;
+{
+  put_word (memory, State.regs[rn]);
+  return -1;
+}
+int
+sim_store_register (sd, rn, memory, length)
+     SIM_DESC sd;
+     int rn;
+     unsigned char *memory;
+     int length;
+{
+  State.regs[rn] = get_word (memory);
+  return -1;
+}