]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - sim/mips/interp.c
sim: constify sim_write source buffer (part 2)
[thirdparty/binutils-gdb.git] / sim / mips / interp.c
index 8cc6318aaef1a9f65accf6f986889c01ee1d5b63..a276d06f9bd0a09407415d4fd074e8fe3ae9267c 100644 (file)
@@ -61,10 +61,8 @@ code on the hardware.
 #include "getopt.h"
 #include "libiberty.h"
 #include "bfd.h"
-#include "callback.h"   /* GDB simulator callback interface */
-#include "remote-sim.h" /* GDB simulator interface */
-
-#include "sysdep.h"
+#include "gdb/callback.h"   /* GDB simulator callback interface */
+#include "gdb/remote-sim.h" /* GDB simulator interface */
 
 #ifndef PARAMS
 #define PARAMS(x) 
@@ -131,6 +129,9 @@ static void ColdReset PARAMS((SIM_DESC sd));
 
 /* Note that the monitor code essentially assumes this layout of memory.
    If you change these, change the monitor code, too.  */
+/* FIXME Currently addresses are truncated to 32-bits, see
+   mips/sim-main.c:address_translation(). If that changes, then these
+   values will need to be extended, and tested for more carefully. */
 #define K0BASE  (0x80000000)
 #define K0SIZE  (0x20000000)
 #define K1BASE  (0xA0000000)
@@ -156,7 +157,7 @@ static SIM_ADDR lsipmon_monitor_base = 0xBFC00200;
 static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg);
 
 
-#define MEM_SIZE (2 << 20)
+#define MEM_SIZE (8 << 20)     /* 8 MBytes */
 
 
 #if defined(TRACE)
@@ -177,9 +178,11 @@ enum {
   OPTION_DINERO_TRACE = OPTION_START,
   OPTION_DINERO_FILE,
   OPTION_FIRMWARE,
+  OPTION_INFO_MEMORY,
   OPTION_BOARD
 };
 
+static int display_mem_info = 0;
 
 static SIM_RC
 mips_option_handler (sd, cpu, opt, arg, is_command)
@@ -256,6 +259,10 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
          }
        return SIM_RC_OK;
       }
+
+    case OPTION_INFO_MEMORY:
+      display_mem_info = 1;
+      break;
     }
   
   return SIM_RC_OK;
@@ -287,6 +294,20 @@ static const OPTION mips_options[] =
 
     , "Customize simulation for a particular board.", mips_option_handler },
 
+  /* These next two options have the same names as ones found in the
+     memory_options[] array in common/sim-memopt.c.  This is because
+     the intention is to provide an alternative handler for those two
+     options.  We need an alternative handler because the memory
+     regions are not set up until after the command line arguments
+     have been parsed, and so we cannot display the memory info whilst
+     processing the command line.  There is a hack in sim_open to
+     remove these handlers when we want the real --memory-info option
+     to work.  */
+  { { "info-memory", no_argument, NULL, OPTION_INFO_MEMORY },
+    '\0', NULL, "List configured memory regions", mips_option_handler },
+  { { "memory-info", no_argument, NULL, OPTION_INFO_MEMORY },
+    '\0', NULL, NULL, mips_option_handler },
+  
   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
 };
 
@@ -326,7 +347,7 @@ SIM_DESC
 sim_open (kind, cb, abfd, argv)
      SIM_OPEN_KIND kind;
      host_callback *cb;
-     struct _bfd *abfd;
+     struct bfd *abfd;
      char **argv;
 {
   SIM_DESC sd = sim_state_alloc (kind, cb);
@@ -365,17 +386,67 @@ sim_open (kind, cb, abfd, argv)
   if (board == NULL)
     {
       /* Allocate core managed memory */
-      
+      sim_memopt *entry, *match = NULL;
+      address_word mem_size = 0;
+      int mapped = 0;
 
       /* 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 */
       sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
-      sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
-                      K1BASE, K0SIZE,
-                      MEM_SIZE, /* actual size */
-                      K0BASE);
-      
+
+      /* Look for largest memory region defined on command-line at
+        phys address 0. */
+#ifdef SIM_HAVE_FLATMEM
+      mem_size = STATE_MEM_SIZE (sd);
+#endif
+      for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next)
+       {
+         /* If we find an entry at address 0, then we will end up
+            allocating a new buffer in the "memory alias" command
+            below. The region at address 0 will be deleted. */
+         address_word size = (entry->modulo != 0
+                              ? entry->modulo : entry->nr_bytes);
+         if (entry->addr == 0
+             && (!match || entry->level < match->level))
+           match = entry;
+         else if (entry->addr == K0BASE || entry->addr == K1BASE)
+           mapped = 1;
+         else
+           {
+             sim_memopt *alias;
+             for (alias = entry->alias; alias != NULL; alias = alias->next)
+               {
+                 if (alias->addr == 0
+                     && (!match || entry->level < match->level))
+                   match = entry;
+                 else if (alias->addr == K0BASE || alias->addr == K1BASE)
+                   mapped = 1;
+               }
+           }
+       }
+
+      if (!mapped)
+       {
+         if (match)
+           {
+             /* Get existing memory region size. */
+             mem_size = (match->modulo != 0
+                         ? match->modulo : match->nr_bytes);
+             /* Delete old region. */
+             sim_do_commandf (sd, "memory delete %d:0x%lx@%d",
+                              match->space, match->addr, match->level);
+           }         
+         else if (mem_size == 0)
+           mem_size = MEM_SIZE;
+         /* Limit to KSEG1 size (512MB) */
+         if (mem_size > K1SIZE)
+           mem_size = K1SIZE;
+         /* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */
+         sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
+                          K1BASE, K1SIZE, (long)mem_size, K0BASE);
+       }
+
       device_init(sd);
     }
   else if (board != NULL
@@ -534,6 +605,31 @@ sim_open (kind, cb, abfd, argv)
     }
 #endif
 
+  if (display_mem_info)
+    {
+      struct option_list * ol;
+      struct option_list * prev;
+
+      /* This is a hack.  We want to execute the real --memory-info command
+        line switch which is handled in common/sim-memopts.c, not the
+        override we have defined in this file.  So we remove the
+        mips_options array from the state options list.  This is safe
+         because we have now processed all of the command line.  */
+      for (ol = STATE_OPTIONS (sd), prev = NULL;
+          ol != NULL;
+          prev = ol, ol = ol->next)
+       if (ol->options == mips_options)
+         break;
+
+      SIM_ASSERT (ol != NULL);
+
+      if (prev == NULL)
+       STATE_OPTIONS (sd) = ol->next;
+      else
+       prev->next = ol->next;
+
+      sim_do_commandf (sd, "memory-info");
+    }
 
   /* check for/establish the a reference program image */
   if (sim_analyze_program (sd,
@@ -766,7 +862,7 @@ int
 sim_write (sd,addr,buffer,size)
      SIM_DESC sd;
      SIM_ADDR addr;
-     unsigned char *buffer;
+     const unsigned char *buffer;
      int size;
 {
   int index;
@@ -868,8 +964,16 @@ sim_store_register (sd,rn,memory,length)
        }
       else
        {
-         cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory);
-         return 8;
+          if (length == 8)
+           {
+             cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory);
+             return 8;
+           }
+         else
+           {
+             cpu->fgr[rn - FGR_BASE] = T2H_4 (*(unsigned32*)memory);
+             return 4;
+           }
        }
     }
 
@@ -889,8 +993,16 @@ sim_store_register (sd,rn,memory,length)
     }
   else
     {
-      cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
-      return 8;
+      if (length == 8)
+       {
+         cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
+         return 8;
+       }
+      else
+       {
+         cpu->registers[rn] = (signed32) T2H_4(*(unsigned32*)memory);
+         return 4;
+       }
     }
 
   return 0;
@@ -939,8 +1051,16 @@ sim_fetch_register (sd,rn,memory,length)
        }
       else
        {
-         *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]);
-         return 8;
+         if (length == 8)
+           {
+             *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]);
+             return 8;
+           }
+         else
+           {
+             *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->fgr[rn - FGR_BASE]));
+             return 4;
+           }
        }
     }
 
@@ -960,8 +1080,17 @@ sim_fetch_register (sd,rn,memory,length)
     }
   else
     {
-      *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
-      return 8;
+      if (length == 8)
+       {
+         *(unsigned64*)memory =
+           H2T_8 ((unsigned64) (cpu->registers[rn]));
+         return 8;
+       }
+      else
+       {
+         *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
+         return 4;
+       }
     }
 
   return 0;
@@ -971,7 +1100,7 @@ sim_fetch_register (sd,rn,memory,length)
 SIM_RC
 sim_create_inferior (sd, abfd, argv,env)
      SIM_DESC sd;
-     struct _bfd *abfd;
+     struct bfd *abfd;
      char **argv;
      char **env;
 {
@@ -1077,7 +1206,10 @@ sim_firmware_command (SIM_DESC sd, char *arg)
          }
       }
     else
-      address_present = 0;
+      {
+       address_present = 0;
+       address = -1; /* Dummy value.  */
+      }
   }
 
   if (! strncmp (arg, "idt", 3))
@@ -1175,6 +1307,10 @@ sim_monitor (SIM_DESC sd,
        char *buf = zalloc (nr);
        sim_read (sd, A1, buf, nr);
        V0 = sim_io_write (sd, fd, buf, nr);
+       if (fd == 1)
+           sim_io_flush_stdout (sd);
+       else if (fd == 2)
+           sim_io_flush_stderr (sd);
        zfree (buf);
        break;
       }
@@ -1232,8 +1368,39 @@ sim_monitor (SIM_DESC sd,
       /*      [A0 + 4] = instruction cache size */
       /*      [A0 + 8] = data cache size */
       {
-       unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+       unsigned_4 value;
        unsigned_4 zero = 0;
+       address_word mem_size;
+       sim_memopt *entry, *match = NULL;
+
+       /* Search for memory region mapped to KSEG0 or KSEG1. */
+       for (entry = STATE_MEMOPT (sd); 
+            entry != NULL;
+            entry = entry->next)
+         {
+           if ((entry->addr == K0BASE || entry->addr == K1BASE)
+               && (!match || entry->level < match->level))
+             match = entry;
+           else
+             {
+               sim_memopt *alias;
+               for (alias = entry->alias; 
+                    alias != NULL;
+                    alias = alias->next)
+                 if ((alias->addr == K0BASE || alias->addr == K1BASE)
+                     && (!match || entry->level < match->level))
+                   match = entry;
+             }
+         }
+
+       /* Get region size, limit to KSEG1 size (512MB). */
+       SIM_ASSERT (match != NULL);
+       mem_size = (match->modulo != 0
+                   ? match->modulo : match->nr_bytes);
+       if (mem_size > K1SIZE)
+         mem_size = K1SIZE;
+
+       value = mem_size;
        H2T (value);
        sim_write (sd, A0 + 0, (char *)&value, 4);
        sim_write (sd, A0 + 4, (char *)&zero, 4);
@@ -1638,6 +1805,20 @@ ColdReset (SIM_DESC sd)
            FPR_STATE[rn] = fmt_uninterpreted;
        }
       
+      /* Initialise the Config0 register. */
+      C0_CONFIG = 0x80000000           /* Config1 present */
+       | 2;                            /* KSEG0 uncached */
+      if (WITH_TARGET_WORD_BITSIZE == 64)
+       {
+         /* FIXME Currently mips/sim-main.c:address_translation()
+            truncates all addresses to 32-bits. */
+         if (0 && WITH_TARGET_ADDRESS_BITSIZE == 64)
+           C0_CONFIG |= (2 << 13);     /* MIPS64, 64-bit addresses */
+         else
+           C0_CONFIG |= (1 << 13);     /* MIPS64, 32-bit addresses */
+       }
+      if (BigEndianMem)
+       C0_CONFIG |= 0x00008000;        /* Big Endian */
     }
 }
 
@@ -1921,8 +2102,7 @@ cop_lw (SIM_DESC sd,
 #ifdef DEBUG
          printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
 #endif
-         StoreFPR(coproc_reg,fmt_word,(uword64)memword);
-         FPR_STATE[coproc_reg] = fmt_uninterpreted;
+         StoreFPR(coproc_reg,fmt_uninterpreted_32,(uword64)memword);
          break;
        }
 
@@ -1953,7 +2133,7 @@ cop_ld (SIM_DESC sd,
     case 1:
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
        {
-         StoreFPR(coproc_reg,fmt_uninterpreted,memword);
+         StoreFPR(coproc_reg,fmt_uninterpreted_64,memword);
          break;
        }
 
@@ -1984,11 +2164,7 @@ cop_sw (SIM_DESC sd,
     case 1:
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
        {
-         FP_formats hold;
-         hold = FPR_STATE[coproc_reg];
-         FPR_STATE[coproc_reg] = fmt_word;
-         value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
-         FPR_STATE[coproc_reg] = hold;
+         value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted_32);
          break;
        }
 
@@ -2015,7 +2191,7 @@ cop_sd (SIM_DESC sd,
     case 1:
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
        {
-         value = ValueFPR(coproc_reg,fmt_uninterpreted);
+         value = ValueFPR(coproc_reg,fmt_uninterpreted_64);
          break;
        }
 
@@ -2099,7 +2275,7 @@ decode_coproc (SIM_DESC sd,
              case 8:
                /* 8 = BadVAddr            R4000   VR4100  VR4300 */
                if (code == 0x00)
-                 GPR[rt] = COP0_BADVADDR;
+                 GPR[rt] = (signed_word) (signed_address) COP0_BADVADDR;
                else
                  COP0_BADVADDR = GPR[rt];
                break;
@@ -2137,10 +2313,11 @@ decode_coproc (SIM_DESC sd,
 #else
                /* 16 = Config             R4000   VR4100  VR4300 */
               case 16:
-                if (code == 0x00)
-                  GPR[rt] = C0_CONFIG;
-                else
-                  C0_CONFIG = GPR[rt];
+               if (code == 0x00)
+                 GPR[rt] = C0_CONFIG;
+               else
+                 /* only bottom three bits are writable */
+                 C0_CONFIG = (C0_CONFIG & ~0x7) | (GPR[rt] & 0x7);
                 break;
 #endif
 #ifdef SUBTARGET_R3900
@@ -2181,6 +2358,40 @@ decode_coproc (SIM_DESC sd,
 #endif
              }
          }
+       else if ((code == 0x00 || code == 0x01)
+                && rd == 16)
+         {
+           /* [D]MFC0 RT,C0_CONFIG,SEL */
+           signed32 cfg = 0;
+           switch (tail & 0x07) 
+             {
+             case 0:
+               cfg = C0_CONFIG;
+               break;
+             case 1:
+               /* MIPS32 r/o Config1: 
+                  Config2 present */
+               cfg = 0x80000000;
+               /* MIPS16 implemented. 
+                  XXX How to check configuration? */
+               cfg |= 0x0000004;
+               if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
+                 /* MDMX & FPU implemented */
+                 cfg |= 0x00000021;
+               break;
+             case 2:
+               /* MIPS32 r/o Config2: 
+                  Config3 present. */
+               cfg = 0x80000000;
+               break;
+             case 3:
+               /* MIPS32 r/o Config3: 
+                  SmartMIPS implemented. */
+               cfg = 0x00000002;
+               break;
+             }
+           GPR[rt] = cfg;
+         }
        else if (code == 0x10 && (tail & 0x3f) == 0x18)
          {
            /* ERET */