Commit | Line | Data |
---|---|---|
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 | 359 | 010010,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 | 378 | 010010,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 | 394 | 010010,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 | 441 | 010010,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 | 455 | 010010,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 | 466 | 010010,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 | 486 | 010010,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 | 505 | 010010,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 | 524 | 010010,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 | 555 | 010010,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 | 587 | 010010,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 | 639 | 010010,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 | 659 | 010010,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 | 679 | 010010,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 | 699 | 010010,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 | 718 | 010010,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 | 738 | 010010,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 | 757 | 010010,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 | 776 | 010010,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 | 795 | 010010,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 | 815 | 010010,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 | 943 | 010010,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 | 963 | 010010,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 | 983 | 010010,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 | 1003 | 010010,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 | 1023 | 010010,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 | 1036 | 010010,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 | 1048 | 010010,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 | 1061 | 010010,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 | 1073 | 010010,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 | 1091 | 010010,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 | 1109 | 010010,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 | 1127 | 010010,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 | 1145 | 010010,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 | 1159 | 010010,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 | 1173 | 010010,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 | 1187 | 010010,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 | 1205 | 010010,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 | 1225 | 010010,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 | 1242 | 010010,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 | 1263 | 010010,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 | 1282 | 010010,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 | 1299 | 010010,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 | 1315 | 010010,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 | 1334 | 010010,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 | 1354 | 010010,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 | } |