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