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