Implement 32 bit MIPS16 instructions listed in m16.igen.
[deliverable/binutils-gdb.git] / sim / mips / sky-pke.c
index cf7408b0684785298e50f80d7f555e79726765d3..6e318750eaab4a3dd451b946204bef9178341142 100644 (file)
@@ -4,15 +4,16 @@
 #include "config.h"
 
 #include <stdlib.h>
-#include "sky-pke.h"
-#include "sky-dma.h"
+#include "sim-main.h"
 #include "sim-bits.h"
 #include "sim-assert.h"
-#include "sky-vu0.h"
-#include "sky-vu1.h"
+#include "sky-pke.h"
+#include "sky-dma.h"
+#include "sky-vu.h"
 #include "sky-gpuif.h"
 #include "sky-device.h"
 
+
 #ifdef HAVE_STRING_H
 #include <string.h>
 #else
@@ -64,6 +65,11 @@ static void pke_code_direct(struct pke_device* me, unsigned_4 pkecode);
 static void pke_code_directhl(struct pke_device* me, unsigned_4 pkecode);
 static void pke_code_unpack(struct pke_device* me, unsigned_4 pkecode);
 static void pke_code_error(struct pke_device* me, unsigned_4 pkecode);
+unsigned_4 pke_fifo_flush(struct pke_fifo*);
+void pke_fifo_reset(struct pke_fifo*);
+struct fifo_quadword* pke_fifo_fit(struct pke_fifo*);
+struct fifo_quadword* pke_fifo_access(struct pke_fifo*, unsigned_4 qwnum);
+void pke_fifo_old(struct pke_fifo*, unsigned_4 qwnum);
 
 
 
@@ -192,6 +198,70 @@ pke_attach(SIM_DESC sd, struct pke_device* me)
 }
 
 
+/* Read PKE Pseudo-PC into buf in target order */
+int
+read_pke_pc (struct pke_device *me, void *buf)
+{
+  *((int *) buf) = H2T_4( (me->fifo_pc << 2) | me->qw_pc );
+  return 4;
+}
+
+
+/* Read PKE reg into buf in target order */
+int
+read_pke_reg (struct pke_device *me, int reg_num, void *buf)
+{
+  /* handle reads to individual registers; clear `readable' on error */
+  switch (reg_num)
+    {
+    /* handle common case of register reading, side-effect free */
+    /* PKE1-only registers*/
+    case PKE_REG_BASE:
+    case PKE_REG_OFST:
+    case PKE_REG_TOPS:
+    case PKE_REG_TOP:
+    case PKE_REG_DBF:
+      if (me->pke_number == 0)
+       {
+         *((int *) buf) = 0;
+         break;
+       }
+      /* fall through */
+
+    /* PKE0 & PKE1 common registers*/
+    case PKE_REG_STAT:
+    case PKE_REG_ERR:
+    case PKE_REG_MARK:
+    case PKE_REG_CYCLE:
+    case PKE_REG_MODE:
+    case PKE_REG_NUM:
+    case PKE_REG_MASK:
+    case PKE_REG_CODE:
+    case PKE_REG_ITOPS:
+    case PKE_REG_ITOP:
+    case PKE_REG_R0:
+    case PKE_REG_R1:
+    case PKE_REG_R2:
+    case PKE_REG_R3:
+    case PKE_REG_C0:
+    case PKE_REG_C1:
+    case PKE_REG_C2:
+    case PKE_REG_C3:
+      *((int *) buf) = H2T_4(me->regs[reg_num][0]);
+      break;
+
+    /* handle common case of write-only registers */
+    case PKE_REG_FBRST:
+      *((int *) buf) = 0;
+      break;
+
+    default:
+      ASSERT(0); /* tests above should prevent this possibility */
+    }
+
+  return 4;
+}
+
 
 /* Handle a PKE read; return no. of bytes read */
 
@@ -225,68 +295,15 @@ pke_io_read_buffer(device *me_,
       /* register bank */
       int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
       int reg_byte = ADDR_OFFSET_QW(addr);      /* find byte-offset inside register bank */
-      int readable = 1;
       quadword result;
 
       /* clear result */
       result[0] = result[1] = result[2] = result[3] = 0;
 
-      /* handle reads to individual registers; clear `readable' on error */
-      switch(reg_num)
-       {
-         /* handle common case of register reading, side-effect free */
-         /* PKE1-only registers*/
-       case PKE_REG_BASE:
-       case PKE_REG_OFST:
-       case PKE_REG_TOPS:
-       case PKE_REG_TOP:
-       case PKE_REG_DBF:
-         if(me->pke_number == 0)
-           readable = 0;
-         /* fall through */
-         /* PKE0 & PKE1 common registers*/
-       case PKE_REG_STAT:
-       case PKE_REG_ERR:
-       case PKE_REG_MARK:
-       case PKE_REG_CYCLE:
-       case PKE_REG_MODE:
-       case PKE_REG_NUM:
-       case PKE_REG_MASK:
-       case PKE_REG_CODE:
-       case PKE_REG_ITOPS:
-       case PKE_REG_ITOP:
-       case PKE_REG_R0:
-       case PKE_REG_R1:
-       case PKE_REG_R2:
-       case PKE_REG_R3:
-       case PKE_REG_C0:
-       case PKE_REG_C1:
-       case PKE_REG_C2:
-       case PKE_REG_C3:
-         result[0] = H2T_4(me->regs[reg_num][0]);
-         break;
-
-         /* handle common case of write-only registers */
-       case PKE_REG_FBRST:
-         readable = 0;
-         break;
-
-       default:
-         ASSERT(0); /* test above should prevent this possibility */
-       }
+      read_pke_reg (me, reg_num, result);
 
       /* perform transfer & return */
-      if(readable) 
-       {
-         /* copy the bits */
-         memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes);
-         /* okay */
-       }
-      else
-       {
-         /* return zero bits */
-         memset(dest, 0, nr_bytes);
-       } 
+      memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes);
 
       return nr_bytes;
       /* NOTREACHED */
@@ -305,8 +322,104 @@ pke_io_read_buffer(device *me_,
   return 0;
 }
 
+/* Write PKE reg from buf, which is in target order */
+int
+write_pke_reg (struct pke_device *me, int reg_num, const void *buf)
+{
+  int writeable = 1;
+  /* make words host-endian */
+  unsigned_4 input = T2H_4( *((unsigned_4 *) buf) );
+
+  /* handle writes to individual registers; clear `writeable' on error */
+  switch (reg_num)
+    {
+    case PKE_REG_FBRST:
+      /* Order these tests from least to most overriding, in case
+        multiple bits are set. */
+      if(BIT_MASK_GET(input, PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E))
+       {
+         /* clear a bunch of status bits */
+         PKE_REG_MASK_SET(me, STAT, PSS, 0);
+         PKE_REG_MASK_SET(me, STAT, PFS, 0);
+         PKE_REG_MASK_SET(me, STAT, PIS, 0);
+         PKE_REG_MASK_SET(me, STAT, INT, 0);
+         PKE_REG_MASK_SET(me, STAT, ER0, 0);
+         PKE_REG_MASK_SET(me, STAT, ER1, 0);
+         me->flags &= ~PKE_FLAG_PENDING_PSS;
+         /* will allow resumption of possible stalled instruction */
+       }
+      if(BIT_MASK_GET(input, PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E))
+       {
+         me->flags |= PKE_FLAG_PENDING_PSS;
+       }
+      if(BIT_MASK_GET(input, PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E))
+       {
+         PKE_REG_MASK_SET(me, STAT, PFS, 1);
+       }
+      if(BIT_MASK_GET(input, PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E))
+       {
+         pke_reset(me);
+       }
+      break;
+      
+    case PKE_REG_ERR:
+      /* copy bottom three bits */
+      BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input, 0, 2));
+      break;
+
+    case PKE_REG_MARK:
+      /* copy bottom sixteen bits */
+      PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input, 0, 15));
+      /* reset MRK bit in STAT */
+      PKE_REG_MASK_SET(me, STAT, MRK, 0);
+      break;
+
+      /* handle common case of read-only registers */
+      /* PKE1-only registers - not really necessary to handle separately */
+    case PKE_REG_BASE:
+    case PKE_REG_OFST:
+    case PKE_REG_TOPS:
+    case PKE_REG_TOP:
+    case PKE_REG_DBF:
+      if(me->pke_number == 0)
+       writeable = 0;
+      /* fall through */
+      /* PKE0 & PKE1 common registers*/
+    case PKE_REG_STAT:
+      /* ignore FDR bit for PKE1_STAT -- simulator does not implement PKE->RAM transfers */
+    case PKE_REG_CYCLE:
+    case PKE_REG_MODE:
+    case PKE_REG_NUM:
+    case PKE_REG_MASK:
+    case PKE_REG_CODE:
+    case PKE_REG_ITOPS:
+    case PKE_REG_ITOP:
+    case PKE_REG_R0:
+    case PKE_REG_R1:
+    case PKE_REG_R2:
+    case PKE_REG_R3:
+    case PKE_REG_C0:
+    case PKE_REG_C1:
+    case PKE_REG_C2:
+    case PKE_REG_C3:
+      writeable = 0;
+      break;
+
+    default:
+      ASSERT(0); /* test above should prevent this possibility */
+    }
+
+  /* perform return */
+  if(! writeable) 
+    {
+      return 0; /* error */
+    } 
+
+  return 4;
+}
+
 
-/* Handle a PKE read; return no. of bytes written */
+/* Handle a PKE write; return no. of bytes written */
 
 int
 pke_io_write_buffer(device *me_,
@@ -338,7 +451,6 @@ pke_io_write_buffer(device *me_,
       /* register bank */
       int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4;
       int reg_byte = ADDR_OFFSET_QW(addr);      /* find byte-offset inside register bank */
-      int writeable = 1;
       quadword input;
 
       /* clear input */
@@ -347,95 +459,7 @@ pke_io_write_buffer(device *me_,
       /* write user-given bytes into input */
       memcpy(((unsigned_1*) &input) + reg_byte, src, nr_bytes);
 
-      /* make words host-endian */
-      input[0] = T2H_4(input[0]);
-      /* we may ignore other words */
-
-      /* handle writes to individual registers; clear `writeable' on error */
-      switch(reg_num)
-       {
-       case PKE_REG_FBRST:
-         /* Order these tests from least to most overriding, in case
-             multiple bits are set. */
-         if(BIT_MASK_GET(input[0], PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E))
-           {
-             /* clear a bunch of status bits */
-             PKE_REG_MASK_SET(me, STAT, PSS, 0);
-             PKE_REG_MASK_SET(me, STAT, PFS, 0);
-             PKE_REG_MASK_SET(me, STAT, PIS, 0);
-             PKE_REG_MASK_SET(me, STAT, INT, 0);
-             PKE_REG_MASK_SET(me, STAT, ER0, 0);
-             PKE_REG_MASK_SET(me, STAT, ER1, 0);
-             me->flags &= ~PKE_FLAG_PENDING_PSS;
-             /* will allow resumption of possible stalled instruction */
-           }
-         if(BIT_MASK_GET(input[0], PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E))
-           {
-             me->flags |= PKE_FLAG_PENDING_PSS;
-           }
-         if(BIT_MASK_GET(input[0], PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E))
-           {
-             PKE_REG_MASK_SET(me, STAT, PFS, 1);
-           }
-         if(BIT_MASK_GET(input[0], PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E))
-           {
-             pke_reset(me);
-           }
-         break;
-
-       case PKE_REG_ERR:
-         /* copy bottom three bits */
-         BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input[0], 0, 2));
-         break;
-
-       case PKE_REG_MARK:
-         /* copy bottom sixteen bits */
-         PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input[0], 0, 15));
-         /* reset MRK bit in STAT */
-         PKE_REG_MASK_SET(me, STAT, MRK, 0);
-         break;
-
-         /* handle common case of read-only registers */
-         /* PKE1-only registers - not really necessary to handle separately */
-       case PKE_REG_BASE:
-       case PKE_REG_OFST:
-       case PKE_REG_TOPS:
-       case PKE_REG_TOP:
-       case PKE_REG_DBF:
-         if(me->pke_number == 0)
-           writeable = 0;
-         /* fall through */
-         /* PKE0 & PKE1 common registers*/
-       case PKE_REG_STAT:
-         /* ignore FDR bit for PKE1_STAT -- simulator does not implement PKE->RAM transfers */
-       case PKE_REG_CYCLE:
-       case PKE_REG_MODE:
-       case PKE_REG_NUM:
-       case PKE_REG_MASK:
-       case PKE_REG_CODE:
-       case PKE_REG_ITOPS:
-       case PKE_REG_ITOP:
-       case PKE_REG_R0:
-       case PKE_REG_R1:
-       case PKE_REG_R2:
-       case PKE_REG_R3:
-       case PKE_REG_C0:
-       case PKE_REG_C1:
-       case PKE_REG_C2:
-       case PKE_REG_C3:
-         writeable = 0;
-         break;
-
-       default:
-         ASSERT(0); /* test above should prevent this possibility */
-       }
-
-      /* perform return */
-      if(! writeable) 
-       {
-         ; /* error */
-       } 
-
+      write_pke_reg (me, reg_num, input);
       return nr_bytes;
 
       /* NOTREACHED */
@@ -1069,16 +1093,19 @@ pke_check_stall(struct pke_device* me, enum pke_check_target what)
     }
   else if(what == chk_path1) /* VU -> GPUIF */
     {
+      ASSERT(me->pke_number == 1);
       if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 1)
        any_stall = 1;
     }
   else if(what == chk_path2) /* PKE -> GPUIF */
     {
+      ASSERT(me->pke_number == 1);
       if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 2)
        any_stall = 1;
     }
   else if(what == chk_path3) /* DMA -> GPUIF */
     {
+      ASSERT(me->pke_number == 1);
       if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 3)
        any_stall = 1;
     }
@@ -1223,12 +1250,12 @@ pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode)
 
   /* set appropriate bit */
   if(BIT_MASK_GET(imm, PKE_REG_MSKPATH3_B, PKE_REG_MSKPATH3_E) != 0)
-    gif_mode = GIF_REG_MODE_M3R_MASK;
+    gif_mode = GIF_REG_STAT_M3P;
   else
     gif_mode = 0;
 
-  /* write register; patrickm code will look at M3R bit only */
-  PKE_MEM_WRITE(me, GIF_REG_MODE, & gif_mode, 4);
+  /* write register to "read-only" register; gpuif code will look at M3P bit only */
+  PKE_MEM_WRITE(me, GIF_REG_VIF_M3P, & gif_mode, 4);
 
   /* done */
   pke_pc_advance(me, 1);
@@ -1976,20 +2003,12 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
          switch(PKE_REG_MASK_GET(me, MODE, MDE))
            {
            case PKE_MODE_ADDROW: /* add row registers to output data */
+           case PKE_MODE_ACCROW: /* same .. later conditionally accumulate */
              for(i=0; i<4; i++)
                /* exploit R0..R3 contiguity */
                unpacked_data[i] += me->regs[PKE_REG_R0 + i][0];
              break;
 
-           case PKE_MODE_ACCROW: /* add row registers to output data; accumulate */
-             for(i=0; i<4; i++)
-               {
-                 /* exploit R0..R3 contiguity */
-                 unpacked_data[i] += me->regs[PKE_REG_R0 + i][0];
-                 me->regs[PKE_REG_R0 + i][0] = unpacked_data[i];
-               }
-             break;
-
            case PKE_MODE_INPUT: /* pass data through */
            default: /* specified as undefined */
              ;
@@ -2010,6 +2029,11 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
                    {
                    case PKE_MASKREG_INPUT: 
                      masked_value = & unpacked_data[i];
+
+                     /* conditionally accumulate */
+                     if(PKE_REG_MASK_GET(me, MODE, MDE) == PKE_MODE_ACCROW)
+                       me->regs[PKE_REG_R0 + i][0] = unpacked_data[i];
+
                      break;
                      
                    case PKE_MASKREG_ROW: /* exploit R0..R3 contiguity */
@@ -2038,6 +2062,11 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
            {
              /* no mask - just copy over entire unpacked quadword */
              memcpy(vu_new_data, unpacked_data, sizeof(unpacked_data));
+
+             /* conditionally store accumulated row results */
+             if(PKE_REG_MASK_GET(me, MODE, MDE) == PKE_MODE_ACCROW)
+               for(i=0; i<4; i++)
+                 me->regs[PKE_REG_R0 + i][0] = unpacked_data[i];
            }
 
          /* write new VU data word at address; reverse words if needed */
This page took 0.035804 seconds and 4 git commands to generate.