]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/mips/mdmx.igen
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / sim / mips / mdmx.igen
CommitLineData
0e701ac3 1// -*- C -*-
35c246c9
AC
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
a48e8c8d
AC
30:function:64,f::int:get_scale:int sel
31*mdmx:
32// start-sanitize-vr5400
33*vr5400:
34// end-sanitize-vr5400
35c246c9
AC
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 */
01737f42 55 semantic_illegal (CPU_, cia);
35c246c9
AC
56 return 2;
57 case 7:
58 /* long - ss111 */
01737f42 59 semantic_illegal (CPU_, cia);
35c246c9
AC
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
a48e8c8d
AC
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
35c246c9
AC
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:
01737f42
AC
86 sim_io_eprintf (SD, "Vector %d format invalid (PC = 0x%08lx)\n",
87 fpr, (long) CIA);
35c246c9
AC
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
a48e8c8d
AC
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
35c246c9
AC
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:
01737f42
AC
123 sim_io_eprintf (SD, "Vector %d format invalid (PC = 0x%08lx)\n",
124 fpr, (long) cia);
35c246c9
AC
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
a48e8c8d
AC
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
35c246c9
AC
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
a48e8c8d
AC
202:function:64,f::signed:Clamp:int scale, signed value
203*mdmx:
204// start-sanitize-vr5400
205*vr5400:
206// end-sanitize-vr5400
35c246c9
AC
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
a48e8c8d
AC
241:function:64,f::void:store_cc:int i, int value
242*mdmx:
243// start-sanitize-vr5400
244*vr5400:
245// end-sanitize-vr5400
35c246c9 246{
01737f42 247 SETFCC (i, value);
35c246c9
AC
248}
249
a48e8c8d
AC
250:function:64,f::int:value_cc:int i
251*mdmx:
252// start-sanitize-vr5400
253*vr5400:
254// end-sanitize-vr5400
35c246c9 255{
01737f42 256 return GETFCC (i);
35c246c9
AC
257}
258
259
260// Read/write the accumulator
261
a48e8c8d
AC
262:function:64,f::signed64:value_acc:int scale, int element
263*mdmx:
264// start-sanitize-vr5400
265*vr5400:
266// end-sanitize-vr5400
35c246c9
AC
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
a48e8c8d
AC
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
35c246c9
AC
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
a48e8c8d
AC
315:%s:64,f:::VT:int sel, int vt
316*mdmx:
317// start-sanitize-vr5400
318*vr5400:
319// end-sanitize-vr5400
35c246c9
AC
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
a48e8c8d
AC
333:%s:64,f:::SEL:int sel
334*mdmx:
335// start-sanitize-vr5400
336*vr5400:
337// end-sanitize-vr5400
35c246c9
AC
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
a48e8c8d 359010010,5.SEL,5.VT,5.VS,5.VD,001011::64,f::ADD.fmt
35c246c9
AC
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
a48e8c8d 378010010,5.SEL,5.VT,5.VS,1,0000,110111::64,f::ADDA.fmt
35c246c9
AC
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
a48e8c8d 394010010,5.SEL,5.VT,5.VS,0,0000,110111::64,f::ADDA.fmt
35c246c9
AC
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
a48e8c8d
AC
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
35c246c9
AC
415{
416 int s = imm * 8;
01737f42
AC
417 unsigned64 rs = ValueFPR (vs, fmt_long);
418 unsigned64 rt = ValueFPR (vt, fmt_long);
35c246c9
AC
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 }
01737f42 438 StoreFPR (vd, fmt_long, rd);
35c246c9
AC
439}
440
a48e8c8d 441010010,00,3.IMM,5.VT,5.VS,5.VD,0110,X,0::64,f::ALNI.fmt
35c246c9
AC
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
a48e8c8d 455010010,5.RS,5.VT,5.VS,5.VD,0110,X,1::64,f::ALNV.fmt
35c246c9
AC
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
a48e8c8d 466010010,5.SEL,5.VT,5.VS,5.VD,001100::64,f::AND.fmt
35c246c9
AC
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
a48e8c8d 486010010,5.SEL,5.VT,5.VS,00000,000001::64,f::C.EQ.fmt
35c246c9
AC
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
a48e8c8d 505010010,5.SEL,5.VT,5.VS,00000,000101::64,f::C.LE.fmt
35c246c9
AC
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
a48e8c8d 524010010,5.SEL,5.VT,5.VS,00000,000100::64,f::C.LT.fmt
35c246c9
AC
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
0e701ac3 543:function:64,f::signed:Maxi:int scale, signed l, signed r
a48e8c8d
AC
544*mdmx:
545// start-sanitize-vr5400
546*vr5400:
547// end-sanitize-vr5400
35c246c9
AC
548{
549 if (l < r)
550 return r;
551 else
552 return l;
553}
554
a48e8c8d 555010010,5.SEL,5.VT,5.VS,5.VD,000111::64,f::MAX.fmt
35c246c9
AC
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,
0e701ac3
AC
566 Maxi (SD_, scale,
567 value_vr (SD_, scale, VS, i),
568 select_vr (SD_, SEL, VT, i)));
35c246c9
AC
569}
570
571
572
573// Vector Minimum.
574
0e701ac3 575:function:64,f::signed:Mini:int scale, signed l, signed r
a48e8c8d
AC
576*mdmx:
577// start-sanitize-vr5400
578*vr5400:
579// end-sanitize-vr5400
35c246c9
AC
580{
581 if (l < r)
582 return l;
583 else
584 return r;
585}
586
a48e8c8d 587010010,5.SEL,5.VT,5.VS,5.VD,000110::64,f::MIN.fmt
35c246c9
AC
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,
0e701ac3
AC
598 Mini (SD_, scale,
599 value_vr (SD_, scale, VS, i),
600 select_vr (SD_, SEL, VT, i)));
35c246c9
AC
601}
602
603
604
605// Vector Sign.
606
a48e8c8d
AC
607:function:64,f::signed:Sign:int scale, signed l, signed r
608*mdmx:
609// start-sanitize-vr5400
610*vr5400:
611// end-sanitize-vr5400
35c246c9
AC
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
a48e8c8d 639010010,5.SEL,5.VT,5.VS,5.VD,000110::64,f::MSGN.fmt
35c246c9
AC
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
a48e8c8d 659010010,5.SEL,5.VT,5.VS,5.VD,110000::64,f::MUL.fmt
35c246c9
AC
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
a48e8c8d 679010010,5.SEL,5.VT,5.VS,00000,110011::64,f::MULA.fmt
35c246c9
AC
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
a48e8c8d 699010010,5.SEL,5.VT,5.VS,10000,110011::64,f::MULL.fmt
35c246c9
AC
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
a48e8c8d 718010010,5.SEL,5.VT,5.VS,00000,110010::64,f::MULS.fmt
35c246c9
AC
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
a48e8c8d 738010010,5.SEL,5.VT,5.VS,10000,110010::64,f::MULSL.fmt
35c246c9
AC
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
a48e8c8d 757010010,5.SEL,5.VT,5.VS,5.VD,001111::64,f::NOR.fmt
35c246c9
AC
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
a48e8c8d 776010010,5.SEL,5.VT,5.VS,5.VD,001110::64,f::OR.fmt
35c246c9
AC
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
a48e8c8d 795010010,5.SEL,5.VT,5.VS,5.VD,000010::64,f::PICKF.fmt
35c246c9
AC
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,
01737f42 806 (value_cc (SD_, i) == 0
35c246c9
AC
807 ? value_vr (SD_, scale, VS, i)
808 : select_vr (SD_, SEL, VT, i)));
809}
810
811
812
813// Select Vector Elements - True
814
a48e8c8d 815010010,5.SEL,5.VT,5.VS,5.VD,000011::64,f::PICKT.fmt
35c246c9
AC
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,
01737f42 826 (value_cc (SD_, i) != 0
35c246c9
AC
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
a48e8c8d
AC
835:%s:64,f:::RND:int rnd
836*mdmx:
837// start-sanitize-vr5400
838*vr5400:
839// end-sanitize-vr5400
35c246c9
AC
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
a48e8c8d
AC
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
35c246c9
AC
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
a48e8c8d 943010010,5.SEL,5.VT,00000,5.VD,100,3.RND::64,f::Rx.fmt
35c246c9
AC
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
a48e8c8d 963010010,0000,1.SEL,00000,00000,5.VD,111111::64,f::RACL.fmt
35c246c9
AC
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
a48e8c8d 983010010,0100,1.SEL,00000,00000,5.VD,111111::64,f::RACM.fmt
35c246c9
AC
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
a48e8c8d 1003010010,1000,1.SEL,00000,00000,5.VD,111111::64,f::RACH.fmt
35c246c9
AC
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
a48e8c8d 1023010010,0000,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPUH.fmt
35c246c9
AC
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
a48e8c8d 1036010010,0001,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPUL.fmt
35c246c9
AC
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
a48e8c8d 1048010010,0000,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPSH.fmt
35c246c9
AC
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
a48e8c8d 1061010010,0001,0,5.VT,5.VS,5.VD,011111::64,f::SHFL.UPSL.fmt
35c246c9
AC
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
a48e8c8d 1073010010,0100,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.PACH.fmt
35c246c9
AC
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
a48e8c8d 1091010010,0101,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.PACL.fmt
35c246c9
AC
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
a48e8c8d 1109010010,0110,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.MIXH.fmt
35c246c9
AC
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
a48e8c8d 1127010010,0111,1.SEL,5.VT,5.VS,5.VD,011111::64,f::SHFL.MIXL.fmt
35c246c9
AC
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
a48e8c8d 1145010010,100,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.BFLA.fmt
35c246c9
AC
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
a48e8c8d 1159010010,101,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.BFLB.fmt
35c246c9
AC
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
a48e8c8d 1173010010,101,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.REPA.fmt
35c246c9
AC
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
a48e8c8d 1187010010,101,01,5.VT,5.VS,5.VD,011111::64,f::SHFL.REPB.fmt
35c246c9
AC
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
a48e8c8d 1205010010,5.SEL,5.VT,5.VS,5.VD,010000::64,f::SLL.fmt
35c246c9
AC
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
a48e8c8d 1225010010,5.SEL,5.VT,5.VS,5.VD,010011::64,f::SRA.fmt
35c246c9
AC
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
a48e8c8d 1242010010,5.SEL,5.VT,5.VS,5.VD,010010::64,f::SRL.fmt
35c246c9
AC
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
a48e8c8d 1263010010,5.SEL,5.VT,5.VS,5.VD,001010::64,f::SUB.fmt
35c246c9
AC
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
a48e8c8d 1282010010,5.SEL,5.VT,5.VS,0,0000,110110::64,f::SUBA.fmt
35c246c9
AC
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
a48e8c8d 1299010010,5.SEL,5.VT,5.VS,1,0000,110110::64,f::SUBL.fmt
35c246c9
AC
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
a48e8c8d 1315010010,1000,1.SEL,00000,5.VS,00000,111110::64,f::WACH.fmt
35c246c9
AC
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
a48e8c8d 1334010010,0000,1.SEL,5.VT,5.VS,00000,111110::64,f::WACL.fmt
35c246c9
AC
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
a48e8c8d 1354010010,5.SEL,5.VT,5.VS,5.VD,001101::64,f::XOR.fmt
35c246c9
AC
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}