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