aboutsummaryrefslogtreecommitdiff
path: root/sim/mips/mdmx.igen
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>1997-11-26 11:47:36 +0000
committerAndrew Cagney <cagney@redhat.com>1997-11-26 11:47:36 +0000
commit35c246c9d7cb115e4f2aeb8ee5531be2459a1993 (patch)
treed05f9eaad0d4955b60a0317dc277107c3987d636 /sim/mips/mdmx.igen
parent69628a60ea3f52607f25ccc6adb7c7de0176c176 (diff)
downloadgdb-35c246c9d7cb115e4f2aeb8ee5531be2459a1993.zip
gdb-35c246c9d7cb115e4f2aeb8ee5531be2459a1993.tar.gz
gdb-35c246c9d7cb115e4f2aeb8ee5531be2459a1993.tar.bz2
Move MDMX instructions which are public knowledge from vr5400.igen
into mdmx.igen (MDMX is MMX on steroids). Keep the file secret.
Diffstat (limited to 'sim/mips/mdmx.igen')
-rw-r--r--sim/mips/mdmx.igen1299
1 files changed, 1299 insertions, 0 deletions
diff --git a/sim/mips/mdmx.igen b/sim/mips/mdmx.igen
new file mode 100644
index 0000000..2b53c54
--- /dev/null
+++ b/sim/mips/mdmx.igen
@@ -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)));
+}