Move MDMX instructions which are public knowledge from vr5400.igen
authorAndrew Cagney <cagney@redhat.com>
Wed, 26 Nov 1997 11:47:36 +0000 (11:47 +0000)
committerAndrew Cagney <cagney@redhat.com>
Wed, 26 Nov 1997 11:47:36 +0000 (11:47 +0000)
into mdmx.igen (MDMX is MMX on steroids).  Keep the file secret.

sim/mips/.Sanitize
sim/mips/ChangeLog
sim/mips/mdmx.igen [new file with mode: 0644]
sim/mips/vr5400.igen

index 7e0b0bc..5bceb7d 100644 (file)
@@ -24,7 +24,7 @@ else
         lose_these_too="${r5900_files} ${lose_these_too}"
 fi
 
-vr5400_files="vr5400.igen"
+vr5400_files="vr5400.igen mdmx.igen"
 if ( echo $* | grep keep\-vr5400 > /dev/null ) ; then
         keep_these_too="${vr5400_files} ${keep_these_too}"
 else
@@ -148,7 +148,7 @@ else
 fi
 
 
-vr5400_files="ChangeLog configure configure.in sim-main.h interp.c gencode.c mips.igen mips.dc m16.igen vr5400.igen"
+vr5400_files="ChangeLog configure configure.in sim-main.h interp.c gencode.c mips.igen mips.dc m16.igen vr5400.igen mdmx.igen"
 
 if ( echo $* | grep keep\-vr5400 > /dev/null ) ; then
        for i in $vr5400_files ; do
index 59ad047..60f9d52 100644 (file)
@@ -1,3 +1,15 @@
+Wed Nov 26 11:00:23 1997  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * mips.igen (LWC1): Correct assembler - lwc1 not swc1.
+
+start-sanitize-vr5400
+       * sim-main.h: Add 8*3*8 bit accumulator.
+
+       * vr5400.igen: Move mdmx instructins from here
+       * mdmx.igen: To here - new file. Add/fix missing instructions.
+       * mips.igen: Include mdmx.igen.
+
+start-sanitize-vr5400
 Sun Nov 23 01:45:20 1997  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * sim-main.h (sim-fpu.h): Include.
diff --git a/sim/mips/mdmx.igen b/sim/mips/mdmx.igen
new file mode 100644 (file)
index 0000000..2b53c54
--- /dev/null
@@ -0,0 +1,1299 @@
+// Media Instructions
+// ------------------
+
+// Ref: http://www.sgi.com/MIPS/arch/ISA5/MDMXspec.pdf
+
+// Note: For OB instructions, the sel field is deduced by special
+// handling of the "vt" operand.
+//         If vt is:
+//             of the form $vt[0],        then sel is 0000
+//             of the form $vt[1],        then sel is 0001
+//             of the form $vt[2],        then sel is 0010
+//             of the form $vt[3],        then sel is 0011
+//             of the form $vt[4],        then sel is 0100
+//             of the form $vt[5],        then sel is 0101
+//             of the form $vt[6],        then sel is 0110
+//             of the form $vt[7],        then sel is 0111
+//             Normal register specifier, then sel is 1011
+//             Constant,                  then sel is 1111
+//
+// VecAcc is the Vector Accumulator.
+//     This accumulator is organized as 8X24 bit (192 bit) register.
+//     This accumulator holds only signed values.
+
+
+// Verify that the instruction is valid for the curent Architecture
+// If valid, return the scale (log nr bits) of a vector element
+// as determined by SEL.
+
+:function:::int:get_scale:int sel
+{
+#if 0
+  switch (my_index X STATE_ARCHITECTURE)
+    {
+    }
+#endif
+  switch (sel & 0x7)
+    {
+    case 0:
+    case 2:  
+    case 4:
+    case 6:
+      /* octal byte - ssss0 */
+      return 0;
+    case 1:
+    case 5:
+      /* quad halfword - sss01 */
+      return 1;
+    case 3:
+      /* bi word - ss011 */
+      semantic_illegal (sd, cia);
+      return 2;
+    case 7:
+      /* long - ss111 */
+      semantic_illegal (sd, cia);
+      return 3;
+    default:
+      abort ();
+      return -1;
+    }
+}
+
+
+// Fetch/Store VALUE in ELEMENT of vector register FPR.
+// The the of the element determined by SCALE.
+
+:function:::signed:value_vr:int scale, int fpr, int el
+{
+  switch (FPR_STATE[fpr])
+    {
+    case fmt_uninterpreted:
+      FPR_STATE[fpr] = fmt_long;
+      break;
+    case fmt_long:
+    case fmt_unknown:
+      break;
+    default:
+      sim_io_eprintf(sd, "Vector %d format invalid (PC = 0x08lx)\n",
+                    fpr, (long) cia);
+      FPR_STATE[fpr] = fmt_unknown;
+    }
+  switch (scale)
+    {
+    case 0:
+      {
+       signed8 value = *A1_8 (&FGR[fpr], 7 - el);
+       return value;
+      }
+    case 1:
+      {
+       signed16 value = *A2_8 (&FGR[fpr], 3 - el);
+       return value;
+      }
+    default:
+      abort;
+    }
+  return 0;
+}
+
+:function:::signed:store_vr:int scale, int fpr, int element, signed value
+{
+  switch (FPR_STATE[fpr])
+    {
+    case fmt_uninterpreted:
+      FPR_STATE[fpr] = fmt_long;
+      break;
+    case fmt_long:
+    case fmt_unknown:
+      break;
+    default:
+      sim_io_eprintf(sd, "Vector %d format invalid (PC = 0x08lx)\n",
+                    fpr, (long) cia);
+      FPR_STATE[fpr] = fmt_unknown;
+    }
+  switch (scale)
+    {
+    case 0:
+      {
+       *A1_8 (&FGR[fpr], 7 - element) = value;
+       break;
+      }
+    case 1:
+      {
+       *A2_8 (&FGR[fpr], 3 - element) = value;
+       break;
+      }
+    default:
+      abort ();
+    }
+}
+
+
+// Select a value from onr of FGR[VT][ELEMENT], VT and GFR[VT][CONST]
+// according to SEL
+
+:function:::unsigned:select_vr:int sel, int vt, int element
+{
+  switch (sel)
+    {
+      /* element select - 0xxxx */
+    case 0x00: /* 0 xxx 0 */
+    case 0x02:
+    case 0x04:
+    case 0x06:
+    case 0x08:
+    case 0x0a:
+    case 0x0c:
+    case 0x0e:
+      return value_vr (SD_, 0, vt, sel >> 1);
+    case 0x01: /* 0 xx 01 */
+    case 0x05:
+    case 0x09:
+    case 0x0d:
+      return value_vr (SD_, 1, vt, sel >> 2);
+    case 0x03: /* 0 x 011 */
+    case 0x0b:
+      return value_vr (SD_, 2, vt, sel >> 3);
+    case 0x07: /* 0 x 111 */
+    case 0x0f:
+      return value_vr (SD_, 3, vt, sel >> 4);
+
+      /* select vector - 10xxx */
+    case 0x16: /* 10 11 0 */
+      return value_vr (SD_, 0, vt, element);
+    case 0x15: /* 10 1 01 */
+      return value_vr (SD_, 1, vt, element);
+    case 0x13: /* 10  011 */
+      return value_vr (SD_, 2, vt, element);
+    case 0x17: /* 10  111 */
+      return value_vr (SD_, 3, vt, element);
+
+      /* select immediate - 11xxx */
+    case 0x1e: /* 11 11 0 */
+    case 0x1d: /* 11 1 01 */
+    case 0x1b: /* 11  011 */
+    case 0x1f: /* 11  111 */
+      return vt;
+
+    }
+  return 0;
+}
+
+
+// Saturate (clamp) the signed value to (8 << SCALE) bits.
+
+:function:::signed:Clamp:int scale, signed value
+{
+  switch (scale)
+    {
+    case 0:
+      {
+       if (value != (signed8) value)
+         {
+           if (value > 0)
+             return 0x7f;
+           else
+             return 0x80;
+         }
+       return value & 0xff;
+      }
+    case 1:
+      {
+       if (value != (signed16) value)
+         {
+           if (value > 0)
+              return 0x7fff;
+           else
+              return 0x8000;
+         }
+       return value & 0xffff;
+      }
+    default:
+      abort ();
+      return 0;
+    }
+}
+
+
+// Access a single bit of the floating point CC register.
+
+:function:::void:store_cc:int i, int value
+{
+  abort ();
+}
+
+:function:::int:fetch_cc:int i
+{
+  abort ();
+  return 0;
+}
+
+
+//  Read/write the accumulator
+
+:function:::signed64:value_acc:int scale, int element
+{
+  signed64 value = 0;
+  switch (scale)
+    {
+    case 0:
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 0];
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 1] << 8;
+      value |= (signed64) (signed8) CPU->acc [element * 3 + 2] << 16;
+      break;
+    case 1:
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 0];
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 1] << 8;
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 2] << 16;
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 3] << 24;
+      value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 4] << 32;
+      value |= (signed64) (signed8) CPU->acc [element * 3 + 5] << 40;
+      break;
+    }
+  return value;
+}
+
+:function:::void:store_acc:int scale, int element, signed64 value
+{
+  switch (scale)
+    {
+    case 0:
+      CPU->acc [element * 3 + 0] = value >> 0;
+      CPU->acc [element * 3 + 1] = value >> 8;
+      CPU->acc [element * 3 + 2] = value >> 16;
+      break;
+    case 1:
+      CPU->acc [element * 3 + 0] = value >> 0;
+      CPU->acc [element * 3 + 1] = value >> 8;
+      CPU->acc [element * 3 + 2] = value >> 16;
+      CPU->acc [element * 3 + 3] = value >> 24;
+      CPU->acc [element * 3 + 4] = value >> 32;
+      CPU->acc [element * 3 + 5] = value >> 40;
+      break;
+    }
+}
+
+
+// Formatting
+
+:%s::::VT:int sel, int vt
+{
+  static char buf[20];
+  if (sel < 8)
+    sprintf (buf, "v%d[%d]", vt, sel);
+  else if (sel == 0x13)
+    sprintf (buf, "v%d", vt);
+  else if (sel == 0x1f)
+    sprintf (buf, "%d", vt);
+  else
+    sprintf (buf, "(invalid)");
+  return buf;
+}
+
+:%s::::SEL:int sel
+{
+  switch (sel & 7)
+    {
+    case 0:
+    case 2:
+    case 4:
+    case 6:
+      return "ob";
+    case 1:
+    case 5:
+      return "qh";
+    case 3:
+      return "bw";
+    default:
+      return "l";
+    }
+}
+
+
+// Vector Add.
+
+010010,5.SEL,5.VT,5.VS,5.VD,001011::::ADD.fmt
+"add.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             Clamp (SD_, scale,
+                    (value_vr (SD_, scale, VS, i)
+                     + select_vr (SD_, SEL, VT, i))));
+}
+
+
+// Accumulate Vector Add
+
+010010,5.SEL,5.VT,5.VS,1,0000,110111::::ADDA.fmt
+"adda.%s<SEL> v<VD>, v<VS>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              (value_acc (SD_, scale, i)
+               + (signed64) value_vr (SD_, scale, VS, i)
+               + (signed64) select_vr (SD_, SEL, VT, i)));
+}
+
+
+// Load Vector Add
+
+010010,5.SEL,5.VT,5.VS,0,0000,110111::::ADDA.fmt
+"addl.%s<SEL> v<VD>, v<VS>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              ((signed64) value_vr (SD_, scale, VS, i)
+               + (signed64) select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector align, Constant Alignment
+
+:function:::void:ByteAlign:int vd, int imm, int vs, int vt
+{
+  int s = imm * 8;
+  unsigned64 rs = value_fpr (sd, cia, vs, fmt_long);
+  unsigned64 rt = value_fpr (sd, cia, vt, fmt_long);
+  unsigned64 rd;
+  if (BigEndianCPU)
+    {
+      /* (vs || vt) [127 - S .. 64 - S] */
+      if (s == 0)
+       rd = rs;
+      else
+       rd = (MOVED64 (rs, 64 - s, 0, 63, s)
+             | EXTRACTED64 (rt, 63, 64 - s));
+    }
+  else
+    {
+      /* (vs || vt) [63 + S .. S] */
+      if (s == 0)
+       rd = rt;
+      else
+       rd = (MOVED64 (rs, s, 0, 63, 64 - s)
+             | EXTRACTED64 (rt, 63, s));
+    }
+  store_fpr (sd, cia, vd, rd, fmt_long);
+}
+
+010010,00,3.IMM,5.VT,5.VS,5.VD,0110,X,0::::ALNI.fmt
+"alni.%s<FMT#X> v<VD>, v<VS>, v<VT>, <IMM>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  ByteAlign (SD_, VD, IMM, VS, VT);
+}
+
+
+
+// Vector align, Variable Alignment
+
+010010,5.RS,5.VT,5.VS,5.VD,0110,X,1::::ALNV.fmt
+"alnv.%s<FMT#X> v<VD>, v<VS>, v<VT>, r<RS>"
+*mdmx:
+{
+  ByteAlign (SD_, VD, GPR[RS], VS, VT);
+}
+
+
+
+// Vector And.
+
+010010,5.SEL,5.VT,5.VS,5.VD,001100::::AND.fmt
+"and.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (value_vr (SD_, scale, VS, i)
+              & select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Compare Equal.
+
+
+010010,5.SEL,5.VT,5.VS,00000,000001::::C.EQ.fmt
+"c.EQ.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_cc (SD_, i,
+             (value_vr (SD_, scale, VS, i)
+              == select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Compare Less Than or Equal.
+
+010010,5.SEL,5.VT,5.VS,00000,000101::::C.LE.fmt
+"c.le.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_cc (SD_, i,
+             (value_vr (SD_, scale, VS, i)
+              <= select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Compare Less Than.
+
+010010,5.SEL,5.VT,5.VS,00000,000100::::C.LT.fmt
+"c.lt.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_cc (SD_, i,
+             (value_vr (SD_, scale, VS, i)
+              < select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Maximum.
+
+:function:::signed:Max:int scale, signed l, signed r
+{
+  if (l < r)
+    return r;
+  else
+    return l;
+}
+
+010010,5.SEL,5.VT,5.VS,5.VD,000111::::MAX.fmt
+"max.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             Max (SD_, scale,
+                  value_vr (SD_, scale, VS, i),
+                  select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Minimum.
+
+:function:::signed:Min:int scale, signed l, signed r
+{
+  if (l < r)
+    return l;
+  else
+    return r;
+}
+
+010010,5.SEL,5.VT,5.VS,5.VD,000110::::MIN.fmt
+"min.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             Min (SD_, scale,
+                  value_vr (SD_, scale, VS, i),
+                  select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Sign.
+
+:function:::signed:Sign:int scale, signed l, signed r
+{
+  if (l >= 0)
+    return r;
+  else if (r >= 0)
+    return -r;
+  else
+    {
+      /* watch for overflow of MIN_INT */
+      switch (scale)
+       {
+       case 0:
+         if ((r & 0xff) == 0x80)
+           return 0x7ff;
+         else
+           return -r;
+       case 1:
+         if ((r & 0xffff) == 0x8000)
+           return 0x7ffff;
+         else
+           return -r;
+       default:
+         abort ();
+       }
+      return -r;
+    }
+}
+
+010010,5.SEL,5.VT,5.VS,5.VD,000110::::MSGN.fmt
+"msgn.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  if ((SEL & 1) != 1)
+    /* only QH allowed */
+    semantic_illegal (sd, cia);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             Sign (SD_, scale,
+                   value_vr (SD_, scale, VS, i),
+                   select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Multiply.
+
+010010,5.SEL,5.VT,5.VS,5.VD,110000::::MUL.fmt
+"mul.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             Clamp (SD_, scale,
+                    (value_vr (SD_, scale, VS, i)
+                     * select_vr (SD_, SEL, VT, i))));
+}
+
+
+
+// Accumulate Vector Multiply
+
+010010,5.SEL,5.VT,5.VS,00000,110011::::MULA.fmt
+"mula.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              (value_acc (SD_, scale, i)
+               + ((signed64) value_vr (SD_, scale, VS, i)
+                  * (signed64) select_vr (SD_, SEL, VT, i))));
+}
+
+
+
+// Add Vector Multiply to Accumulator.
+
+010010,5.SEL,5.VT,5.VS,10000,110011::::MULL.fmt
+"mull.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              ((signed64) value_vr (SD_, scale, VS, i)
+               * (signed64) select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Subtract Vector Multiply from Accumulator
+
+010010,5.SEL,5.VT,5.VS,00000,110010::::MULS.fmt
+"muls.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              (value_acc (SD_, scale, i)
+               - ((signed64) value_vr (SD_, scale, VS, i)
+                  * (signed64) select_vr (SD_, SEL, VT, i))));
+}
+
+
+
+// Load Negative Vector Multiply
+
+010010,5.SEL,5.VT,5.VS,10000,110010::::MULSL.fmt
+"mulsl.%s<SEL> v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              - ((signed64) value_vr (SD_, scale, VS, i)
+                 * (signed64) select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Nor.
+
+010010,5.SEL,5.VT,5.VS,5.VD,001111::::NOR.fmt
+"nor.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             ~(value_vr (SD_, scale, VS, i)
+               | select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Or.
+
+010010,5.SEL,5.VT,5.VS,5.VD,001110::::OR.fmt
+"or.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (value_vr (SD_, scale, VS, i)
+              | select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Select Vector Elements - False
+
+010010,5.SEL,5.VT,5.VS,5.VD,000010::::PICKF.fmt
+"pickf.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (fetch_cc (SD_, i) == 0
+              ? value_vr (SD_, scale, VS, i)
+              : select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Select Vector Elements - True
+
+010010,5.SEL,5.VT,5.VS,5.VD,000011::::PICKT.fmt
+"pickt.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (fetch_cc (SD_, i) != 0
+              ? value_vr (SD_, scale, VS, i)
+              : select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Scale, Round and Clamp Accumulator
+
+:%s::::RND:int rnd
+{
+  switch (rnd)
+    {
+    case 0:
+      return "zu";
+    case 1:
+      return "nau";
+    case 2:
+      return "neu";
+    case 4:
+      return "rzs";
+    case 5:
+      return "nas";
+    case 6:
+      return "nes";
+    default:
+      return "(invalid)";
+    }
+}
+
+:function:::signed:ScaleRoundClamp:int scale, int rnd, signed val, signed shift
+{
+  int halfway = (1 << (shift - 1));
+  /* must be positive */
+  if (shift < 0)
+    return 0;
+  /* too much shift? */
+  switch (scale)
+    {
+    case 0:
+      if (shift >= 24)
+       return 0;
+      break;
+    case 1:
+      if (shift >= 48)
+       return 0;
+      break;
+    default:
+      abort ();
+    }
+  /* round */
+  switch (rnd & 3)
+    {
+    case 0: /* round towards zero */
+      break;
+    case 1: /* nearest, halfaway rounds away from zero */
+      if (val >= 0)
+       val += halfway;
+      else
+       val -= halfway;
+      break;
+    case 2: /* nearest, halfway rounds to even! */
+      if (val >= 0)
+       {
+         if (val & (halfway << 1))
+           val += halfway;
+         else
+           val += (halfway - 1);
+       }
+      else
+       {
+         if (val & (halfway << 1))
+           val -= halfway;
+         else
+           val -= (halfway - 1);
+       }
+    default:
+      abort ();
+    }
+  /* shift */
+  val >>= shift;
+  /* clamp */
+  switch (rnd & 4)
+    {
+    case 0:
+      /* unsigned clamp */
+      if (val < 0)
+       val = 0;
+      else
+       switch (scale)
+         {
+         case 0:
+           if (val > 0xff)
+             val = 0xff;
+           break;
+         case 1:
+           if (val > 0xffff)
+             val = 0xffff;
+           break;
+         }
+      break;
+    case 8:
+      /* normal signed clamp */
+      val = Clamp (_SD, scale, val);
+      break;
+    }
+  return val;
+}
+
+010010,5.SEL,5.VT,00000,5.VD,100,3.RND::::Rx.fmt
+"r%s<RND>.%s<SEL> v<VD>, v<VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             ScaleRoundClamp (SD_, scale, RND,
+                              value_acc (SD_, scale, i),
+                              select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Vector Read  Accumulator Low.
+
+010010,0000,1.SEL,00000,00000,5.VD,111111::::RACL.fmt
+"racl.%s<SEL> v<VD>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             EXTRACTED (value_acc (SD_, scale, i),
+                        (8 << scale) - 1,
+                        0));
+}
+
+
+
+// Vector Read  Accumulator Middle.
+
+010010,0100,1.SEL,00000,00000,5.VD,111111::::RACM.fmt
+"racm.%s<SEL> v<VD>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             EXTRACTED (value_acc (SD_, scale, i),
+                        (16 << scale) - 1,
+                        (8 << scale) - 0));
+}
+
+
+
+// Vector Read  Accumulator High.
+
+010010,1000,1.SEL,00000,00000,5.VD,111111::::RACH.fmt
+"rach.%s<SEL> v<VD>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             EXTRACTED (value_acc (SD_, scale, i),
+                        (24 << scale) - 1,
+                        (16 << scale) - 0));
+}
+
+
+
+// Vector Element Shuffle.
+
+010010,0000,0,5.VT,5.VS,5.VD,011111::::SHFL.UPUH.fmt
+"shfl.upuh.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < 4; i++)
+    {
+      store_vr (SD_, 1, VD, i,
+               value_vr (SD_, 0, VS, i + 4) & 0xff);
+    }
+}
+
+010010,0001,0,5.VT,5.VS,5.VD,011111::::SHFL.UPUL.fmt
+"shfl.upul.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  int i;
+  for (i = 0; i < 4; i++)
+    {
+      store_vr (SD_, 1, VD, i,
+               value_vr (SD_, 0, VS, i) & 0xff);
+    }
+}
+
+010010,0000,0,5.VT,5.VS,5.VD,011111::::SHFL.UPSH.fmt
+"shfl.upsh.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < 4; i++)
+    {
+      store_vr (SD_, 1, VD, i,
+               value_vr (SD_, 0, VS, i + 4));
+    }
+}
+
+010010,0001,0,5.VT,5.VS,5.VD,011111::::SHFL.UPSL.fmt
+"shfl.upsl.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  int i;
+  for (i = 0; i < 4; i++)
+    {
+      store_vr (SD_, 1, VD, i,
+               value_vr (SD_, 0, VS, i));
+    }
+}
+
+010010,0100,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.PACH.fmt
+"shfl.pach.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (4 >> scale); i++)
+    {
+      store_vr (SD_, scale, VD, i,
+               value_vr (SD_, scale, VT, i * 2 + 1));
+      store_vr (SD_, scale, VD, 1 + (4 >> scale),
+               value_vr (SD_, scale, VS, i * 2 + 1));
+    }
+}
+
+010010,0101,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.PACL.fmt
+"shfl.pacl.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (4 >> scale); i++)
+    {
+      store_vr (SD_, scale, VD, i,
+               value_vr (SD_, scale, VT, i * 2));
+      store_vr (SD_, scale, VD, 1 + (4 >> scale),
+               value_vr (SD_, scale, VS, i * 2));
+    }
+}
+
+010010,0110,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.MIXH.fmt
+"shfl.mixh.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (4 >> scale); i++)
+    {
+      store_vr (SD_, scale, VD, i * 2,
+               value_vr (SD_, scale, VT, i + (4 >> scale)));
+      store_vr (SD_, scale, VD, i * 2 + 1,
+               value_vr (SD_, scale, VS, i + (4 >> scale)));
+    }
+}
+
+010010,0111,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.MIXL.fmt
+"shfl.mixl.%s<SEL> v<VD>, v<VS>, <VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (4 >> scale); i++)
+    {
+      store_vr (SD_, scale, VD, i * 2,
+               value_vr (SD_, scale, VT, i));
+      store_vr (SD_, scale, VD, i * 2 + 1,
+               value_vr (SD_, scale, VS, i));
+    }
+}
+
+010010,100,01,5.VT,5.VS,5.VD,011111::::SHFL.BFLA.fmt
+"shfl.bfla.qh v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  store_vr (SD_, 1, VD, 0,
+           value_vr (SD_, 1, VT, 1));
+  store_vr (SD_, 1, VD, 1,
+           value_vr (SD_, 1, VS, 0));
+  store_vr (SD_, 1, VD, 2,
+           value_vr (SD_, 1, VT, 3));
+  store_vr (SD_, 1, VD, 3,
+           value_vr (SD_, 1, VS, 2));
+}
+
+010010,101,01,5.VT,5.VS,5.VD,011111::::SHFL.BFLB.fmt
+"shfl.bflb.qh v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  store_vr (SD_, 1, VD, 0,
+           value_vr (SD_, 1, VT, 3));
+  store_vr (SD_, 1, VD, 1,
+           value_vr (SD_, 1, VS, 2));
+  store_vr (SD_, 1, VD, 2,
+           value_vr (SD_, 1, VT, 1));
+  store_vr (SD_, 1, VD, 3,
+           value_vr (SD_, 1, VS, 0));
+}
+
+010010,101,01,5.VT,5.VS,5.VD,011111::::SHFL.REPA.fmt
+"shfl.repa.qh v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  store_vr (SD_, 1, VD, 0,
+           value_vr (SD_, 1, VT, 2));
+  store_vr (SD_, 1, VD, 1,
+           value_vr (SD_, 1, VT, 3));
+  store_vr (SD_, 1, VD, 2,
+           value_vr (SD_, 1, VS, 2));
+  store_vr (SD_, 1, VD, 3,
+           value_vr (SD_, 1, VS, 3));
+}
+
+010010,101,01,5.VT,5.VS,5.VD,011111::::SHFL.REPB.fmt
+"shfl.repb.qh v<VD>, v<VS>, <VT>"
+*mdmx:
+{
+  store_vr (SD_, 1, VD, 0,
+           value_vr (SD_, 1, VT, 0));
+  store_vr (SD_, 1, VD, 1,
+           value_vr (SD_, 1, VT, 1));
+  store_vr (SD_, 1, VD, 2,
+           value_vr (SD_, 1, VS, 0));
+  store_vr (SD_, 1, VD, 3,
+           value_vr (SD_, 1, VS, 1));
+}
+
+
+
+// Vector Shift Left Logical
+
+010010,5.SEL,5.VT,5.VS,5.VD,010000::::SLL.fmt
+"sll.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  int mask = (4 << scale) - 1;
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (value_vr (SD_, scale, VS, i)
+              << (select_vr (SD_, SEL, VT, i) & mask)));
+}
+
+
+
+// Vector Shift Right Arithmetic
+
+010010,5.SEL,5.VT,5.VS,5.VD,010011::::SRA.fmt
+"sra.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+{
+  int i;
+  int mask = (4 << scale) - 1;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (value_vr (SD_, scale, VS, i)
+              >> (select_vr (SD_, SEL, VT, i) & mask)));
+}
+
+
+
+// Vector Shift Right Logical.
+
+010010,5.SEL,5.VT,5.VS,5.VD,010010::::SRL.fmt
+"srl.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  int mask = (4 << scale) - 1;
+  int zeros = (1 << (8 << scale)) - 1;
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             ((value_vr (SD_, scale, VS, i) & zeros)
+              >> (select_vr (SD_, SEL, VT, i) & mask)));
+}
+
+
+
+// Vector Subtract.
+
+010010,5.SEL,5.VT,5.VS,5.VD,001010::::SUB.fmt
+"sub.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (value_vr (SD_, scale, VS, i)
+              - select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Accumulate Vector Difference
+
+010010,5.SEL,5.VT,5.VS,0,0000,110110::::SUBA.fmt
+"suba.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, VD, i,
+              (value_acc (SD, scale, i)
+               + (signed64) value_vr (SD_, scale, VS, i)
+               - (signed64) select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Load Vector Difference
+
+010010,5.SEL,5.VT,5.VS,1,0000,110110::::SUBL.fmt
+"subl.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, VD, i,
+              ((signed64) value_vr (SD_, scale, VS, i)
+               - (signed64) select_vr (SD_, SEL, VT, i)));
+}
+
+
+
+// Write Accumulator High.
+
+010010,1000,1.SEL,00000,5.VS,00000,111110::::WACH.fmt
+"wach.%s<SEL> v<VS>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              (((signed64) value_vr (SD_, scale, VS, i) << (16 << scale))
+               | MASKED (value_acc (SD_, scale, i), (16 << scale) - 1, 0)));
+}
+
+
+
+// Vector Write Accumulator Low.
+
+010010,0000,1.SEL,5.VT,5.VS,00000,111110::::WACL.fmt
+"wacl.%s<SEL> v<VS>, <VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_acc (SD_, scale, i,
+              (((signed64) value_vr (SD_, scale, VS, i) << (16 << scale))
+               | MASKED (value_vr (SD_, scale, VT, i),
+                         (16 << scale) - 1, 0)));
+}
+
+
+
+// Vector Xor.
+
+010010,5.SEL,5.VT,5.VS,5.VD,001101::::XOR.fmt
+"xor.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
+*mdmx:
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+{
+  int i;
+  int scale = get_scale (SD_, SEL);
+  for (i = 0; i < (8 >> scale); i++)
+    store_vr (SD_, scale, VD, i,
+             (value_vr (SD_, scale, VS, i)
+              ^ select_vr (SD_, SEL, VT, i)));
+}
index 3fcd3e0..ade64ad 100644 (file)
   int s = MASKED (GPR[RS], 5, 0);
   GPR[RD] = ROTR64 (GPR[RT], s);
 }
-
-
-
-
-// Media Instructions
-// ------------------
-
-// Note:   Vector unit in R5400 supports only octal byte format. 
-// Note:   The sel field is deduced by special handling of the "vt"
-// operand.
-//         If vt is:
-//             of the form $vt[0],        then sel is 0000
-//             of the form $vt[1],        then sel is 0001
-//             of the form $vt[2],        then sel is 0010
-//             of the form $vt[3],        then sel is 0011
-//             of the form $vt[4],        then sel is 0100
-//             of the form $vt[5],        then sel is 0101
-//             of the form $vt[6],        then sel is 0110
-//             of the form $vt[7],        then sel is 0111
-//             Normal register specifier, then sel is 1011
-//             Constant,                  then sel is 1111
-//
-// VecAcc is the Vector Accumulator.
-//     This accumulator is organized as 8X24 bit (192 bit) register.
-//     This accumulator holds only signed values.
-
-:function:::signed:vr:int fpr, int byte
-{
-  signed8 b = V1_8 (value_fpr (sd, cia, fpr, fmt_long), byte);
-  return b;
-}
-
-:function:::void:set_vr:int fpr, int byte, signed value
-{
-  abort ();
-}
-
-:function:::signed:VecAcc:int byte
-{
-  abort ();
-  return 0;
-}
-
-:function:::void:set_VecAcc:int byte, signed value
-{
-  abort ();
-}
-
-:function:::int:cc:int i
-{
-  abort ();
-  return 0;
-}
-
-:function:::void:set_cc:int i, int value
-{
-  abort ();
-}
-
-:function:::signed:Min:signed l, signed r
-{
-  if (l < r)
-    return l;
-  else
-    return r;
-}
-
-:function:::signed:Max:signed l, signed r
-{
-  if (l < r)
-    return r;
-  else
-    return l;
-}
-
-:function:::signed:Compare:signed l, signed r
-{
-  abort ();
-  return 0;
-}
-
-:function:::signed:Clamp:signed l
-{
-  abort ();
-  return 0;
-}
-
-:function:::signed:Round:signed l
-{
-  abort ();
-  return 0;
-}
-
-:function:::void:ByteAlign:int vd, int imm, int vs, int vt
-{
-  abort ();
-}
-
-:function:::signed:One_of:int vs, int vt
-{
-  abort ();
-  return 0;
-}
-
-:function:::unsigned:do_select:int i, int sel, int vt
-{
-  if (sel < 8)
-    return vr (SD_, vt, sel);
-  else if (sel == 0x13)
-    return vr (SD_, vt, i);
-  else if (sel == 0x1f)
-    return vt;
-  else
-    semantic_illegal (sd, cia);
-  return 0;
-}
-
-:%s::::VT:int sel, int vt
-{
-  static char buf[20];
-  if (sel < 8)
-    sprintf (buf, "v%d[%d]", vt, sel);
-  else if (sel == 0x13)
-    sprintf (buf, "v%d", vt);
-  else if (sel == 0x1f)
-    sprintf (buf, "%d", vt);
-  else
-    sprintf (buf, "(invalid)");
-  return buf;
-}
-
-
-// Vector Add.
-010010,4.SEL,0,5.VT,5.VS,5.VD,001011::::ADD.OB
-"add.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) + do_select (SD_, i, SEL, VT));
-}
-
-// Vector Align.
-010010,00,3.IMM,5.VT,5.VS,5.VD,011000::::ALNI.OB
-"alni.ob v<VD>, v<VS>, v<VT>, <IMM>"
-*vr5400:
-{
-  ByteAlign (SD_, VD, IMM, VS, VT);
-}
-
-// Vector And.
-010010,4.SEL,0,5.VT,5.VS,5.VD,001100::::AND.OB
-"and.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) & do_select (SD_, i, SEL, VT));
-}
-
-// Vector Compare Equal.
-010010,4.SEL,0,5.VT,5.VS,00000,000001::::C.EQ.OB
-"c.eq.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_cc (SD_, i, Compare (SD_, vr (SD_, VS, i), do_select (SD_, i, SEL, VT)));
-}
-
-// Vector Compare Less Than or Equal.
-010010,4.SEL,0,5.VT,5.VS,00000,000101::::C.LE.OB
-"c.le.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_cc (SD_, i, Compare (SD_, vr (SD_, VS, i), do_select (SD_, i, SEL, VT)));
-}
-
-// Vector Compare Less Than.
-010010,4.SEL,0,5.VT,5.VS,00000,000100::::C.LT.OB
-"c.lt.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_cc (SD_, i, Compare (SD_, vr (SD_, VS, i), do_select (SD_, i, SEL, VT)));
-}
-
-// Vector Maximum.
-010010,4.SEL,0,5.VT,5.VS,5.VD,000111::::MAX.OB
-"max.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, Max (SD_, vr (SD_, VS, i), do_select (SD_, i, SEL, VT)));
-}
-
-// Vector Minimum.
-010010,4.SEL,0,5.VT,5.VS,5.VD,000110::::MIN.OB
-"min.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, Min (SD_, vr (SD_, VS, i), do_select (SD_, i, SEL, VT)));
-}
-
-// Vector Multiply.
-010010,4.SEL,0,5.VT,5.VS,5.VD,110000::::MUL.OB
-"mul.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) * do_select (SD_, i, SEL, VT));
-}
-
-// Vector Multiply, Accumulate.
-010010,4.SEL,0,5.VT,5.VS,00000,110011::::MULA.OB
-"mula.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_VecAcc (SD_, i, VecAcc (SD_, i) + vr (SD_, VS, i) * do_select (SD_, i, SEL, VT));
-}
-
-// Vector Multiply, Load Accumulator.
-010010,4.SEL,0,5.VT,5.VS,10000,110011::::MULL.OB
-"mull.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_VecAcc (SD_, i, 0 + vr (SD_, VS, i) * do_select (SD_, i, SEL, VT));
-}
-
-// Vector Multiply, Negate, Accumulate.
-010010,4.SEL,0,5.VT,5.VS,00000,110010::::MULS.OB
-"muls.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_VecAcc (SD_, i, VecAcc (SD_, i) - vr (SD_, VS, i) * do_select (SD_, i, SEL, VT));
-}
-
-// Vector Multiply, Negate, Load Accumulator.
-010010,4.SEL,0,5.VT,5.VS,10000,110010::::MULSL.OB
-"mulsl.ob v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_VecAcc (SD_, i, 0 - vr (SD_, VS, i) * do_select (SD_, i, SEL, VT));
-}
-
-// Vector NOr.
-010010,4.SEL,0,5.VT,5.VS,5.VD,001111::::NOR.OB
-"nor.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, ! (vr (SD_, VS, i) | do_select (SD_, i, SEL, VT)));
-}
-
-// Vector Or.
-010010,4.SEL,0,5.VT,5.VS,5.VD,001110::::OR.OB
-"or.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) | do_select (SD_, i, SEL, VT));
-}
-
-// Vector Pick False.
-010010,4.SEL,0,5.VT,5.VS,5.VD,000010::::PICKF.OB
-"pickf.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, cc (SD_, i) ? do_select (SD_, i, SEL, VT) : vr (SD_, VS, i));
-}
-
-// Vector Pick True.
-010010,4.SEL,0,5.VT,5.VS,5.VD,000011::::PICKT.OB
-"pickt.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, cc (SD_, i) ? vr (SD_, VS, i) : do_select (SD_, i, SEL, VT));
-}
-
-// Vector Read  Accumulator High.
-010010,1000,0,00000,00000,5.VD,111111::::RACH.OB
-"rach.ob v<VD>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, EXTRACTED (VecAcc (SD_, i), 23, 16));
-}
-
-// Vector Read  Accumulator Low.
-010010,0000,0,00000,00000,5.VD,111111::::RACL.OB
-"racl.ob v<VD>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, EXTRACTED (VecAcc (SD_, i), 7, 0));
-}
-
-// Vector Read  Accumulator Middle.
-010010,0100,0,00000,00000,5.VD,111111::::RACM.OB
-"racm.ob v<VD>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, EXTRACTED (VecAcc (SD_, i), 15, 8));
-}
-
-// Vector Scale, Round and Clamp Accumulator.
-010010,4.SEL,0,5.VT,00000,5.VD,100000::::RZU.OB
-"rzu.ob v<VD>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, Clamp (SD_, Round (SD_, VecAcc (SD_, i) >> do_select (SD_, i, SEL, VT))));
-}
-
-// Vector Element Shuffle.
-010010,0110,0,5.VT,5.VS,5.VD,011111::::SHFL.MIXH.OB
-"shfl.mixh.ob v<VD>, v<VS>, <VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, One_of (SD_, VS, VT));
-}
-
-// Vector Element Shuffle.
-010010,0111,0,5.VT,5.VS,5.VD,011111::::SHFL.MIXL.OB
-"shfl.mixl.ob v<VD>, v<VS>, <VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, One_of (SD_, VS, VT));
-}
-
-// Vector Element Shuffle.
-010010,0100,0,5.VT,5.VS,5.VD,011111::::SHFL.PACH.OB
-"shfl.pach.ob v<VD>, v<VS>, <VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, One_of (SD_, VS, VT));
-}
-
-// Vector Element Shuffle.
-010010,0101,0,5.VT,5.VS,5.VD,011111::::SHFL.PACL.OB
-"shfl.pacl.ob v<VD>, v<VS>, <VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, One_of (SD_, VS, VT));
-}
-
-// Vector Shift Left  Logical.
-010010,4.SEL,0,5.VT,5.VS,5.VD,010000::::SLL.OB
-"sll.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) << do_select (SD_, i, SEL, VT));
-}
-
-// Vector Shift Right Logical.
-010010,4.SEL,0,5.VT,5.VS,5.VD,010010::::SRL.OB
-"srl.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) >> do_select (SD_, i, SEL, VT));
-}
-
-// Vector Subtract.
-010010,4.SEL,0,5.VT,5.VS,5.VD,001010::::SUB.OB
-"sub.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) - do_select (SD_, i, SEL, VT));
-}
-
-// Vector Write Accumulator High.
-010010,1000,0,00000,5.VS,00000,111110::::WACH.OB
-"wach.ob v<VS>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    /* High8 */ set_VecAcc (SD_, i, (vr (SD_, VS, i) << 16) | MASKED (VecAcc (SD_, i), 15, 0));
-}
-
-// Vector Write Accumulator Low.
-010010,0000,0,5.VT,5.VS,00000,111110::::WACL.OB
-"wacl.ob v<VS>, <VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_VecAcc (SD_, i, (EXTEND8 (vr (SD_, VS, i)) << 8) | vr (SD_, VT, i));
-}
-
-// Vector XOr.
-010010,4.SEL,0,5.VT,5.VS,5.VD,001101::::XOR.OB
-"xor.ob v<VD>, v<VS>, %s<VT#SEL,VT>"
-*vr5400:
-{
-  int i;
-  for (i = 0; i < 8; i++)
-    set_vr (SD_, VD, i, vr (SD_, VS, i) ^ do_select (SD_, i, SEL, VT));
-}