This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / mips / interp.c
index 75bc54b7b821a0d0b43d6794f2ec29528a5ced6f..3ee500195be72014faf6ed666dc84e1d0ef2b11f 100644 (file)
@@ -132,12 +132,33 @@ static void ColdReset PARAMS((SIM_DESC sd));
 #define INDELAYSLOT()  ((STATE & simDELAYSLOT) != 0)
 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
 
+/* Note that the monitor code essentially assumes this layout of memory.
+   If you change these, change the monitor code, too.  */
 #define K0BASE  (0x80000000)
 #define K0SIZE  (0x20000000)
 #define K1BASE  (0xA0000000)
 #define K1SIZE  (0x20000000)
-#define MONITOR_BASE (0xBFC00000)
-#define MONITOR_SIZE (1 << 11)
+
+/* Simple run-time monitor support.
+   
+   We emulate the monitor by placing magic reserved instructions at
+   the monitor's entry points; when we hit these instructions, instead
+   of raising an exception (as we would normally), we look at the
+   instruction and perform the appropriate monitory operation.
+   
+   `*_monitor_base' are the physical addresses at which the corresponding 
+        monitor vectors are located.  `0' means none.  By default,
+        install all three.
+    The RSVD_INSTRUCTION... macros specify the magic instructions we
+    use at the monitor entry points.  */
+static int firmware_option_p = 0;
+static SIM_ADDR idt_monitor_base =     0xBFC00000;
+static SIM_ADDR pmon_monitor_base =    0xBFC00500;
+static SIM_ADDR lsipmon_monitor_base = 0xBFC00200;
+
+static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg);
+
+
 #define MEM_SIZE (2 << 20)
 
 
@@ -158,6 +179,7 @@ static DECLARE_OPTION_HANDLER (mips_option_handler);
 enum {
   OPTION_DINERO_TRACE = OPTION_START,
   OPTION_DINERO_FILE,
+  OPTION_FIRMWARE,
   OPTION_BOARD
 };
 
@@ -225,6 +247,9 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
 #endif /* TRACE */
       return SIM_RC_OK;
 
+    case OPTION_FIRMWARE:
+      return sim_firmware_command (sd, arg);
+
     case OPTION_BOARD:
       {
        if (arg)
@@ -248,6 +273,9 @@ static const OPTION mips_options[] =
   { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
       '\0', "FILE", "Write dinero trace to FILE",
       mips_option_handler },
+  { {"firmware", required_argument, NULL, OPTION_FIRMWARE},
+    '\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor",
+    mips_option_handler },
   { {"board", required_argument, NULL, OPTION_BOARD},
      '\0', "none" /* rely on compile-time string concatenation for other options */
 
@@ -257,6 +285,8 @@ static const OPTION mips_options[] =
            "|" BOARD_JMR3904_PAL
 #define BOARD_JMR3904_DEBUG "jmr3904debug"
            "|" BOARD_JMR3904_DEBUG
+#define BOARD_BSP "bsp"
+           "|" BOARD_BSP
 
     , "Customize simulation for a particular board.", mips_option_handler },
 
@@ -339,8 +369,7 @@ sim_open (kind, cb, abfd, argv)
     {
       /* Allocate core managed memory */
       
-      /* the monitor  */
-      sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE);
+
       /* For compatibility with the old code - under this (at level one)
         are the kernel spaces K0 & K1.  Both of these map to a single
         smaller sub region */
@@ -352,16 +381,53 @@ sim_open (kind, cb, abfd, argv)
       
       device_init(sd);
     }
-  
+  else if (board != NULL
+          && (strcmp(board, BOARD_BSP) == 0))
+    {
+      int i;
+
+      STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
+
+      /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
+      sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+                      0x9FC00000, 
+                      4 * 1024 * 1024, /* 4 MB */
+                      0xBFC00000);
+
+      /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
+      sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+                      0x80000000, 
+                      4 * 1024 * 1024, /* 4 MB */
+                      0xA0000000);
+
+      /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
+      for (i=0; i<8; i++) /* 32 MB total */
+       {
+         unsigned size = 4 * 1024 * 1024;  /* 4 MB */
+         sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+                          0x88000000 + (i * size), 
+                          size, 
+                          0xA8000000 + (i * size));
+       }
+    }
 #if (WITH_HW)
-  if (board != NULL
-      && (strcmp(board, BOARD_JMR3904) == 0 ||
-         strcmp(board, BOARD_JMR3904_PAL) == 0 ||
-         strcmp(board, BOARD_JMR3904_DEBUG) == 0))
+  else if (board != NULL
+          && (strcmp(board, BOARD_JMR3904) == 0 ||
+              strcmp(board, BOARD_JMR3904_PAL) == 0 ||
+              strcmp(board, BOARD_JMR3904_DEBUG) == 0))
     {
       /* match VIRTUAL memory layout of JMR-TX3904 board */
       int i;
 
+      /* --- disable monitor unless forced on by user --- */
+
+      if (! firmware_option_p)
+       {
+         idt_monitor_base = 0;
+         pmon_monitor_base = 0;
+         lsipmon_monitor_base = 0;
+       }
+
       /* --- environment --- */
 
       STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
@@ -526,51 +592,54 @@ sim_open (kind, cb, abfd, argv)
     open_trace(sd);
 #endif /* TRACE */
 
-  /* Write an abort sequence into the TRAP (common) exception vector
-     addresses.  This is to catch code executing a TRAP (et.al.)
-     instruction without installing a trap handler. */
-  {
-    unsigned32 halt[2] = { 0x2404002f /* addiu r4, r0, 47 */,
-                          HALT_INSTRUCTION /* BREAK */ };
-    H2T (halt[0]);
-    H2T (halt[1]);
-    sim_write (sd, 0x80000000, (char *) halt, sizeof (halt));
-    sim_write (sd, 0x80000180, (char *) halt, sizeof (halt));
-    sim_write (sd, 0x80000200, (char *) halt, sizeof (halt));
-    sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt));
-    sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt));
-    sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt));
-  }
-
+  /*
+  sim_io_eprintf (sd, "idt@%x pmon@%x lsipmon@%x\n", 
+                 idt_monitor_base,
+                 pmon_monitor_base, 
+                 lsipmon_monitor_base);
+  */
 
   /* Write the monitor trap address handlers into the monitor (eeprom)
      address space.  This can only be done once the target endianness
      has been determined. */
-  {
-    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)
-       "undefined" instructions into the relevant vector slots. */
-    for (loop = 0; (loop < MONITOR_SIZE); loop += 4)
-      {
-       address_word vaddr = (MONITOR_BASE + loop);
-       unsigned32 insn = (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT));
-       H2T (insn);
-       sim_write (sd, vaddr, (char *)&insn, sizeof (insn));
-      }
+  if (idt_monitor_base != 0)
+    {
+      unsigned loop;
+      unsigned idt_monitor_size = 1 << 11;
+
+      /* the default monitor region */
+      sim_do_commandf (sd, "memory region 0x%x,0x%x",
+                      idt_monitor_base, idt_monitor_size);
+
+      /* 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)
+        "undefined" instructions into the relevant vector slots. */
+      for (loop = 0; (loop < idt_monitor_size); loop += 4)
+       {
+         address_word vaddr = (idt_monitor_base + loop);
+         unsigned32 insn = (RSVD_INSTRUCTION |
+                            (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK)
+                             << RSVD_INSTRUCTION_ARG_SHIFT));
+         H2T (insn);
+         sim_write (sd, vaddr, (char *)&insn, sizeof (insn));
+       }
+    }
+
+  if ((pmon_monitor_base != 0) || (lsipmon_monitor_base != 0))
+    {
     /* The PMON monitor uses the same address space, but rather than
        branching into it the address of a routine is loaded. We can
        cheat for the moment, and direct the PMON routine to IDT style
        instructions within the monitor space. This relies on the IDT
        monitor not using the locations from 0xBFC00500 onwards as its
        entry points.*/
-    for (loop = 0; (loop < 24); loop++)
-      {
-        address_word vaddr = (MONITOR_BASE + 0x500 + (loop * 4));
-        unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
-        switch (loop)
-          {
+      unsigned loop;
+      for (loop = 0; (loop < 24); loop++)
+       {
+         unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
+         switch (loop)
+           {
             case 0: /* read */
               value = 7;
               break;
@@ -593,15 +662,43 @@ sim_open (kind, cb, abfd, argv)
               value = 28;
               break;
           }
-       /* FIXME - should monitor_base be SIM_ADDR?? */
-        value = ((unsigned int)MONITOR_BASE + (value * 8));
+
+       SIM_ASSERT (idt_monitor_base != 0);
+        value = ((unsigned int) idt_monitor_base + (value * 8));
        H2T (value);
-       sim_write (sd, vaddr, (char *)&value, sizeof (value));
 
-       /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500.  */
-       vaddr -= 0x300;
-       sim_write (sd, vaddr, (char *)&value, sizeof (value));
+       if (pmon_monitor_base != 0)
+         {
+           address_word vaddr = (pmon_monitor_base + (loop * 4));
+           sim_write (sd, vaddr, (char *)&value, sizeof (value));
+         }
+
+       if (lsipmon_monitor_base != 0)
+         {
+           address_word vaddr = (lsipmon_monitor_base + (loop * 4));
+           sim_write (sd, vaddr, (char *)&value, sizeof (value));
+         }
       }
+
+  /* Write an abort sequence into the TRAP (common) exception vector
+     addresses.  This is to catch code executing a TRAP (et.al.)
+     instruction without installing a trap handler. */
+  if ((idt_monitor_base != 0) || 
+      (pmon_monitor_base != 0) || 
+      (lsipmon_monitor_base != 0))
+    {
+      unsigned32 halt[2] = { 0x2404002f /* addiu r4, r0, 47 */,
+                            HALT_INSTRUCTION /* BREAK */ };
+      H2T (halt[0]);
+      H2T (halt[1]);
+      sim_write (sd, 0x80000000, (char *) halt, sizeof (halt));
+      sim_write (sd, 0x80000180, (char *) halt, sizeof (halt));
+      sim_write (sd, 0x80000200, (char *) halt, sizeof (halt));
+      /* XXX: Write here unconditionally? */
+      sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt));
+      sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt));
+      sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt));
+    }
   }
 
 
@@ -750,6 +847,7 @@ sim_store_register (sd,rn,memory,length)
 
   if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
     {
+      cpu->fpr_state[rn - FGRIDX] = fmt_uninterpreted;
       if (cpu->register_widths[rn] == 32)
        {
          cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory);
@@ -904,6 +1002,91 @@ fetch_str (SIM_DESC sd,
   return buf;
 }
 
+
+/* Implements the "sim firmware" command:
+       sim firmware NAME[@ADDRESS] --- emulate ROM monitor named NAME.
+               NAME can be idt, pmon, or lsipmon.  If omitted, ADDRESS
+               defaults to the normal address for that monitor.
+       sim firmware none --- don't emulate any ROM monitor.  Useful
+               if you need a clean address space.  */
+static SIM_RC
+sim_firmware_command (SIM_DESC sd, char *arg)
+{
+  int address_present = 0;
+  SIM_ADDR address;
+
+  /* Signal occurrence of this option. */
+  firmware_option_p = 1;
+
+  /* Parse out the address, if present.  */
+  {
+    char *p = strchr (arg, '@');
+    if (p)
+      {
+       char *q;
+       address_present = 1;
+       p ++; /* skip over @ */
+
+       address = strtoul (p, &q, 0);
+       if (*q != '\0') 
+         {
+           sim_io_printf (sd, "Invalid address given to the"
+                          "`sim firmware NAME@ADDRESS' command: %s\n",
+                          p);
+           return SIM_RC_FAIL;
+         }
+      }
+    else
+      address_present = 0;
+  }
+
+  if (! strncmp (arg, "idt", 3))
+    {
+      idt_monitor_base = address_present ? address : 0xBFC00000;
+      pmon_monitor_base = 0;
+      lsipmon_monitor_base = 0;
+    }
+  else if (! strncmp (arg, "pmon", 4))
+    {
+      /* pmon uses indirect calls.  Hook into implied idt. */
+      pmon_monitor_base = address_present ? address : 0xBFC00500;
+      idt_monitor_base = pmon_monitor_base - 0x500;
+      lsipmon_monitor_base = 0;
+    }
+  else if (! strncmp (arg, "lsipmon", 7))
+    {
+      /* lsipmon uses indirect calls.  Hook into implied idt. */
+      pmon_monitor_base = 0;
+      lsipmon_monitor_base = address_present ? address : 0xBFC00200;
+      idt_monitor_base = lsipmon_monitor_base - 0x200;
+    }
+  else if (! strncmp (arg, "none", 4))
+    {
+      if (address_present)
+       {
+         sim_io_printf (sd,
+                        "The `sim firmware none' command does "
+                        "not take an `ADDRESS' argument.\n");
+         return SIM_RC_FAIL;
+       }
+      idt_monitor_base = 0;
+      pmon_monitor_base = 0;
+      lsipmon_monitor_base = 0;
+    }
+  else
+    {
+      sim_io_printf (sd, "\
+Unrecognized name given to the `sim firmware NAME' command: %s\n\
+Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n",
+                    arg);
+      return SIM_RC_FAIL;
+    }
+  
+  return SIM_RC_OK;
+}
+
+
+
 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
 void
 sim_monitor (SIM_DESC sd,
@@ -972,6 +1155,8 @@ sim_monitor (SIM_DESC sd,
     case 11: /* char inbyte(void) */
       {
         char tmp;
+       /* ensure that all output has gone... */
+       sim_io_flush_stdout (sd);
         if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char))
          {
            sim_io_error(sd,"Invalid return from character read");
This page took 0.029036 seconds and 4 git commands to generate.