* gx sim prototype tweaks
[binutils-gdb.git] / sim / mips / mdmx.igen
blob5222863c0f93e5b082a0376931829eb827a3014c
1 //  -*- C -*-
2 // Media Instructions
3 // ------------------
5 // Ref: http://www.sgi.com/MIPS/arch/ISA5/MDMXspec.pdf
7 // Note: For OB instructions, the sel field is deduced by special
8 // handling of the "vt" operand.
9 //         If vt is:
10 //             of the form $vt[0],        then sel is 0000
11 //             of the form $vt[1],        then sel is 0001
12 //             of the form $vt[2],        then sel is 0010
13 //             of the form $vt[3],        then sel is 0011
14 //             of the form $vt[4],        then sel is 0100
15 //             of the form $vt[5],        then sel is 0101
16 //             of the form $vt[6],        then sel is 0110
17 //             of the form $vt[7],        then sel is 0111
18 //             Normal register specifier, then sel is 1011
19 //             Constant,                  then sel is 1111
21 // VecAcc is the Vector Accumulator.
22 //     This accumulator is organized as 8X24 bit (192 bit) register.
23 //     This accumulator holds only signed values.
26 // Verify that the instruction is valid for the curent Architecture
27 // If valid, return the scale (log nr bits) of a vector element
28 // as determined by SEL.
30 :function:64,f::int:get_scale:int sel
31 *mdmx:
32 // start-sanitize-vr5400
33 *vr5400:
34 // end-sanitize-vr5400
36 #if 0
37   switch (my_index X STATE_ARCHITECTURE)
38     {
39     }
40 #endif
41   switch (sel & 0x7)
42     {
43     case 0:
44     case 2:  
45     case 4:
46     case 6:
47       /* octal byte - ssss0 */
48       return 0;
49     case 1:
50     case 5:
51       /* quad halfword - sss01 */
52       return 1;
53     case 3:
54       /* bi word - ss011 */
55       semantic_illegal (CPU_, cia);
56       return 2;
57     case 7:
58       /* long - ss111 */
59       semantic_illegal (CPU_, cia);
60       return 3;
61     default:
62       abort ();
63       return -1;
64     }
68 // Fetch/Store VALUE in ELEMENT of vector register FPR.
69 // The the of the element determined by SCALE.
71 :function:64,f::signed:value_vr:int scale, int fpr, int el
72 *mdmx:
73 // start-sanitize-vr5400
74 *vr5400:
75 // end-sanitize-vr5400
77   switch (FPR_STATE[fpr])
78     {
79     case fmt_uninterpreted:
80       FPR_STATE[fpr] = fmt_long;
81       break;
82     case fmt_long:
83     case fmt_unknown:
84       break;
85     default:
86       sim_io_eprintf (SD, "Vector %d format invalid (PC = 0x%08lx)\n",
87                       fpr, (long) CIA);
88       FPR_STATE[fpr] = fmt_unknown;
89     }
90   switch (scale)
91     {
92     case 0:
93       {
94         signed8 value = *A1_8 (&FGR[fpr], 7 - el);
95         return value;
96       }
97     case 1:
98       {
99         signed16 value = *A2_8 (&FGR[fpr], 3 - el);
100         return value;
101       }
102     default:
103       abort;
104     }
105   return 0;
108 :function:64,f::void:store_vr:int scale, int fpr, int element, signed value
109 *mdmx:
110 // start-sanitize-vr5400
111 *vr5400:
112 // end-sanitize-vr5400
114   switch (FPR_STATE[fpr])
115     {
116     case fmt_uninterpreted:
117       FPR_STATE[fpr] = fmt_long;
118       break;
119     case fmt_long:
120     case fmt_unknown:
121       break;
122     default:
123       sim_io_eprintf (SD, "Vector %d format invalid (PC = 0x%08lx)\n",
124                       fpr, (long) cia);
125       FPR_STATE[fpr] = fmt_unknown;
126     }
127   switch (scale)
128     {
129     case 0:
130       {
131         *A1_8 (&FGR[fpr], 7 - element) = value;
132         break;
133       }
134     case 1:
135       {
136         *A2_8 (&FGR[fpr], 3 - element) = value;
137         break;
138       }
139     default:
140       abort ();
141     }
145 // Select a value from onr of FGR[VT][ELEMENT], VT and GFR[VT][CONST]
146 // according to SEL
148 :function:64,f::unsigned:select_vr:int sel, int vt, int element
149 *mdmx:
150 // start-sanitize-vr5400
151 *vr5400:
152 // end-sanitize-vr5400
154   switch (sel)
155     {
156       /* element select - 0xxxx */
157     case 0x00: /* 0 xxx 0 */
158     case 0x02:
159     case 0x04:
160     case 0x06:
161     case 0x08:
162     case 0x0a:
163     case 0x0c:
164     case 0x0e:
165       return value_vr (SD_, 0, vt, sel >> 1);
166     case 0x01: /* 0 xx 01 */
167     case 0x05:
168     case 0x09:
169     case 0x0d:
170       return value_vr (SD_, 1, vt, sel >> 2);
171     case 0x03: /* 0 x 011 */
172     case 0x0b:
173       return value_vr (SD_, 2, vt, sel >> 3);
174     case 0x07: /* 0 x 111 */
175     case 0x0f:
176       return value_vr (SD_, 3, vt, sel >> 4);
178       /* select vector - 10xxx */
179     case 0x16: /* 10 11 0 */
180       return value_vr (SD_, 0, vt, element);
181     case 0x15: /* 10 1 01 */
182       return value_vr (SD_, 1, vt, element);
183     case 0x13: /* 10  011 */
184       return value_vr (SD_, 2, vt, element);
185     case 0x17: /* 10  111 */
186       return value_vr (SD_, 3, vt, element);
188       /* select immediate - 11xxx */
189     case 0x1e: /* 11 11 0 */
190     case 0x1d: /* 11 1 01 */
191     case 0x1b: /* 11  011 */
192     case 0x1f: /* 11  111 */
193       return vt;
195     }
196   return 0;
200 // Saturate (clamp) the signed value to (8 << SCALE) bits.
202 :function:64,f::signed:Clamp:int scale, signed value
203 *mdmx:
204 // start-sanitize-vr5400
205 *vr5400:
206 // end-sanitize-vr5400
208   switch (scale)
209     {
210     case 0:
211       {
212         if (value != (signed8) value)
213           {
214             if (value > 0)
215               return 0x7f;
216             else
217               return 0x80;
218           }
219         return value & 0xff;
220       }
221     case 1:
222       {
223         if (value != (signed16) value)
224           {
225             if (value > 0)
226                return 0x7fff;
227             else
228                return 0x8000;
229           }
230         return value & 0xffff;
231       }
232     default:
233       abort ();
234       return 0;
235     }
239 // Access a single bit of the floating point CC register.
241 :function:64,f::void:store_cc:int i, int value
242 *mdmx:
243 // start-sanitize-vr5400
244 *vr5400:
245 // end-sanitize-vr5400
247   SETFCC (i, value);
250 :function:64,f::int:value_cc:int i
251 *mdmx:
252 // start-sanitize-vr5400
253 *vr5400:
254 // end-sanitize-vr5400
256   return GETFCC (i);
260 //  Read/write the accumulator
262 :function:64,f::signed64:value_acc:int scale, int element
263 *mdmx:
264 // start-sanitize-vr5400
265 *vr5400:
266 // end-sanitize-vr5400
268   signed64 value = 0;
269   switch (scale)
270     {
271     case 0:
272       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 0];
273       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 1] << 8;
274       value |= (signed64) (signed8) CPU->acc [element * 3 + 2] << 16;
275       break;
276     case 1:
277       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 0];
278       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 1] << 8;
279       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 2] << 16;
280       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 3] << 24;
281       value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 4] << 32;
282       value |= (signed64) (signed8) CPU->acc [element * 3 + 5] << 40;
283       break;
284     }
285   return value;
288 :function:64,f::void:store_acc:int scale, int element, signed64 value
289 *mdmx:
290 // start-sanitize-vr5400
291 *vr5400:
292 // end-sanitize-vr5400
294   switch (scale)
295     {
296     case 0:
297       CPU->acc [element * 3 + 0] = value >> 0;
298       CPU->acc [element * 3 + 1] = value >> 8;
299       CPU->acc [element * 3 + 2] = value >> 16;
300       break;
301     case 1:
302       CPU->acc [element * 3 + 0] = value >> 0;
303       CPU->acc [element * 3 + 1] = value >> 8;
304       CPU->acc [element * 3 + 2] = value >> 16;
305       CPU->acc [element * 3 + 3] = value >> 24;
306       CPU->acc [element * 3 + 4] = value >> 32;
307       CPU->acc [element * 3 + 5] = value >> 40;
308       break;
309     }
313 // Formatting
315 :%s:64,f:::VT:int sel, int vt
316 *mdmx:
317 // start-sanitize-vr5400
318 *vr5400:
319 // end-sanitize-vr5400
321   static char buf[20];
322   if (sel < 8)
323     sprintf (buf, "v%d[%d]", vt, sel);
324   else if (sel == 0x13)
325     sprintf (buf, "v%d", vt);
326   else if (sel == 0x1f)
327     sprintf (buf, "%d", vt);
328   else
329     sprintf (buf, "(invalid)");
330   return buf;
333 :%s:64,f:::SEL:int sel
334 *mdmx:
335 // start-sanitize-vr5400
336 *vr5400:
337 // end-sanitize-vr5400
339   switch (sel & 7)
340     {
341     case 0:
342     case 2:
343     case 4:
344     case 6:
345       return "ob";
346     case 1:
347     case 5:
348       return "qh";
349     case 3:
350       return "bw";
351     default:
352       return "l";
353     }
357 // Vector Add.
359 010010,5.SEL,5.VT,5.VS,5.VD,001011::64,f::ADD.fmt
360 "add.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
361 *mdmx:
362 // start-sanitize-vr5400
363 *vr5400:
364 // end-sanitize-vr5400
366   int i;
367   int scale = get_scale (SD_, SEL);
368   for (i = 0; i < (8 >> scale); i++)
369     store_vr (SD_, scale, VD, i,
370               Clamp (SD_, scale,
371                      (value_vr (SD_, scale, VS, i)
372                       + select_vr (SD_, SEL, VT, i))));
376 // Accumulate Vector Add
378 010010,5.SEL,5.VT,5.VS,1,0000,110111::64,f::ADDA.fmt
379 "adda.%s<SEL> v<VD>, v<VS>"
380 *mdmx:
382   int i;
383   int scale = get_scale (SD_, SEL);
384   for (i = 0; i < (8 >> scale); i++)
385     store_acc (SD_, scale, i,
386                (value_acc (SD_, scale, i)
387                 + (signed64) value_vr (SD_, scale, VS, i)
388                 + (signed64) select_vr (SD_, SEL, VT, i)));
392 // Load Vector Add
394 010010,5.SEL,5.VT,5.VS,0,0000,110111::64,f::ADDA.fmt
395 "addl.%s<SEL> v<VD>, v<VS>"
396 *mdmx:
398   int i;
399   int scale = get_scale (SD_, SEL);
400   for (i = 0; i < (8 >> scale); i++)
401     store_acc (SD_, scale, i,
402                ((signed64) value_vr (SD_, scale, VS, i)
403                 + (signed64) select_vr (SD_, SEL, VT, i)));
408 // Vector align, Constant Alignment
410 :function:64,f::void:ByteAlign:int vd, int imm, int vs, int vt
411 *mdmx:
412 // start-sanitize-vr5400
413 *vr5400:
414 // end-sanitize-vr5400
416   int s = imm * 8;
417   unsigned64 rs = ValueFPR (vs, fmt_long);
418   unsigned64 rt = ValueFPR (vt, fmt_long);
419   unsigned64 rd;
420   if (BigEndianCPU)
421     {
422       /* (vs || vt) [127 - S .. 64 - S] */
423       if (s == 0)
424         rd = rs;
425       else
426         rd = (MOVED64 (rs, 64 - s, 0, 63, s)
427               | EXTRACTED64 (rt, 63, 64 - s));
428     }
429   else
430     {
431       /* (vs || vt) [63 + S .. S] */
432       if (s == 0)
433         rd = rt;
434       else
435         rd = (MOVED64 (rs, s, 0, 63, 64 - s)
436               | EXTRACTED64 (rt, 63, s));
437     }
438   StoreFPR (vd, fmt_long, rd);
441 010010,00,3.IMM,5.VT,5.VS,5.VD,0110,X,0::64,f::ALNI.fmt
442 "alni.%s<FMT#X> v<VD>, v<VS>, v<VT>, <IMM>"
443 *mdmx:
444 // start-sanitize-vr5400
445 *vr5400:
446 // end-sanitize-vr5400
448   ByteAlign (SD_, VD, IMM, VS, VT);
453 // Vector align, Variable Alignment
455 010010,5.RS,5.VT,5.VS,5.VD,0110,X,1::64,f::ALNV.fmt
456 "alnv.%s<FMT#X> v<VD>, v<VS>, v<VT>, r<RS>"
457 *mdmx:
459   ByteAlign (SD_, VD, GPR[RS], VS, VT);
464 // Vector And.
466 010010,5.SEL,5.VT,5.VS,5.VD,001100::64,f::AND.fmt
467 "and.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
468 *mdmx:
469 // start-sanitize-vr5400
470 *vr5400:
471 // end-sanitize-vr5400
473   int i;
474   int scale = get_scale (SD_, SEL);
475   for (i = 0; i < (8 >> scale); i++)
476     store_vr (SD_, scale, VD, i,
477               (value_vr (SD_, scale, VS, i)
478                & select_vr (SD_, SEL, VT, i)));
483 // Vector Compare Equal.
486 010010,5.SEL,5.VT,5.VS,00000,000001::64,f::C.EQ.fmt
487 "c.EQ.%s<SEL> v<VS>, %s<VT#SEL,VT>"
488 *mdmx:
489 // start-sanitize-vr5400
490 *vr5400:
491 // end-sanitize-vr5400
493   int i;
494   int scale = get_scale (SD_, SEL);
495   for (i = 0; i < (8 >> scale); i++)
496     store_cc (SD_, i,
497               (value_vr (SD_, scale, VS, i)
498                == select_vr (SD_, SEL, VT, i)));
503 // Vector Compare Less Than or Equal.
505 010010,5.SEL,5.VT,5.VS,00000,000101::64,f::C.LE.fmt
506 "c.le.%s<SEL> v<VS>, %s<VT#SEL,VT>"
507 *mdmx:
508 // start-sanitize-vr5400
509 *vr5400:
510 // end-sanitize-vr5400
512   int i;
513   int scale = get_scale (SD_, SEL);
514   for (i = 0; i < (8 >> scale); i++)
515     store_cc (SD_, i,
516               (value_vr (SD_, scale, VS, i)
517                <= select_vr (SD_, SEL, VT, i)));
522 // Vector Compare Less Than.
524 010010,5.SEL,5.VT,5.VS,00000,000100::64,f::C.LT.fmt
525 "c.lt.%s<SEL> v<VS>, %s<VT#SEL,VT>"
526 *mdmx:
527 // start-sanitize-vr5400
528 *vr5400:
529 // end-sanitize-vr5400
531   int i;
532   int scale = get_scale (SD_, SEL);
533   for (i = 0; i < (8 >> scale); i++)
534     store_cc (SD_, i,
535               (value_vr (SD_, scale, VS, i)
536                < select_vr (SD_, SEL, VT, i)));
541 // Vector Maximum.
543 :function:64,f::signed:Maxi:int scale, signed l, signed r
544 *mdmx:
545 // start-sanitize-vr5400
546 *vr5400:
547 // end-sanitize-vr5400
549   if (l < r)
550     return r;
551   else
552     return l;
555 010010,5.SEL,5.VT,5.VS,5.VD,000111::64,f::MAX.fmt
556 "max.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
557 *mdmx:
558 // start-sanitize-vr5400
559 *vr5400:
560 // end-sanitize-vr5400
562   int i;
563   int scale = get_scale (SD_, SEL);
564   for (i = 0; i < (8 >> scale); i++)
565     store_vr (SD_, scale, VD, i,
566               Maxi (SD_, scale,
567                     value_vr (SD_, scale, VS, i),
568                     select_vr (SD_, SEL, VT, i)));
573 // Vector Minimum.
575 :function:64,f::signed:Mini:int scale, signed l, signed r
576 *mdmx:
577 // start-sanitize-vr5400
578 *vr5400:
579 // end-sanitize-vr5400
581   if (l < r)
582     return l;
583   else
584     return r;
587 010010,5.SEL,5.VT,5.VS,5.VD,000110::64,f::MIN.fmt
588 "min.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
589 *mdmx:
590 // start-sanitize-vr5400
591 *vr5400:
592 // end-sanitize-vr5400
594   int i;
595   int scale = get_scale (SD_, SEL);
596   for (i = 0; i < (8 >> scale); i++)
597     store_vr (SD_, scale, VD, i,
598               Mini (SD_, scale,
599                     value_vr (SD_, scale, VS, i),
600                     select_vr (SD_, SEL, VT, i)));
605 // Vector Sign.
607 :function:64,f::signed:Sign:int scale, signed l, signed r
608 *mdmx:
609 // start-sanitize-vr5400
610 *vr5400:
611 // end-sanitize-vr5400
613   if (l >= 0)
614     return r;
615   else if (r >= 0)
616     return -r;
617   else
618     {
619       /* watch for overflow of MIN_INT */
620       switch (scale)
621         {
622         case 0:
623           if ((r & 0xff) == 0x80)
624             return 0x7ff;
625           else
626             return -r;
627         case 1:
628           if ((r & 0xffff) == 0x8000)
629             return 0x7ffff;
630           else
631             return -r;
632         default:
633           abort ();
634         }
635       return -r;
636     }
639 010010,5.SEL,5.VT,5.VS,5.VD,000110::64,f::MSGN.fmt
640 "msgn.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
641 *mdmx:
643   int i;
644   int scale = get_scale (SD_, SEL);
645   if ((SEL & 1) != 1)
646     /* only QH allowed */
647     semantic_illegal (sd, cia);
648   for (i = 0; i < (8 >> scale); i++)
649     store_vr (SD_, scale, VD, i,
650               Sign (SD_, scale,
651                     value_vr (SD_, scale, VS, i),
652                     select_vr (SD_, SEL, VT, i)));
657 // Vector Multiply.
659 010010,5.SEL,5.VT,5.VS,5.VD,110000::64,f::MUL.fmt
660 "mul.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
661 *mdmx:
662 // start-sanitize-vr5400
663 *vr5400:
664 // end-sanitize-vr5400
666   int i;
667   int scale = get_scale (SD_, SEL);
668   for (i = 0; i < (8 >> scale); i++)
669     store_vr (SD_, scale, VD, i,
670               Clamp (SD_, scale,
671                      (value_vr (SD_, scale, VS, i)
672                       * select_vr (SD_, SEL, VT, i))));
677 // Accumulate Vector Multiply
679 010010,5.SEL,5.VT,5.VS,00000,110011::64,f::MULA.fmt
680 "mula.%s<SEL> v<VS>, %s<VT#SEL,VT>"
681 *mdmx:
682 // start-sanitize-vr5400
683 *vr5400:
684 // end-sanitize-vr5400
686   int i;
687   int scale = get_scale (SD_, SEL);
688   for (i = 0; i < (8 >> scale); i++)
689     store_acc (SD_, scale, i,
690                (value_acc (SD_, scale, i)
691                 + ((signed64) value_vr (SD_, scale, VS, i)
692                    * (signed64) select_vr (SD_, SEL, VT, i))));
697 // Add Vector Multiply to Accumulator.
699 010010,5.SEL,5.VT,5.VS,10000,110011::64,f::MULL.fmt
700 "mull.%s<SEL> v<VS>, %s<VT#SEL,VT>"
701 *mdmx:
702 // start-sanitize-vr5400
703 *vr5400:
704 // end-sanitize-vr5400
706   int i;
707   int scale = get_scale (SD_, SEL);
708   for (i = 0; i < (8 >> scale); i++)
709     store_acc (SD_, scale, i,
710                ((signed64) value_vr (SD_, scale, VS, i)
711                 * (signed64) select_vr (SD_, SEL, VT, i)));
716 // Subtract Vector Multiply from Accumulator
718 010010,5.SEL,5.VT,5.VS,00000,110010::64,f::MULS.fmt
719 "muls.%s<SEL> v<VS>, %s<VT#SEL,VT>"
720 *mdmx:
721 // start-sanitize-vr5400
722 *vr5400:
723 // end-sanitize-vr5400
725   int i;
726   int scale = get_scale (SD_, SEL);
727   for (i = 0; i < (8 >> scale); i++)
728     store_acc (SD_, scale, i,
729                (value_acc (SD_, scale, i)
730                 - ((signed64) value_vr (SD_, scale, VS, i)
731                    * (signed64) select_vr (SD_, SEL, VT, i))));
736 // Load Negative Vector Multiply
738 010010,5.SEL,5.VT,5.VS,10000,110010::64,f::MULSL.fmt
739 "mulsl.%s<SEL> v<VS>, %s<VT#SEL,VT>"
740 *mdmx:
741 // start-sanitize-vr5400
742 *vr5400:
743 // end-sanitize-vr5400
745   int i;
746   int scale = get_scale (SD_, SEL);
747   for (i = 0; i < (8 >> scale); i++)
748     store_acc (SD_, scale, i,
749                - ((signed64) value_vr (SD_, scale, VS, i)
750                   * (signed64) select_vr (SD_, SEL, VT, i)));
755 // Vector Nor.
757 010010,5.SEL,5.VT,5.VS,5.VD,001111::64,f::NOR.fmt
758 "nor.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
759 *mdmx:
760 // start-sanitize-vr5400
761 *vr5400:
762 // end-sanitize-vr5400
764   int i;
765   int scale = get_scale (SD_, SEL);
766   for (i = 0; i < (8 >> scale); i++)
767     store_vr (SD_, scale, VD, i,
768               ~(value_vr (SD_, scale, VS, i)
769                 | select_vr (SD_, SEL, VT, i)));
774 // Vector Or.
776 010010,5.SEL,5.VT,5.VS,5.VD,001110::64,f::OR.fmt
777 "or.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
778 *mdmx:
779 // start-sanitize-vr5400
780 *vr5400:
781 // end-sanitize-vr5400
783   int i;
784   int scale = get_scale (SD_, SEL);
785   for (i = 0; i < (8 >> scale); i++)
786     store_vr (SD_, scale, VD, i,
787               (value_vr (SD_, scale, VS, i)
788                | select_vr (SD_, SEL, VT, i)));
793 // Select Vector Elements - False
795 010010,5.SEL,5.VT,5.VS,5.VD,000010::64,f::PICKF.fmt
796 "pickf.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
797 *mdmx:
798 // start-sanitize-vr5400
799 *vr5400:
800 // end-sanitize-vr5400
802   int i;
803   int scale = get_scale (SD_, SEL);
804   for (i = 0; i < (8 >> scale); i++)
805     store_vr (SD_, scale, VD, i,
806               (value_cc (SD_, i) == 0
807                ? value_vr (SD_, scale, VS, i)
808                : select_vr (SD_, SEL, VT, i)));
813 // Select Vector Elements - True
815 010010,5.SEL,5.VT,5.VS,5.VD,000011::64,f::PICKT.fmt
816 "pickt.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
817 *mdmx:
818 // start-sanitize-vr5400
819 *vr5400:
820 // end-sanitize-vr5400
822   int i;
823   int scale = get_scale (SD_, SEL);
824   for (i = 0; i < (8 >> scale); i++)
825     store_vr (SD_, scale, VD, i,
826               (value_cc (SD_, i) != 0
827                ? value_vr (SD_, scale, VS, i)
828                : select_vr (SD_, SEL, VT, i)));
833 // Scale, Round and Clamp Accumulator
835 :%s:64,f:::RND:int rnd
836 *mdmx:
837 // start-sanitize-vr5400
838 *vr5400:
839 // end-sanitize-vr5400
841   switch (rnd)
842     {
843     case 0:
844       return "zu";
845     case 1:
846       return "nau";
847     case 2:
848       return "neu";
849     case 4:
850       return "rzs";
851     case 5:
852       return "nas";
853     case 6:
854       return "nes";
855     default:
856       return "(invalid)";
857     }
860 :function:64,f::signed:ScaleRoundClamp:int scale, int rnd, signed val, signed shift
861 *mdmx:
862 // start-sanitize-vr5400
863 *vr5400:
864 // end-sanitize-vr5400
866   int halfway = (1 << (shift - 1));
867   /* must be positive */
868   if (shift < 0)
869     return 0;
870   /* too much shift? */
871   switch (scale)
872     {
873     case 0:
874       if (shift >= 24)
875         return 0;
876       break;
877     case 1:
878       if (shift >= 48)
879         return 0;
880       break;
881     default:
882       abort ();
883     }
884   /* round */
885   switch (rnd & 3)
886     {
887     case 0: /* round towards zero */
888       break;
889     case 1: /* nearest, halfaway rounds away from zero */
890       if (val >= 0)
891         val += halfway;
892       else
893         val -= halfway;
894       break;
895     case 2: /* nearest, halfway rounds to even! */
896       if (val >= 0)
897         {
898           if (val & (halfway << 1))
899             val += halfway;
900           else
901             val += (halfway - 1);
902         }
903       else
904         {
905           if (val & (halfway << 1))
906             val -= halfway;
907           else
908             val -= (halfway - 1);
909         }
910     default:
911       abort ();
912     }
913   /* shift */
914   val >>= shift;
915   /* clamp */
916   switch (rnd & 4)
917     {
918     case 0:
919       /* unsigned clamp */
920       if (val < 0)
921         val = 0;
922       else
923         switch (scale)
924           {
925           case 0:
926             if (val > 0xff)
927               val = 0xff;
928             break;
929           case 1:
930             if (val > 0xffff)
931               val = 0xffff;
932             break;
933           }
934       break;
935     case 8:
936       /* normal signed clamp */
937       val = Clamp (_SD, scale, val);
938       break;
939     }
940   return val;
943 010010,5.SEL,5.VT,00000,5.VD,100,3.RND::64,f::Rx.fmt
944 "r%s<RND>.%s<SEL> v<VD>, v<VT>"
945 *mdmx:
946 // start-sanitize-vr5400
947 *vr5400:
948 // end-sanitize-vr5400
950   int i;
951   int scale = get_scale (SD_, SEL);
952   for (i = 0; i < (8 >> scale); i++)
953     store_vr (SD_, scale, VD, i,
954               ScaleRoundClamp (SD_, scale, RND,
955                                value_acc (SD_, scale, i),
956                                select_vr (SD_, SEL, VT, i)));
961 // Vector Read  Accumulator Low.
963 010010,0000,1.SEL,00000,00000,5.VD,111111::64,f::RACL.fmt
964 "racl.%s<SEL> v<VD>"
965 *mdmx:
966 // start-sanitize-vr5400
967 *vr5400:
968 // end-sanitize-vr5400
970   int i;
971   int scale = get_scale (SD_, SEL);
972   for (i = 0; i < (8 >> scale); i++)
973     store_vr (SD_, scale, VD, i,
974               EXTRACTED (value_acc (SD_, scale, i),
975                          (8 << scale) - 1,
976                          0));
981 // Vector Read  Accumulator Middle.
983 010010,0100,1.SEL,00000,00000,5.VD,111111::64,f::RACM.fmt
984 "racm.%s<SEL> v<VD>"
985 *mdmx:
986 // start-sanitize-vr5400
987 *vr5400:
988 // end-sanitize-vr5400
990   int i;
991   int scale = get_scale (SD_, SEL);
992   for (i = 0; i < (8 >> scale); i++)
993     store_vr (SD_, scale, VD, i,
994               EXTRACTED (value_acc (SD_, scale, i),
995                          (16 << scale) - 1,
996                          (8 << scale) - 0));
1001 // Vector Read  Accumulator High.
1003 010010,1000,1.SEL,00000,00000,5.VD,111111::64,f::RACH.fmt
1004 "rach.%s<SEL> v<VD>"
1005 *mdmx:
1006 // start-sanitize-vr5400
1007 *vr5400:
1008 // end-sanitize-vr5400
1010   int i;
1011   int scale = get_scale (SD_, SEL);
1012   for (i = 0; i < (8 >> scale); i++)
1013     store_vr (SD_, scale, VD, i,
1014               EXTRACTED (value_acc (SD_, scale, i),
1015                          (24 << scale) - 1,
1016                          (16 << scale) - 0));
1021 // Vector Element Shuffle.
1023 010010,0000,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPUH.fmt
1024 "shfl.upuh.%s<SEL> v<VD>, v<VS>, <VT>"
1025 *mdmx:
1027   int i;
1028   int scale = get_scale (SD_, SEL);
1029   for (i = 0; i < 4; i++)
1030     {
1031       store_vr (SD_, 1, VD, i,
1032                 value_vr (SD_, 0, VS, i + 4) & 0xff);
1033     }
1036 010010,0001,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPUL.fmt
1037 "shfl.upul.%s<SEL> v<VD>, v<VS>, <VT>"
1038 *mdmx:
1040   int i;
1041   for (i = 0; i < 4; i++)
1042     {
1043       store_vr (SD_, 1, VD, i,
1044                 value_vr (SD_, 0, VS, i) & 0xff);
1045     }
1048 010010,0000,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPSH.fmt
1049 "shfl.upsh.%s<SEL> v<VD>, v<VS>, <VT>"
1050 *mdmx:
1052   int i;
1053   int scale = get_scale (SD_, SEL);
1054   for (i = 0; i < 4; i++)
1055     {
1056       store_vr (SD_, 1, VD, i,
1057                 value_vr (SD_, 0, VS, i + 4));
1058     }
1061 010010,0001,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPSL.fmt
1062 "shfl.upsl.%s<SEL> v<VD>, v<VS>, <VT>"
1063 *mdmx:
1065   int i;
1066   for (i = 0; i < 4; i++)
1067     {
1068       store_vr (SD_, 1, VD, i,
1069                 value_vr (SD_, 0, VS, i));
1070     }
1073 010010,0100,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.PACH.fmt
1074 "shfl.pach.%s<SEL> v<VD>, v<VS>, <VT>"
1075 *mdmx:
1076 // start-sanitize-vr5400
1077 *vr5400:
1078 // end-sanitize-vr5400
1080   int i;
1081   int scale = get_scale (SD_, SEL);
1082   for (i = 0; i < (4 >> scale); i++)
1083     {
1084       store_vr (SD_, scale, VD, i,
1085                 value_vr (SD_, scale, VT, i * 2 + 1));
1086       store_vr (SD_, scale, VD, 1 + (4 >> scale),
1087                 value_vr (SD_, scale, VS, i * 2 + 1));
1088     }
1091 010010,0101,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.PACL.fmt
1092 "shfl.pacl.%s<SEL> v<VD>, v<VS>, <VT>"
1093 *mdmx:
1094 // start-sanitize-vr5400
1095 *vr5400:
1096 // end-sanitize-vr5400
1098   int i;
1099   int scale = get_scale (SD_, SEL);
1100   for (i = 0; i < (4 >> scale); i++)
1101     {
1102       store_vr (SD_, scale, VD, i,
1103                 value_vr (SD_, scale, VT, i * 2));
1104       store_vr (SD_, scale, VD, 1 + (4 >> scale),
1105                 value_vr (SD_, scale, VS, i * 2));
1106     }
1109 010010,0110,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.MIXH.fmt
1110 "shfl.mixh.%s<SEL> v<VD>, v<VS>, <VT>"
1111 *mdmx:
1112 // start-sanitize-vr5400
1113 *vr5400:
1114 // end-sanitize-vr5400
1116   int i;
1117   int scale = get_scale (SD_, SEL);
1118   for (i = 0; i < (4 >> scale); i++)
1119     {
1120       store_vr (SD_, scale, VD, i * 2,
1121                 value_vr (SD_, scale, VT, i + (4 >> scale)));
1122       store_vr (SD_, scale, VD, i * 2 + 1,
1123                 value_vr (SD_, scale, VS, i + (4 >> scale)));
1124     }
1127 010010,0111,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.MIXL.fmt
1128 "shfl.mixl.%s<SEL> v<VD>, v<VS>, <VT>"
1129 *mdmx:
1130 // start-sanitize-vr5400
1131 *vr5400:
1132 // end-sanitize-vr5400
1134   int i;
1135   int scale = get_scale (SD_, SEL);
1136   for (i = 0; i < (4 >> scale); i++)
1137     {
1138       store_vr (SD_, scale, VD, i * 2,
1139                 value_vr (SD_, scale, VT, i));
1140       store_vr (SD_, scale, VD, i * 2 + 1,
1141                 value_vr (SD_, scale, VS, i));
1142     }
1145 010010,100,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.BFLA.fmt
1146 "shfl.bfla.qh v<VD>, v<VS>, <VT>"
1147 *mdmx:
1149   store_vr (SD_, 1, VD, 0,
1150             value_vr (SD_, 1, VT, 1));
1151   store_vr (SD_, 1, VD, 1,
1152             value_vr (SD_, 1, VS, 0));
1153   store_vr (SD_, 1, VD, 2,
1154             value_vr (SD_, 1, VT, 3));
1155   store_vr (SD_, 1, VD, 3,
1156             value_vr (SD_, 1, VS, 2));
1159 010010,101,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.BFLB.fmt
1160 "shfl.bflb.qh v<VD>, v<VS>, <VT>"
1161 *mdmx:
1163   store_vr (SD_, 1, VD, 0,
1164             value_vr (SD_, 1, VT, 3));
1165   store_vr (SD_, 1, VD, 1,
1166             value_vr (SD_, 1, VS, 2));
1167   store_vr (SD_, 1, VD, 2,
1168             value_vr (SD_, 1, VT, 1));
1169   store_vr (SD_, 1, VD, 3,
1170             value_vr (SD_, 1, VS, 0));
1173 010010,101,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.REPA.fmt
1174 "shfl.repa.qh v<VD>, v<VS>, <VT>"
1175 *mdmx:
1177   store_vr (SD_, 1, VD, 0,
1178             value_vr (SD_, 1, VT, 2));
1179   store_vr (SD_, 1, VD, 1,
1180             value_vr (SD_, 1, VT, 3));
1181   store_vr (SD_, 1, VD, 2,
1182             value_vr (SD_, 1, VS, 2));
1183   store_vr (SD_, 1, VD, 3,
1184             value_vr (SD_, 1, VS, 3));
1187 010010,101,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.REPB.fmt
1188 "shfl.repb.qh v<VD>, v<VS>, <VT>"
1189 *mdmx:
1191   store_vr (SD_, 1, VD, 0,
1192             value_vr (SD_, 1, VT, 0));
1193   store_vr (SD_, 1, VD, 1,
1194             value_vr (SD_, 1, VT, 1));
1195   store_vr (SD_, 1, VD, 2,
1196             value_vr (SD_, 1, VS, 0));
1197   store_vr (SD_, 1, VD, 3,
1198             value_vr (SD_, 1, VS, 1));
1203 // Vector Shift Left Logical
1205 010010,5.SEL,5.VT,5.VS,5.VD,010000::64,f::SLL.fmt
1206 "sll.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1207 *mdmx:
1208 // start-sanitize-vr5400
1209 *vr5400:
1210 // end-sanitize-vr5400
1212   int i;
1213   int scale = get_scale (SD_, SEL);
1214   int mask = (4 << scale) - 1;
1215   for (i = 0; i < (8 >> scale); i++)
1216     store_vr (SD_, scale, VD, i,
1217               (value_vr (SD_, scale, VS, i)
1218                << (select_vr (SD_, SEL, VT, i) & mask)));
1223 // Vector Shift Right Arithmetic
1225 010010,5.SEL,5.VT,5.VS,5.VD,010011::64,f::SRA.fmt
1226 "sra.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1227 *mdmx:
1229   int i;
1230   int mask = (4 << scale) - 1;
1231   int scale = get_scale (SD_, SEL);
1232   for (i = 0; i < (8 >> scale); i++)
1233     store_vr (SD_, scale, VD, i,
1234               (value_vr (SD_, scale, VS, i)
1235                >> (select_vr (SD_, SEL, VT, i) & mask)));
1240 // Vector Shift Right Logical.
1242 010010,5.SEL,5.VT,5.VS,5.VD,010010::64,f::SRL.fmt
1243 "srl.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1244 *mdmx:
1245 // start-sanitize-vr5400
1246 *vr5400:
1247 // end-sanitize-vr5400
1249   int i;
1250   int scale = get_scale (SD_, SEL);
1251   int mask = (4 << scale) - 1;
1252   int zeros = (1 << (8 << scale)) - 1;
1253   for (i = 0; i < (8 >> scale); i++)
1254     store_vr (SD_, scale, VD, i,
1255               ((value_vr (SD_, scale, VS, i) & zeros)
1256                >> (select_vr (SD_, SEL, VT, i) & mask)));
1261 // Vector Subtract.
1263 010010,5.SEL,5.VT,5.VS,5.VD,001010::64,f::SUB.fmt
1264 "sub.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1265 *mdmx:
1266 // start-sanitize-vr5400
1267 *vr5400:
1268 // end-sanitize-vr5400
1270   int i;
1271   int scale = get_scale (SD_, SEL);
1272   for (i = 0; i < (8 >> scale); i++)
1273     store_vr (SD_, scale, VD, i,
1274               (value_vr (SD_, scale, VS, i)
1275                - select_vr (SD_, SEL, VT, i)));
1280 // Accumulate Vector Difference
1282 010010,5.SEL,5.VT,5.VS,0,0000,110110::64,f::SUBA.fmt
1283 "suba.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1284 *mdmx:
1286   int i;
1287   int scale = get_scale (SD_, SEL);
1288   for (i = 0; i < (8 >> scale); i++)
1289     store_acc (SD_, scale, VD, i,
1290                (value_acc (SD, scale, i)
1291                 + (signed64) value_vr (SD_, scale, VS, i)
1292                 - (signed64) select_vr (SD_, SEL, VT, i)));
1297 // Load Vector Difference
1299 010010,5.SEL,5.VT,5.VS,1,0000,110110::64,f::SUBL.fmt
1300 "subl.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1301 *mdmx:
1303   int i;
1304   int scale = get_scale (SD_, SEL);
1305   for (i = 0; i < (8 >> scale); i++)
1306     store_acc (SD_, scale, VD, i,
1307                ((signed64) value_vr (SD_, scale, VS, i)
1308                 - (signed64) select_vr (SD_, SEL, VT, i)));
1313 // Write Accumulator High.
1315 010010,1000,1.SEL,00000,5.VS,00000,111110::64,f::WACH.fmt
1316 "wach.%s<SEL> v<VS>"
1317 *mdmx:
1318 // start-sanitize-vr5400
1319 *vr5400:
1320 // end-sanitize-vr5400
1322   int i;
1323   int scale = get_scale (SD_, SEL);
1324   for (i = 0; i < (8 >> scale); i++)
1325     store_acc (SD_, scale, i,
1326                (((signed64) value_vr (SD_, scale, VS, i) << (16 << scale))
1327                 | MASKED (value_acc (SD_, scale, i), (16 << scale) - 1, 0)));
1332 // Vector Write Accumulator Low.
1334 010010,0000,1.SEL,5.VT,5.VS,00000,111110::64,f::WACL.fmt
1335 "wacl.%s<SEL> v<VS>, <VT>"
1336 *mdmx:
1337 // start-sanitize-vr5400
1338 *vr5400:
1339 // end-sanitize-vr5400
1341   int i;
1342   int scale = get_scale (SD_, SEL);
1343   for (i = 0; i < (8 >> scale); i++)
1344     store_acc (SD_, scale, i,
1345                (((signed64) value_vr (SD_, scale, VS, i) << (16 << scale))
1346                 | MASKED (value_vr (SD_, scale, VT, i),
1347                           (16 << scale) - 1, 0)));
1352 // Vector Xor.
1354 010010,5.SEL,5.VT,5.VS,5.VD,001101::64,f::XOR.fmt
1355 "xor.%s<SEL> v<VD>, v<VS>, %s<VT#SEL,VT>"
1356 *mdmx:
1357 // start-sanitize-vr5400
1358 *vr5400:
1359 // end-sanitize-vr5400
1361   int i;
1362   int scale = get_scale (SD_, SEL);
1363   for (i = 0; i < (8 >> scale); i++)
1364     store_vr (SD_, scale, VD, i,
1365               (value_vr (SD_, scale, VS, i)
1366                ^ select_vr (SD_, SEL, VT, i)));