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