Re-do load/store operations so that they work for both 32 and 64 bit
[deliverable/binutils-gdb.git] / sim / mips / interp.c
index 8f2553e53add6cc974451d1f093ae541d82173c2..4e69b571bcf4d6c78a20309b1fcb2ca3e37291ce 100644 (file)
@@ -14,8 +14,7 @@
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
    $Revision$
-     $Author$
-       $Date$             
+   $Date$             
 
 NOTEs:
 
@@ -39,6 +38,14 @@ code on the hardware.
 #include "sim-options.h"
 #include "sim-assert.h"
 
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#include "sky-vu.h"
+#include "sky-vpe.h"
+#include "sky-libvpe.h"
+#endif
+/* end-sanitize-sky */
+
 #include "config.h"
 
 #include <stdio.h>
@@ -75,9 +82,7 @@ char* pr_uword64 PARAMS ((uword64 addr));
 
 
 /* Get the simulator engine description, without including the code: */
-#if (WITH_IGEN)
-#define LOADDRMASK (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3)
-#else
+#if !(WITH_IGEN)
 #define SIM_MANIFESTS
 #include "oengine.c"
 #undef SIM_MANIFESTS
@@ -149,20 +154,36 @@ static void ColdReset PARAMS((SIM_DESC sd));
 #define MONITOR_SIZE (1 << 11)
 #define MEM_SIZE (2 << 20)
 
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#undef MEM_SIZE
+#define MEM_SIZE (16 << 20) /* 16 MB */
+#endif
+/* end-sanitize-sky */
+
 #if defined(TRACE)
 static char *tracefile = "trace.din"; /* default filename for trace log */
 FILE *tracefh = NULL;
 static void open_trace PARAMS((SIM_DESC sd));
 #endif /* TRACE */
 
-#define OPTION_DINERO_TRACE  200
-#define OPTION_DINERO_FILE   201
+static DECLARE_OPTION_HANDLER (mips_option_handler);
+
+enum {
+  OPTION_DINERO_TRACE  = OPTION_START,
+  OPTION_DINERO_FILE
+/* start-sanitize-sky */
+  ,OPTION_FLOAT_TYPE
+/* end-sanitize-sky */
+};
 
 static SIM_RC
-mips_option_handler (sd, opt, arg)
+mips_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)
@@ -173,7 +194,7 @@ mips_option_handler (sd, opt, arg)
         allow external control of the program points being traced
         (i.e. only from main onwards, excluding the run-time setup,
         etc.). */
-      for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
+      for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
        {
          sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
          if (arg == NULL)
@@ -188,7 +209,7 @@ mips_option_handler (sd, opt, arg)
            STATE &= ~simTRACE;
          else
            {
-             fprintf (stderr, "Unreconized dinero-trace option `%s'\n", arg);
+             fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg);
              return SIM_RC_FAIL;
            }
        }
@@ -219,6 +240,20 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
 #endif /* TRACE */
       return SIM_RC_OK;
 
+/* start-sanitize-sky */
+    case OPTION_FLOAT_TYPE:
+      /* Use host (fast) or target (accurate) floating point implementation. */
+      if (arg && strcmp (arg, "host") == 0)
+       STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_TARGET;
+      else if (arg && strcmp (arg, "target") == 0)
+       STATE_FP_TYPE_OPT (sd) |= STATE_FP_TYPE_OPT_TARGET;
+      else
+       {
+         fprintf (stderr, "Unrecognized float-type option `%s'\n", arg);
+         return SIM_RC_FAIL;
+       }
+      return SIM_RC_OK;
+/* end-sanitize-sky */
     }
 
   return SIM_RC_OK;
@@ -232,6 +267,11 @@ static const OPTION mips_options[] =
   { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
       '\0', "FILE", "Write dinero trace to FILE",
       mips_option_handler },
+/* start-sanitize-sky */
+  { {"float-type", required_argument, NULL, OPTION_FLOAT_TYPE},
+      '\0', "host|target", "Use host (fast) or target (accurate) floating point",
+      mips_option_handler },
+/* end-sanitize-sky */
   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
 };
 
@@ -262,15 +302,6 @@ static void device_init(SIM_DESC sd) {
 #endif
 }
 
-/* start-sanitize-sky */
-#ifdef TARGET_SKY
-static struct {
-  short i[16];
-  int f[NUM_VU_REGS - 16];
-} vu_regs[2];
-#endif
-/* end-sanitize-sky */
-
 /*---------------------------------------------------------------------------*/
 /*-- GDB simulator interface ------------------------------------------------*/
 /*---------------------------------------------------------------------------*/
@@ -296,7 +327,7 @@ sim_open (kind, cb, abfd, argv)
   
   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
     return 0;
-  sim_add_option_table (sd, mips_options);
+  sim_add_option_table (sd, NULL, mips_options);
 
   /* Allocate core managed memory */
 
@@ -306,10 +337,22 @@ sim_open (kind, cb, abfd, argv)
      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 */
+/* start-sanitize-sky */
+#ifndef TARGET_SKY
+/* end-sanitize-sky */
   sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
                   K1BASE, K0SIZE,
                   MEM_SIZE, /* actual size */
                   K0BASE);
+/* start-sanitize-sky */
+#else
+  sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
+                  K1BASE, K0SIZE,
+                  MEM_SIZE, /* actual size */
+                  K0BASE, 
+                  0); /* add alias at 0x0000 */
+#endif
+/* end-sanitize-sky */
 
   device_init(sd);
 
@@ -386,34 +429,14 @@ sim_open (kind, cb, abfd, argv)
     /* start-sanitize-sky */
 #ifdef TARGET_SKY
     /* Now the VU registers */
-    for( rn = 0; rn < 16; rn++ ) { /* first the integer registers */
+    for( rn = 0; rn < NUM_VU_INTEGER_REGS; rn++ ) { 
       cpu->register_widths[rn + NUM_R5900_REGS] = 16;
       cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 16;
-
-      /* Hack for now - to test gdb interface */
-      vu_regs[0].i[rn] = rn + 0x100;
-      vu_regs[1].i[rn] = rn + 0x200;
     }
 
-    for( rn = 16; rn < NUM_VU_REGS; rn++ ) { /* then the FP registers */
-      float f;
-
+    for( rn = NUM_VU_INTEGER_REGS; rn < NUM_VU_REGS; rn++ ) { 
       cpu->register_widths[rn + NUM_R5900_REGS] = 32;
       cpu->register_widths[rn + NUM_R5900_REGS + NUM_VU_REGS] = 32;
-
-      /* Hack for now - to test gdb interface */
-      if( rn < 24 ) {
-       f = rn - 16 + 100.0;
-       vu_regs[0].f[rn-16] = *((unsigned *) &f);
-       f = rn - 16 + 200.0;
-       vu_regs[1].f[rn-16] = *((unsigned *) &f);
-      }
-      else {
-       f = (rn - 24)/4 + (rn - 24)%4 + 1000.0;
-       vu_regs[0].f[rn-16] = *((unsigned *) &f);
-       f = (rn - 24)/4 + (rn - 24)%4 + 2000.0;
-       vu_regs[1].f[rn-16] = *((unsigned *) &f);
-      }
     }
 #endif
     /* end-sanitize-sky */
@@ -554,7 +577,7 @@ sim_write (sd,addr,buffer,size)
       int cca;
       if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
        break;
-      if (sim_core_write_buffer (SD, CPU, sim_core_read_map, buffer + index, paddr, 1) != 1)
+      if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
        break;
     }
 
@@ -583,7 +606,7 @@ sim_read (sd,addr,buffer,size)
       int cca;
       if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
        break;
-      if (sim_core_read_buffer (SD, CPU, sim_core_read_map, buffer + index, paddr, 1) != 1)
+      if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
        break;
     }
 
@@ -632,28 +655,101 @@ sim_store_register (sd,rn,memory,length)
       HI1 = T2H_8(*(unsigned64*)memory);
       return 8;
     }
-
   /* end-sanitize-r5900 */
+
   /* start-sanitize-sky */
 #ifdef TARGET_SKY
-  else if( rn > NUM_R5900_REGS ) {
-    rn = rn - NUM_R5900_REGS;
-
-    if( rn < 16 ) 
-      vu_regs[0].i[rn] = T2H_2( *(unsigned short *) memory );
-    else if( rn < NUM_VU_REGS )
-      vu_regs[0].f[rn - 16] = T2H_4( *(unsigned int *) memory );
-    else {
-      rn = rn - NUM_VU_REGS;
-
-      if( rn < 16 ) 
-       vu_regs[1].i[rn] = T2H_2( *(unsigned short *) memory );
+  if (rn >= NUM_R5900_REGS) 
+    {
+      int size = 4;    /* Default register size */
+
+      rn = rn - NUM_R5900_REGS;
+
+      if (rn < NUM_VU_INTEGER_REGS)
+       size = write_vu_int_reg (&(vu0_device.state->regs), rn, memory);
       else if( rn < NUM_VU_REGS )
-       vu_regs[1].f[rn - 16] = T2H_4( *(unsigned int *) memory );
-      else
-       sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+       {
+         if (rn >= FIRST_VEC_REG)
+           {
+             rn -= FIRST_VEC_REG;
+             size = write_vu_vec_reg (&(vu0_device.state->regs), rn>>2, rn&3,
+                                     memory);
+           }
+         else switch (rn - NUM_VU_INTEGER_REGS)
+           {
+           case 0:
+             size = write_vu_special_reg (vu0_device.state, VU_REG_CIA,
+                                     memory);
+             break;
+           case 1:
+             size = write_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MR,
+                                     memory);
+             break;
+           case 2: /* VU0 has no P register */
+             break;
+           case 3:
+             size = write_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MI,
+                                     memory);
+             break;
+           case 4:
+             size = write_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MQ,
+                                     memory);
+             break;
+           default:
+             size = write_vu_acc_reg (&(vu0_device.state->regs), 
+                                     rn - (NUM_VU_INTEGER_REGS + 5),
+                                     memory);
+             break;
+           }
+       }
+      else {
+       rn = rn - NUM_VU_REGS;
+
+       if( rn < NUM_VU_INTEGER_REGS ) 
+         size = write_vu_int_reg (&(vu1_device.state->regs), rn, memory);
+       else if( rn < NUM_VU_REGS )
+         {
+           if (rn >= FIRST_VEC_REG)
+             {
+               rn -= FIRST_VEC_REG;
+               size = write_vu_vec_reg (&(vu1_device.state->regs), 
+                                         rn >> 2, rn & 3, memory);
+             }
+           else switch (rn - NUM_VU_INTEGER_REGS)
+             {
+             case 0:
+               size = write_vu_special_reg (vu1_device.state, VU_REG_CIA,
+                                           memory);
+               break;
+             case 1:
+               size = write_vu_misc_reg (&(vu1_device.state->regs), 
+                                        VU_REG_MR, memory);
+               break;
+             case 2: 
+               size = write_vu_misc_reg (&(vu1_device.state->regs), 
+                                        VU_REG_MP, memory);
+               break;
+             case 3:
+               size = write_vu_misc_reg (&(vu1_device.state->regs), 
+                                        VU_REG_MI, memory);
+               break;
+             case 4:
+               size = write_vu_misc_reg (&(vu1_device.state->regs), 
+                                        VU_REG_MQ, memory);
+               break;
+             default:
+               size = write_vu_acc_reg (&(vu1_device.state->regs), 
+                                       rn - (NUM_VU_INTEGER_REGS + 5),
+                                       memory);
+               break;
+             }
+         }
+       else
+         sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
+      }
+
+      return size;
     }
-  }
 #endif
   /* end-sanitize-sky */
 
@@ -721,31 +817,104 @@ sim_fetch_register (sd,rn,memory,length)
       *((unsigned64*)memory) = H2T_8(HI1);
       return 8;
     }
-
   /* end-sanitize-r5900 */
+
   /* start-sanitize-sky */
 #ifdef TARGET_SKY
-  if( rn > NUM_R5900_REGS ) {
-    rn = rn - NUM_R5900_REGS;
-
-    if( rn < 16 ) 
-      *((unsigned short *) memory) = H2T_2( vu_regs[0].i[rn] );
-    else if( rn < NUM_VU_REGS )
-      *((unsigned int *) memory) = H2T_4( vu_regs[0].f[rn - 16] );
-    else {
-      rn = rn - NUM_VU_REGS;
-
-      if( rn < 16 ) 
-       (*(unsigned short *) memory) = H2T_2( vu_regs[1].i[rn] );
-      else if( rn < NUM_VU_REGS )
-       (*(unsigned int *) memory) = H2T_4( vu_regs[1].f[rn - 16] );
+  if (rn >= NUM_R5900_REGS) 
+    {
+      int size = 4; /* default register width */
+
+      rn = rn - NUM_R5900_REGS;
+
+      if (rn < NUM_VU_INTEGER_REGS)
+       size = read_vu_int_reg (&(vu0_device.state->regs), rn, memory);
+      else if (rn < NUM_VU_REGS)
+       {
+         if (rn >= FIRST_VEC_REG)
+           {
+             rn -= FIRST_VEC_REG;
+             size = read_vu_vec_reg (&(vu0_device.state->regs), rn>>2, rn & 3,
+                                     memory);
+           }
+         else switch (rn - NUM_VU_INTEGER_REGS)
+           {
+           case 0:
+             size = read_vu_special_reg (vu0_device.state, VU_REG_CIA,
+                                     memory);
+
+             break;
+           case 1:
+             size = read_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MR,
+                                     memory);
+             break;
+           case 2: /* VU0 has no P register */
+             break;
+           case 3:
+             size = read_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MI,
+                                     memory);
+             break;
+           case 4:
+             size = read_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MQ,
+                                     memory);
+             break;
+           default:
+             size = read_vu_acc_reg (&(vu0_device.state->regs), 
+                                     rn - (NUM_VU_INTEGER_REGS + 5),
+                                     memory);
+             break;
+           }
+       }
       else
-       sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
+       {
+         rn = rn - NUM_VU_REGS;
+       
+         if (rn < NUM_VU_INTEGER_REGS) 
+           size = read_vu_int_reg (&(vu1_device.state->regs), rn, memory);
+         else if (rn < NUM_VU_REGS)
+           {
+             if (rn >= FIRST_VEC_REG)
+               {
+                 rn -= FIRST_VEC_REG;
+                 size = read_vu_vec_reg (&(vu1_device.state->regs), 
+                                         rn >> 2, rn & 3, memory);
+               }
+             else switch (rn - NUM_VU_INTEGER_REGS)
+               {
+               case 0:
+                 size = read_vu_special_reg (vu1_device.state, VU_REG_CIA,
+                                             memory);
+                 break;
+               case 1:
+                 size = read_vu_misc_reg (&(vu1_device.state->regs), 
+                                          VU_REG_MR, memory);
+                 break;
+               case 2:
+                 size = read_vu_misc_reg (&(vu1_device.state->regs), 
+                                          VU_REG_MP, memory);
+                 break;
+               case 3:
+                 size = read_vu_misc_reg (&(vu1_device.state->regs), 
+                                          VU_REG_MI, memory);
+                 break;
+               case 4:
+                 size = read_vu_misc_reg (&(vu1_device.state->regs), 
+                                          VU_REG_MQ, memory);
+                 break;
+               default:
+                 size = read_vu_acc_reg (&(vu1_device.state->regs), 
+                                         rn - (NUM_VU_INTEGER_REGS + 5),
+                                         memory);
+                 break;
+               }
+           }
+         else
+           sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
+       }
+
+      return size;
     }
-    return -1;
-  }
 #endif
-
   /* end-sanitize-sky */
 
   /* Any floating point register */
@@ -776,43 +945,6 @@ sim_fetch_register (sd,rn,memory,length)
 }
 
 
-void
-sim_info (sd,verbose)
-     SIM_DESC sd;
-     int verbose;
-{
-  /* Accessed from the GDB "info files" command: */
-  if (STATE_VERBOSE_P (sd) || verbose)
-    {
-      
-      sim_io_printf (sd, "MIPS %d-bit %s endian simulator\n",
-                    WITH_TARGET_WORD_BITSIZE,
-                    (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little"));
-      
-#if !defined(FASTSIM)
-      /* It would be a useful feature, if when performing multi-cycle
-        simulations (rather than single-stepping) we keep the start and
-        end times of the execution, so that we can give a performance
-        figure for the simulator. */
-#endif /* !FASTSIM */
-      sim_io_printf (sd, "Number of execution cycles = %ld\n",
-                    (long) sim_events_time (sd));
-      
-      /* print information pertaining to MIPS ISA and architecture being simulated */
-      /* things that may be interesting */
-      /* instructions executed - if available */
-      /* cycles executed - if available */
-      /* pipeline stalls - if available */
-      /* virtual time taken */
-      /* profiling size */
-      /* profiling frequency */
-      /* profile minpc */
-      /* profile maxpc */
-    }
-  profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL);
-}
-
-
 SIM_RC
 sim_create_inferior (sd, abfd, argv,env)
      SIM_DESC sd;
@@ -989,9 +1121,12 @@ sim_monitor (SIM_DESC sd,
       /*      [A0 + 4] = instruction cache size */
       /*      [A0 + 8] = data cache size */
       {
-       address_word value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+       unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
+       unsigned_4 zero = 0;
        H2T (value);
-       sim_write (sd, A0, (char *)&value, sizeof (value));
+       sim_write (sd, A0 + 0, (char *)&value, 4);
+       sim_write (sd, A0 + 4, (char *)&zero, 4);
+       sim_write (sd, A0 + 8, (char *)&zero, 4);
        /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
        break;
       }
@@ -1489,7 +1624,7 @@ load_memory (SIM_DESC sd,
             uword64* memvalp,
             uword64* memval1p,
             int CCA,
-            int AccessLength,
+            unsigned int AccessLength,
             address_word pAddr,
             address_word vAddr,
             int IorD)
@@ -1516,9 +1651,9 @@ load_memory (SIM_DESC sd,
   if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
     {
       /* In reality this should be a Bus Error */
-      sim_io_error (sd, "AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",
+      sim_io_error (sd, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
                    AccessLength,
-                   (LOADDRMASK + 1) << 2,
+                   (LOADDRMASK + 1) << 3,
                    pr_addr (pAddr));
     }
 
@@ -1534,43 +1669,42 @@ load_memory (SIM_DESC sd,
     {
     case AccessLength_QUADWORD :
       {
-       unsigned_16 val = sim_core_read_aligned_16 (cpu, NULL_CIA,
-                                                   sim_core_read_map, pAddr);
+       unsigned_16 val = sim_core_read_aligned_16 (cpu, NULL_CIA, read_map, pAddr);
        value1 = VH8_16 (val);
        value = VL8_16 (val);
        break;
       }
     case AccessLength_DOUBLEWORD :
       value = sim_core_read_aligned_8 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
+                                      read_map, pAddr);
       break;
     case AccessLength_SEPTIBYTE :
       value = sim_core_read_misaligned_7 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
+                                         read_map, pAddr);
       break;
     case AccessLength_SEXTIBYTE :
       value = sim_core_read_misaligned_6 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
+                                         read_map, pAddr);
       break;
     case AccessLength_QUINTIBYTE :
       value = sim_core_read_misaligned_5 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
+                                         read_map, pAddr);
       break;
     case AccessLength_WORD :
       value = sim_core_read_aligned_4 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
+                                      read_map, pAddr);
       break;
     case AccessLength_TRIPLEBYTE :
       value = sim_core_read_misaligned_3 (cpu, NULL_CIA,
-                                         sim_core_read_map, pAddr);
+                                         read_map, pAddr);
       break;
     case AccessLength_HALFWORD :
       value = sim_core_read_aligned_2 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
+                                      read_map, pAddr);
       break;
     case AccessLength_BYTE :
       value = sim_core_read_aligned_1 (cpu, NULL_CIA,
-                                      sim_core_read_map, pAddr);
+                                      read_map, pAddr);
       break;
     default:
       abort ();
@@ -1581,13 +1715,13 @@ load_memory (SIM_DESC sd,
         (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
 #endif /* DEBUG */
   
-  /* See also store_memory. */
-  if (AccessLength <= AccessLength_DOUBLEWORD)
+  /* See also store_memory. Position data in correct byte lanes. */
+  if (AccessLength <= LOADDRMASK)
     {
       if (BigEndianMem)
        /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
           shifted to the most significant byte position.  */
-       value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
+       value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
       else
        /* For little endian target, byte (pAddr&LOADDRMASK == 0)
           is already in the correct postition. */
@@ -1622,7 +1756,7 @@ store_memory (SIM_DESC sd,
              sim_cpu *cpu,
              address_word cia,
              int CCA,
-             int AccessLength,
+             unsigned int AccessLength,
              uword64 MemElem,
              uword64 MemElem1,   /* High order 64 bits */
              address_word pAddr,
@@ -1638,7 +1772,10 @@ store_memory (SIM_DESC sd,
 #endif /* WARN_MEM */
   
   if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
-    sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
+    sim_io_error (sd, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n",
+                 AccessLength,
+                 (LOADDRMASK + 1) << 3,
+                 pr_addr(pAddr));
   
 #if defined(TRACE)
   dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
@@ -1648,13 +1785,13 @@ store_memory (SIM_DESC sd,
   printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
 #endif /* DEBUG */
   
-  /* See also load_memory */
-  if (AccessLength <= AccessLength_DOUBLEWORD)
+  /* See also load_memory. Position data in correct byte lanes. */
+  if (AccessLength <= LOADDRMASK)
     {
       if (BigEndianMem)
        /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
           shifted to the most significant byte position.  */
-       MemElem >>= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
+       MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8);
       else
        /* For little endian target, byte (pAddr&LOADDRMASK == 0)
           is already in the correct postition. */
@@ -1670,41 +1807,40 @@ store_memory (SIM_DESC sd,
     case AccessLength_QUADWORD :
       {
        unsigned_16 val = U16_8 (MemElem1, MemElem);
-       sim_core_write_aligned_16 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, val);
+       sim_core_write_aligned_16 (cpu, NULL_CIA, write_map, pAddr, val);
        break;
       }
     case AccessLength_DOUBLEWORD :
       sim_core_write_aligned_8 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
+                               write_map, pAddr, MemElem);
       break;
     case AccessLength_SEPTIBYTE :
       sim_core_write_misaligned_7 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
+                                  write_map, pAddr, MemElem);
       break;
     case AccessLength_SEXTIBYTE :
       sim_core_write_misaligned_6 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
+                                  write_map, pAddr, MemElem);
       break;
     case AccessLength_QUINTIBYTE :
       sim_core_write_misaligned_5 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
+                                  write_map, pAddr, MemElem);
       break;
     case AccessLength_WORD :
       sim_core_write_aligned_4 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
+                               write_map, pAddr, MemElem);
       break;
     case AccessLength_TRIPLEBYTE :
       sim_core_write_misaligned_3 (cpu, NULL_CIA,
-                                  sim_core_write_map, pAddr, MemElem);
+                                  write_map, pAddr, MemElem);
       break;
     case AccessLength_HALFWORD :
       sim_core_write_aligned_2 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
+                               write_map, pAddr, MemElem);
       break;
     case AccessLength_BYTE :
       sim_core_write_aligned_1 (cpu, NULL_CIA,
-                               sim_core_write_map, pAddr, MemElem);
+                               write_map, pAddr, MemElem);
       break;
     default:
       abort ();
@@ -1819,7 +1955,7 @@ signal_exception (SIM_DESC sd,
         code = (instruction >> 6) & 0xFFFFF;
         
         sim_io_eprintf(sd,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
-                    code, pr_addr(cia));
+                      code, pr_addr(cia));
       }
      break;
 
@@ -2923,6 +3059,7 @@ SquareRoot(op,fmt)
   return(result);
 }
 
+#if 0
 uword64
 Max (uword64 op1,
      uword64 op2,
@@ -2990,7 +3127,9 @@ Max (uword64 op1,
 
   return(result);
 }
+#endif 
 
+#if 0
 uword64
 Min (uword64 op1,
      uword64 op2,
@@ -3058,6 +3197,7 @@ Min (uword64 op1,
 
   return(result);
 }
+#endif
 
 uword64
 convert (SIM_DESC sd,
@@ -3232,6 +3372,35 @@ cop_ld (SIM_DESC sd,
   return;
 }
 
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+void
+cop_lq (SIM_DESC sd,
+       sim_cpu *cpu,
+       address_word cia,
+       int coproc_num,
+       int coproc_reg,
+       unsigned128 memword)
+{
+  switch (coproc_num)
+    {
+    case 2:
+      /* XXX COP2 */
+      break;
+      
+    default:
+      sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
+                   coproc_num,coproc_reg,pr_addr(cia));
+      break;
+    }
+  
+  return;
+}
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+
 unsigned int
 cop_sw (SIM_DESC sd,
        sim_cpu *cpu,
@@ -3291,6 +3460,35 @@ cop_sd (SIM_DESC sd,
   return(value);
 }
 
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+unsigned128
+cop_sq (SIM_DESC sd,
+       sim_cpu *cpu,
+       address_word cia,
+       int coproc_num,
+       int coproc_reg)
+{
+  unsigned128 value = U16_8(0, 0);
+  switch (coproc_num)
+    {
+    case 2:
+      /* XXX COP2 */
+      break;
+
+    default:
+      sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",
+                   coproc_num,coproc_reg,pr_addr(cia));
+      break;
+    }
+
+  return(value);
+}
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+
 void
 decode_coproc (SIM_DESC sd,
               sim_cpu *cpu,
@@ -3432,9 +3630,179 @@ decode_coproc (SIM_DESC sd,
     break;
     
     case 2: /* undefined co-processor */
-      sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
-      break;
-      
+      {
+       int handle = 0;
+
+       /* start-sanitize-sky */
+#ifdef TARGET_SKY
+       /* On the R5900, this refers to a "VU" vector co-processor. */
+
+       int i_25_21 = (instruction >> 21) & 0x1f;
+       int i_20_16 = (instruction >> 16) & 0x1f;
+       int i_15_11 = (instruction >> 11) & 0x1f;
+       int i_15_0 = instruction & 0xffff;
+       int i_10_1 = (instruction >> 1) & 0x3ff;
+       int i_5_0 = instruction & 0x03f;
+       int interlock = instruction & 0x01;
+       int co = (instruction >> 25) & 0x01;
+       /* setup for semantic.c-like actions below */
+       typedef unsigned_4 instruction_word;
+       int CIA = cia;
+       int NIA = cia + 4;
+       sim_cpu* CPU_ = cpu;
+
+       handle = 1;
+
+       /* test COP2 usability */
+       if(! (SR & status_CU2))
+         {
+           SignalException(CoProcessorUnusable,instruction);       
+           /* NOTREACHED */
+         }
+
+       /* classify & execute basic COP2 instructions */
+       if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
+         {
+           address_word offset = EXTEND16(i_15_0) << 2;
+           if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+         }
+       else if(i_25_21 == 0x08 && i_20_16==0x02) /* BC2FL */
+         {
+           address_word offset = EXTEND16(i_15_0) << 2;
+           if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+           else NULLIFY_NEXT_INSTRUCTION();
+         }
+       else if(i_25_21 == 0x08 && i_20_16 == 0x01) /* BC2T */
+         {
+           address_word offset = EXTEND16(i_15_0) << 2;
+           if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+         }
+       else if(i_25_21 == 0x08 && i_20_16 == 0x03) /* BC2TL */
+         {
+           address_word offset = EXTEND16(i_15_0) << 2;
+           if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+           else NULLIFY_NEXT_INSTRUCTION();
+         }
+       else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
+               (i_25_21 == 0x01)) /* QMFC2 */
+         {
+           int rt = i_20_16;
+           int id = i_15_11;
+           address_word vu_cr_addr; /* VU control register address */
+           unsigned_4 data;
+
+           /* interlock checking */
+           if(vu0_busy_in_macro_mode()) /* busy in macro mode */
+             {
+               /* interlock bit invalid here */
+               if(interlock) 
+                 ; /* XXX: warning */
+
+               /* always check data hazard */
+               while(vu0_macro_hazard_check(id))
+                 vu0_issue(sd);
+             }
+           else if(vu0_busy_in_micro_mode() && interlock)
+             {
+               while(vu0_busy_in_micro_mode())
+                 vu0_issue(sd);
+             }
+
+           /* compute VU register address */
+           if(i_25_21 == 0x01) /* QMFC2 */
+             vu_cr_addr = VU0_REGISTER_WINDOW_START + (id * 16);
+           else /* CFC2 */
+             vu_cr_addr = VU0_MST + (id * 16);
+
+           /* read or write word */
+           data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
+           GPR[rt] = EXTEND64(data);
+         }
+       else if((i_25_21 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
+               (i_25_21 == 0x05)) /* QMTC2 */
+         {
+           int rt = i_20_16;
+           int id = i_15_11;
+           address_word vu_cr_addr; /* VU control register address */
+           unsigned_4 data;
+
+           /* interlock checking */
+           if(vu0_busy_in_macro_mode()) /* busy in macro mode */
+             {
+               /* interlock bit invalid here */
+               if(interlock) 
+                 ; /* XXX: warning */
+
+               /* always check data hazard */
+               while(vu0_macro_hazard_check(id))
+                 vu0_issue(sd);
+             }
+           else if(vu0_busy_in_micro_mode())
+             {
+               if(interlock)
+                 {
+                   while(! vu0_micro_interlock_released())
+                     vu0_issue(sd);
+                 }
+             }
+
+           /* compute VU register address */
+           if(i_25_21 == 0x05) /* QMTC2 */
+             vu_cr_addr = VU0_REGISTER_WINDOW_START + (id * 16);
+           else /* CTC2 */
+             vu_cr_addr = VU0_MST + (id * 16);
+
+           data = GPR[rt];
+           sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
+         }
+       else if( 0 /* XXX: ... upper ... */)
+         {
+           unsigned_4 vu_upper, vu_lower;
+           vu_upper =
+             0x00000000 | /* bits 31 .. 25 */
+             instruction & 0x01ffffff; /* bits 24 .. 0 */
+           vu_lower = 0x8000033c; /* NOP */
+
+           while(vu0_busy_in_micro_mode())
+             vu0_issue(sd);
+
+           vu0_macro_issue(vu_upper, vu_lower);
+         }
+       else if( 0 /* XXX: ... lower ... */)
+         {
+           unsigned_4 vu_upper, vu_lower;
+           vu_upper = 0x000002ff; /* NOP */
+           vu_lower =
+             0x10000000 | /* bits 31 .. 25 */
+             instruction & 0x01ffffff; /* bits 24 .. 0 */
+
+           while(vu0_busy_in_micro_mode())
+             vu0_issue(sd);
+
+           vu0_macro_issue(vu_upper, vu_lower);
+         }
+       /* XXX */
+       /* ... other COP2 instructions ... */
+       else
+         {
+           SignalException(ReservedInstruction, instruction); 
+           /* NOTREACHED */
+         }
+       
+       /* cleanup for semantic.c-like actions above */
+       PC = NIA;
+
+#endif /* TARGET_SKY */
+       /* end-sanitize-sky */
+
+       if(! handle)
+         {
+           sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
+                          instruction,pr_addr(cia));
+         }
+      }
+    break;
+    
     case 1: /* should not occur (FPU co-processor) */
     case 3: /* should not occur (FPU co-processor) */
       SignalException(ReservedInstruction,instruction);
@@ -3444,6 +3812,7 @@ decode_coproc (SIM_DESC sd,
   return;
 }
 
+
 /*-- instruction simulation -------------------------------------------------*/
 
 /* When the IGEN simulator is being built, the function below is be
This page took 0.035943 seconds and 4 git commands to generate.