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