Thu June 18 14:37:14 1998 Joyce Janczyn <janczyn@cygnus.com>
[binutils-gdb.git] / sim / mn10300 / interp.c
index eede9a706e3738ab616693a05e573735e6f9877e..e67bee88c95c5c44111006d95356e4ab22b70cf1 100644 (file)
@@ -3,6 +3,9 @@
 #if WITH_COMMON
 #include "sim-main.h"
 #include "sim-options.h"
+/* start-sanitize-am30 */
+#include "sim-hw.h"
+/* end-sanitize-am30 */
 #else
 #include "mn10300_sim.h"
 #endif
 host_callback *mn10300_callback;
 int mn10300_debug;
 
+
+/* simulation target board.  NULL=default configuration */
+static char* board = NULL;
+
+static DECLARE_OPTION_HANDLER (mn10300_option_handler);
+
+enum {
+  OPTION_BOARD = OPTION_START,
+};
+
+static SIM_RC
+mn10300_option_handler (sd, cpu, opt, arg, is_command)
+     SIM_DESC sd;
+     sim_cpu *cpu;
+     int opt;
+     char *arg;
+     int is_command;
+{
+  int cpu_nr;
+  switch (opt)
+    {
+    case OPTION_BOARD:
+      {
+       if (arg)
+         {
+           board = zalloc(strlen(arg) + 1);
+           strcpy(board, arg);
+         }
+       return SIM_RC_OK;
+      }
+    }
+  
+  return SIM_RC_OK;
+}
+
+static const OPTION mn10300_options[] = 
+{
+/* start-sanitize-am30 */
+#define BOARD_AM32 "am32"
+  { {"board", required_argument, NULL, OPTION_BOARD},
+     '\0', "none" /* rely on compile-time string concatenation for other options */
+           "|" BOARD_AM32
+    , "Customize simulation for a particular board.", mn10300_option_handler },
+/* end-sanitize-am30 */
+
+  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
+};
+
 #if WITH_COMMON
 #else
 static void dispatch PARAMS ((uint32, uint32, int));
@@ -260,7 +311,6 @@ compare_simops (arg1, arg2)
   return 0;
 }
 
-
 SIM_DESC
 sim_open (kind, cb, abfd, argv)
      SIM_OPEN_KIND kind;
@@ -892,151 +942,6 @@ sim_load (sd, prog, abfd, from_tty)
 /* 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
@@ -1054,19 +959,21 @@ sim_open (kind, cb, abfd, argv)
   /* for compatibility */
   simulator = sd;
 
-  /* FIXME: should be better way of setting up interrupts */
+  /* FIXME: should be better way of setting up interrupts.  For
+     moment, only support watchpoints causing a breakpoint (gdb
+     halt). */
   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;
+  STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
+  STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
 
   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
     return 0;
+  sim_add_option_table (sd, NULL, mn10300_options);
 
   /* Allocate core managed memory */
-
-  /* "Mirror" the ROM addresses below 1MB. */
   sim_do_command (sd, "memory region 0,0x100000");
+  sim_do_command (sd, "memory region 0x40000000,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
@@ -1079,6 +986,119 @@ sim_open (kind, cb, abfd, argv)
       return 0;
     }
 
+  /* start-sanitize-am30 */
+  if ( NULL != board
+       && (strcmp(board, BOARD_AM32) == 0 ) )
+       {
+        /* device support for mn1030002 */
+        /* interrupt controller */
+
+        sim_hw_parse (sd, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
+
+        /* DEBUG: NMI input's */
+        sim_hw_parse (sd, "/glue@0x30000000/reg 0x30000000 12");
+        sim_hw_parse (sd, "/glue@0x30000000 > int0 nmirq /mn103int");
+        sim_hw_parse (sd, "/glue@0x30000000 > int1 watchdog /mn103int");
+        sim_hw_parse (sd, "/glue@0x30000000 > int2 syserr /mn103int");
+
+        /* DEBUG: ACK input */
+        sim_hw_parse (sd, "/glue@0x30002000/reg 0x30002000 4");
+        sim_hw_parse (sd, "/glue@0x30002000 > int ack /mn103int");
+        
+        /* DEBUG: LEVEL output */
+        sim_hw_parse (sd, "/glue@0x30004000/reg 0x30004000 8");
+        sim_hw_parse (sd, "/mn103int > nmi int0 /glue@0x30004000");
+        sim_hw_parse (sd, "/mn103int > level int1 /glue@0x30004000");
+
+        /* DEBUG: A bunch of interrupt inputs */
+        sim_hw_parse (sd, "/glue@0x30006000/reg 0x30006000 32");
+        sim_hw_parse (sd, "/glue@0x30006000 > int0 irq-0 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int1 irq-1 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int2 irq-2 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int3 irq-3 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int4 irq-4 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int5 irq-5 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int6 irq-6 /mn103int");
+        sim_hw_parse (sd, "/glue@0x30006000 > int7 irq-7 /mn103int");
+
+        /* processor interrupt device */
+
+        /* the device */
+        sim_hw_parse (sd, "/mn103cpu@0x20000000");
+        sim_hw_parse (sd, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
+
+        /* DEBUG: ACK output wired upto a glue device */
+        sim_hw_parse (sd, "/glue@0x20002000");
+        sim_hw_parse (sd, "/glue@0x20002000/reg 0x20002000 4");
+        sim_hw_parse (sd, "/mn103cpu > ack int0 /glue@0x20002000");
+
+        /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
+        sim_hw_parse (sd, "/glue@0x20004000");
+        sim_hw_parse (sd, "/glue@0x20004000/reg 0x20004000 12");
+        sim_hw_parse (sd, "/glue@0x20004000 > int0 reset /mn103cpu");
+        sim_hw_parse (sd, "/glue@0x20004000 > int1 nmi /mn103cpu");
+        sim_hw_parse (sd, "/glue@0x20004000 > int2 level /mn103cpu");
+
+        /* REAL: The processor wired up to the real interrupt controller */
+        sim_hw_parse (sd, "/mn103cpu > ack ack /mn103int");
+        sim_hw_parse (sd, "/mn103int > level level /mn103cpu");
+        sim_hw_parse (sd, "/mn103int > nmi nmi /mn103cpu");
+
+
+        /* PAL */
+
+        /* the device */
+        sim_hw_parse (sd, "/pal@0x31000000");
+        sim_hw_parse (sd, "/pal@0x31000000/reg 0x31000000 64");
+        sim_hw_parse (sd, "/pal@0x31000000/poll? true");
+
+        /* DEBUG: PAL wired up to a glue device */
+        sim_hw_parse (sd, "/glue@0x31002000");
+        sim_hw_parse (sd, "/glue@0x31002000/reg 0x31002000 16");
+        sim_hw_parse (sd, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
+        sim_hw_parse (sd, "/pal@0x31000000 > timer int1 /glue@0x31002000");
+        sim_hw_parse (sd, "/pal@0x31000000 > int int2 /glue@0x31002000");
+        sim_hw_parse (sd, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
+        sim_hw_parse (sd, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
+        sim_hw_parse (sd, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
+        
+        /* REAL: The PAL wired up to the real interrupt controller */
+        sim_hw_parse (sd, "/pal@0x31000000 > countdown irq-0 /mn103int");
+        sim_hw_parse (sd, "/pal@0x31000000 > timer irq-1 /mn103int");
+        sim_hw_parse (sd, "/pal@0x31000000 > int irq-2 /mn103int");
+        
+        /* 8 and 16 bit timers */
+        sim_hw_parse (sd, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100");
+  
+        /* Hook timer interrupts up to interrupt controller */
+        sim_hw_parse (sd, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
+        sim_hw_parse (sd, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
+
+
+        /* Serial devices 0,1,2 */
+        sim_hw_parse (sd, "/mn103ser@0x34000800/reg 0x34000800 48");
+        sim_hw_parse (sd, "/mn103ser@0x34000800/poll? true");
+  
+        /* Hook serial interrupts up to interrupt controller */
+        sim_hw_parse (sd, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
+        sim_hw_parse (sd, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
+        sim_hw_parse (sd, "/mn103ser > serial-1-receive serial-0-receive /mn103int");
+        sim_hw_parse (sd, "/mn103ser > serial-1-transmit serial-0-transmit /mn103int");
+        sim_hw_parse (sd, "/mn103ser > serial-2-receive serial-0-receive /mn103int");
+        sim_hw_parse (sd, "/mn103ser > serial-2-transmit serial-0-transmit /mn103int");
+
+        sim_hw_parse (sd, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
+       }
+  
+  /* end-sanitize-am30 */
+
   /* check for/establish the a reference program image */
   if (sim_analyze_program (sd,
                           (STATE_PROG_ARGV (sd) != NULL