sim-main.h: Re-arange r5900 registers so that they have their own
[binutils-gdb.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 }