Add generic sim-info.c:sim_info() function using module mechanism.
[external/binutils.git] / sim / mips / mdmx.igen
1 //  -*- C -*-
2 // Media Instructions
3 // ------------------
4
5 // Ref: http://www.sgi.com/MIPS/arch/ISA5/MDMXspec.pdf
6
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
20 //
21 // VecAcc is the Vector Accumulator.
22 //     This accumulator is organized as 8X24 bit (192 bit) register.
23 //     This accumulator holds only signed values.
24
25
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.
29
30 :function:64,f::int:get_scale:int sel
31 *mdmx:
32 // start-sanitize-vr5400
33 *vr5400:
34 // end-sanitize-vr5400
35 {
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     }
65 }
66
67
68 // Fetch/Store VALUE in ELEMENT of vector register FPR.
69 // The the of the element determined by SCALE.
70
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
76 {
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;
106 }
107
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
113 {
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     }
142 }
143
144
145 // Select a value from onr of FGR[VT][ELEMENT], VT and GFR[VT][CONST]
146 // according to SEL
147
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
153 {
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);
177
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);
187
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;
194
195     }
196   return 0;
197 }
198
199
200 // Saturate (clamp) the signed value to (8 << SCALE) bits.
201
202 :function:64,f::signed:Clamp:int scale, signed value
203 *mdmx:
204 // start-sanitize-vr5400
205 *vr5400:
206 // end-sanitize-vr5400
207 {
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     }
236 }
237
238
239 // Access a single bit of the floating point CC register.
240
241 :function:64,f::void:store_cc:int i, int value
242 *mdmx:
243 // start-sanitize-vr5400
244 *vr5400:
245 // end-sanitize-vr5400
246 {
247   SETFCC (i, value);
248 }
249
250 :function:64,f::int:value_cc:int i
251 *mdmx:
252 // start-sanitize-vr5400
253 *vr5400:
254 // end-sanitize-vr5400
255 {
256   return GETFCC (i);
257 }
258
259
260 //  Read/write the accumulator
261
262 :function:64,f::signed64:value_acc:int scale, int element
263 *mdmx:
264 // start-sanitize-vr5400
265 *vr5400:
266 // end-sanitize-vr5400
267 {
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;
286 }
287
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
293 {
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     }
310 }
311
312
313 // Formatting
314
315 :%s:64,f:::VT:int sel, int vt
316 *mdmx:
317 // start-sanitize-vr5400
318 *vr5400:
319 // end-sanitize-vr5400
320 {
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;
331 }
332
333 :%s:64,f:::SEL:int sel
334 *mdmx:
335 // start-sanitize-vr5400
336 *vr5400:
337 // end-sanitize-vr5400
338 {
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     }
354 }
355
356
357 // Vector Add.
358
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
365 {
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))));
373 }
374
375
376 // Accumulate Vector Add
377
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:
381 {
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)));
389 }
390
391
392 // Load Vector Add
393
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:
397 {
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)));
404 }
405
406
407
408 // Vector align, Constant Alignment
409
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
415 {
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);
439 }
440
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
447 {
448   ByteAlign (SD_, VD, IMM, VS, VT);
449 }
450
451
452
453 // Vector align, Variable Alignment
454
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:
458 {
459   ByteAlign (SD_, VD, GPR[RS], VS, VT);
460 }
461
462
463
464 // Vector And.
465
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
472 {
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)));
479 }
480
481
482
483 // Vector Compare Equal.
484
485
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
492 {
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)));
499 }
500
501
502
503 // Vector Compare Less Than or Equal.
504
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
511 {
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)));
518 }
519
520
521
522 // Vector Compare Less Than.
523
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
530 {
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)));
537 }
538
539
540
541 // Vector Maximum.
542
543 :function:64,f::signed:Maxi:int scale, signed l, signed r
544 *mdmx:
545 // start-sanitize-vr5400
546 *vr5400:
547 // end-sanitize-vr5400
548 {
549   if (l < r)
550     return r;
551   else
552     return l;
553 }
554
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
561 {
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)));
569 }
570
571
572
573 // Vector Minimum.
574
575 :function:64,f::signed:Mini:int scale, signed l, signed r
576 *mdmx:
577 // start-sanitize-vr5400
578 *vr5400:
579 // end-sanitize-vr5400
580 {
581   if (l < r)
582     return l;
583   else
584     return r;
585 }
586
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
593 {
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)));
601 }
602
603
604
605 // Vector Sign.
606
607 :function:64,f::signed:Sign:int scale, signed l, signed r
608 *mdmx:
609 // start-sanitize-vr5400
610 *vr5400:
611 // end-sanitize-vr5400
612 {
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     }
637 }
638
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:
642 {
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)));
653 }
654
655
656
657 // Vector Multiply.
658
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
665 {
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))));
673 }
674
675
676
677 // Accumulate Vector Multiply
678
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
685 {
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))));
693 }
694
695
696
697 // Add Vector Multiply to Accumulator.
698
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
705 {
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)));
712 }
713
714
715
716 // Subtract Vector Multiply from Accumulator
717
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
724 {
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))));
732 }
733
734
735
736 // Load Negative Vector Multiply
737
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
744 {
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)));
751 }
752
753
754
755 // Vector Nor.
756
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
763 {
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)));
770 }
771
772
773
774 // Vector Or.
775
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
782 {
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)));
789 }
790
791
792
793 // Select Vector Elements - False
794
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
801 {
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)));
809 }
810
811
812
813 // Select Vector Elements - True
814
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
821 {
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)));
829 }
830
831
832
833 // Scale, Round and Clamp Accumulator
834
835 :%s:64,f:::RND:int rnd
836 *mdmx:
837 // start-sanitize-vr5400
838 *vr5400:
839 // end-sanitize-vr5400
840 {
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     }
858 }
859
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
865 {
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;
941 }
942
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
949 {
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)));
957 }
958
959
960
961 // Vector Read  Accumulator Low.
962
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
969 {
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));
977 }
978
979
980
981 // Vector Read  Accumulator Middle.
982
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
989 {
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));
997 }
998
999
1000
1001 // Vector Read  Accumulator High.
1002
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
1009 {
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));
1017 }
1018
1019
1020
1021 // Vector Element Shuffle.
1022
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:
1026 {
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     }
1034 }
1035
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:
1039 {
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     }
1046 }
1047
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:
1051 {
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     }
1059 }
1060
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:
1064 {
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     }
1071 }
1072
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
1079 {
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     }
1089 }
1090
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
1097 {
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     }
1107 }
1108
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
1115 {
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     }
1125 }
1126
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
1133 {
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     }
1143 }
1144
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:
1148 {
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));
1157 }
1158
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:
1162 {
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));
1171 }
1172
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:
1176 {
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));
1185 }
1186
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:
1190 {
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));
1199 }
1200
1201
1202
1203 // Vector Shift Left Logical
1204
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
1211 {
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)));
1219 }
1220
1221
1222
1223 // Vector Shift Right Arithmetic
1224
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:
1228 {
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)));
1236 }
1237
1238
1239
1240 // Vector Shift Right Logical.
1241
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
1248 {
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)));
1257 }
1258
1259
1260
1261 // Vector Subtract.
1262
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
1269 {
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)));
1276 }
1277
1278
1279
1280 // Accumulate Vector Difference
1281
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:
1285 {
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)));
1293 }
1294
1295
1296
1297 // Load Vector Difference
1298
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:
1302 {
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)));
1309 }
1310
1311
1312
1313 // Write Accumulator High.
1314
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
1321 {
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)));
1328 }
1329
1330
1331
1332 // Vector Write Accumulator Low.
1333
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
1340 {
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)));
1348 }
1349
1350
1351
1352 // Vector Xor.
1353
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
1360 {
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)));
1367 }