base, sim, mem, arch: Remove the dummy CPU in NULL
[gem5.git] / src / arch / mips / dsp.cc
1 /*
2 * Copyright (c) 2007 MIPS Technologies, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "arch/mips/dsp.hh"
30
31 #include "arch/mips/isa_traits.hh"
32 #include "base/bitfield.hh"
33 #include "base/logging.hh"
34 #include "cpu/static_inst.hh"
35 #include "sim/serialize.hh"
36
37 using namespace MipsISA;
38 using namespace std;
39
40 int32_t
41 MipsISA::bitrev(int32_t value)
42 {
43 int32_t result = 0;
44 int shift;
45
46 for (int i = 0; i < 16; i++) {
47 shift = 2 * i - 15;
48
49 if (shift < 0)
50 result |= (value & 1 << i) << -shift;
51 else
52 result |= (value & 1 << i) >> shift;
53 }
54
55 return result;
56 }
57
58 uint64_t
59 MipsISA::dspSaturate(uint64_t value, int32_t fmt, int32_t sign,
60 uint32_t *overflow)
61 {
62 int64_t svalue = (int64_t)value;
63
64 switch (sign) {
65 case SIGNED:
66 if (svalue > (int64_t)FIXED_SMAX[fmt]) {
67 *overflow = 1;
68 svalue = (int64_t)FIXED_SMAX[fmt];
69 } else if (svalue < (int64_t)FIXED_SMIN[fmt]) {
70 *overflow = 1;
71 svalue = (int64_t)FIXED_SMIN[fmt];
72 }
73 break;
74 case UNSIGNED:
75 if (svalue > (int64_t)FIXED_UMAX[fmt]) {
76 *overflow = 1;
77 svalue = FIXED_UMAX[fmt];
78 } else if (svalue < (int64_t)FIXED_UMIN[fmt]) {
79 *overflow = 1;
80 svalue = FIXED_UMIN[fmt];
81 }
82 break;
83 }
84
85 return (uint64_t)svalue;
86 }
87
88 uint64_t
89 MipsISA::checkOverflow(uint64_t value, int32_t fmt, int32_t sign,
90 uint32_t *overflow)
91 {
92 int64_t svalue = (int64_t)value;
93
94 switch (sign)
95 {
96 case SIGNED:
97 if (svalue > (int64_t)FIXED_SMAX[fmt] ||
98 svalue < (int64_t)FIXED_SMIN[fmt])
99 *overflow = 1;
100 break;
101 case UNSIGNED:
102 if (svalue > (int64_t)FIXED_UMAX[fmt] ||
103 svalue < (int64_t)FIXED_UMIN[fmt])
104 *overflow = 1;
105 break;
106 }
107
108 return (uint64_t)svalue;
109 }
110
111 uint64_t
112 MipsISA::signExtend(uint64_t value, int32_t fmt)
113 {
114 int32_t signpos = SIMD_NBITS[fmt];
115 uint64_t sign = uint64_t(1) << (signpos - 1);
116 uint64_t ones = ~(0ULL);
117
118 if (value & sign)
119 value |= (ones << signpos); // extend with ones
120 else
121 value &= (ones >> (64 - signpos)); // extend with zeros
122
123 return value;
124 }
125
126 uint64_t
127 MipsISA::addHalfLsb(uint64_t value, int32_t lsbpos)
128 {
129 return value += ULL(1) << (lsbpos - 1);
130 }
131
132 int32_t
133 MipsISA::dspAbs(int32_t a, int32_t fmt, uint32_t *dspctl)
134 {
135 int nvals = SIMD_NVALS[fmt];
136 int32_t result;
137 int64_t svalue;
138 uint32_t ouflag = 0;
139 uint64_t a_values[SIMD_MAX_VALS];
140
141 simdUnpack(a, a_values, fmt, SIGNED);
142
143 for (int i = 0; i < nvals; i++) {
144 svalue = (int64_t)a_values[i];
145
146 if (a_values[i] == FIXED_SMIN[fmt]) {
147 a_values[i] = FIXED_SMAX[fmt];
148 ouflag = 1;
149 } else if (svalue < 0) {
150 a_values[i] = uint64_t(0 - svalue);
151 }
152 }
153
154 simdPack(a_values, &result, fmt);
155
156 if (ouflag)
157 writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG],
158 1 << DSP_OUFLAG);
159
160 return result;
161 }
162
163 int32_t
164 MipsISA::dspAdd(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
165 int32_t sign, uint32_t *dspctl)
166 {
167 int nvals = SIMD_NVALS[fmt];
168 int32_t result;
169 uint32_t ouflag = 0;
170 uint64_t a_values[SIMD_MAX_VALS];
171 uint64_t b_values[SIMD_MAX_VALS];
172
173 simdUnpack(a, a_values, fmt, sign);
174 simdUnpack(b, b_values, fmt, sign);
175
176 for (int i = 0; i < nvals; i++)
177 {
178 if (saturate)
179 a_values[i] = dspSaturate(a_values[i] + b_values[i], fmt, sign,
180 &ouflag);
181 else
182 a_values[i] = checkOverflow(a_values[i] + b_values[i], fmt, sign,
183 &ouflag);
184 }
185
186 simdPack(a_values, &result, fmt);
187
188 if (ouflag)
189 writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG],
190 1 << DSP_OUFLAG);
191
192 return result;
193 }
194
195 int32_t
196 MipsISA::dspAddh(int32_t a, int32_t b, int32_t fmt, int32_t round,
197 int32_t sign)
198 {
199 int nvals = SIMD_NVALS[fmt];
200 int32_t result;
201 uint64_t a_values[SIMD_MAX_VALS];
202 uint64_t b_values[SIMD_MAX_VALS];
203
204 simdUnpack(a, a_values, fmt, sign);
205 simdUnpack(b, b_values, fmt, sign);
206
207 for (int i = 0; i < nvals; i++) {
208 if (round)
209 a_values[i] = addHalfLsb(a_values[i] + b_values[i], 1) >> 1;
210 else
211 a_values[i] = (a_values[i] + b_values[i]) >> 1;
212 }
213
214 simdPack(a_values, &result, fmt);
215
216 return result;
217 }
218
219 int32_t
220 MipsISA::dspSub(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
221 int32_t sign, uint32_t *dspctl)
222 {
223 int nvals = SIMD_NVALS[fmt];
224 int32_t result;
225 uint32_t ouflag = 0;
226 uint64_t a_values[SIMD_MAX_VALS];
227 uint64_t b_values[SIMD_MAX_VALS];
228
229 simdUnpack(a, a_values, fmt, sign);
230 simdUnpack(b, b_values, fmt, sign);
231
232 for (int i = 0; i < nvals; i++) {
233 if (saturate)
234 a_values[i] = dspSaturate(a_values[i] - b_values[i], fmt, sign,
235 &ouflag);
236 else
237 a_values[i] = checkOverflow(a_values[i] - b_values[i], fmt, sign,
238 &ouflag);
239 }
240
241 simdPack(a_values, &result, fmt);
242
243 if (ouflag)
244 writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG],
245 1 << DSP_OUFLAG);
246
247 return result;
248 }
249
250 int32_t
251 MipsISA::dspSubh(int32_t a, int32_t b, int32_t fmt, int32_t round,
252 int32_t sign)
253 {
254 int nvals = SIMD_NVALS[fmt];
255 int32_t result;
256 uint64_t a_values[SIMD_MAX_VALS];
257 uint64_t b_values[SIMD_MAX_VALS];
258
259 simdUnpack(a, a_values, fmt, sign);
260 simdUnpack(b, b_values, fmt, sign);
261
262 for (int i = 0; i < nvals; i++)
263 {
264 if (round)
265 a_values[i] = addHalfLsb(a_values[i] - b_values[i], 1) >> 1;
266 else
267 a_values[i] = (a_values[i] - b_values[i]) >> 1;
268 }
269
270 simdPack(a_values, &result, fmt);
271
272 return result;
273 }
274
275 int32_t
276 MipsISA::dspShll(int32_t a, uint32_t sa, int32_t fmt, int32_t saturate,
277 int32_t sign, uint32_t *dspctl)
278 {
279 int nvals = SIMD_NVALS[fmt];
280 int32_t result;
281 uint32_t ouflag = 0;
282 uint64_t a_values[SIMD_MAX_VALS];
283
284 sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0);
285 simdUnpack(a, a_values, fmt, sign);
286
287 for (int i = 0; i < nvals; i++)
288 {
289 if (saturate)
290 a_values[i] = dspSaturate(a_values[i] << sa, fmt, sign, &ouflag);
291 else
292 a_values[i] = checkOverflow(a_values[i] << sa, fmt, sign, &ouflag);
293 }
294
295 simdPack(a_values, &result, fmt);
296
297 if (ouflag)
298 writeDSPControl(dspctl, (ouflag << 6) << DSP_CTL_POS[DSP_OUFLAG],
299 1 << DSP_OUFLAG);
300
301 return result;
302 }
303
304 int32_t
305 MipsISA::dspShrl(int32_t a, uint32_t sa, int32_t fmt, int32_t sign)
306 {
307 int nvals = SIMD_NVALS[fmt];
308 int32_t result;
309 uint64_t a_values[SIMD_MAX_VALS];
310
311 sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0);
312
313 simdUnpack(a, a_values, fmt, UNSIGNED);
314
315 for (int i = 0; i < nvals; i++)
316 a_values[i] = a_values[i] >> sa;
317
318 simdPack(a_values, &result, fmt);
319
320 return result;
321 }
322
323 int32_t
324 MipsISA::dspShra(int32_t a, uint32_t sa, int32_t fmt, int32_t round,
325 int32_t sign, uint32_t *dspctl)
326 {
327 int nvals = SIMD_NVALS[fmt];
328 int32_t result;
329 uint64_t a_values[SIMD_MAX_VALS];
330
331 sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0);
332
333 simdUnpack(a, a_values, fmt, SIGNED);
334
335 for (int i = 0; i < nvals; i++) {
336 if (round)
337 a_values[i] = addHalfLsb(a_values[i], sa) >> sa;
338 else
339 a_values[i] = a_values[i] >> sa;
340 }
341
342 simdPack(a_values, &result, fmt);
343
344 return result;
345 }
346
347 int32_t
348 MipsISA::dspMulq(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
349 int32_t round, uint32_t *dspctl)
350 {
351 int nvals = SIMD_NVALS[fmt];
352 int sa = SIMD_NBITS[fmt];
353 int32_t result;
354 uint32_t ouflag = 0;
355 uint64_t a_values[SIMD_MAX_VALS];
356 uint64_t b_values[SIMD_MAX_VALS];
357 int64_t temp;
358
359 simdUnpack(a, a_values, fmt, SIGNED);
360 simdUnpack(b, b_values, fmt, SIGNED);
361
362 for (int i = 0; i < nvals; i++) {
363 if (round)
364 temp =
365 (int64_t)addHalfLsb(a_values[i] * b_values[i] << 1, sa) >> sa;
366 else
367 temp = (int64_t)(a_values[i] * b_values[i]) >> (sa - 1);
368
369 if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) {
370 ouflag = 1;
371
372 if (saturate)
373 temp = FIXED_SMAX[fmt];
374 }
375
376 a_values[i] = temp;
377 }
378
379 simdPack(a_values, &result, fmt);
380
381 if (ouflag)
382 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
383 1 << DSP_OUFLAG);
384
385 return result;
386 }
387
388 int32_t
389 MipsISA::dspMul(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
390 uint32_t *dspctl)
391 {
392 int nvals = SIMD_NVALS[fmt];
393 int32_t result;
394 uint32_t ouflag = 0;
395 uint64_t a_values[SIMD_MAX_VALS];
396 uint64_t b_values[SIMD_MAX_VALS];
397
398 simdUnpack(a, a_values, fmt, SIGNED);
399 simdUnpack(b, b_values, fmt, SIGNED);
400
401 for (int i = 0; i < nvals; i++)
402 {
403 if (saturate)
404 a_values[i] = dspSaturate(a_values[i] * b_values[i], fmt, SIGNED,
405 &ouflag);
406 else
407 a_values[i] = checkOverflow(a_values[i] * b_values[i], fmt, SIGNED,
408 &ouflag);
409 }
410
411 simdPack(a_values, &result, fmt);
412
413 if (ouflag)
414 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
415 1 << DSP_OUFLAG);
416
417 return result;
418 }
419
420 int32_t
421 MipsISA::dspMuleu(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl)
422 {
423 int nvals = SIMD_NVALS[SIMD_FMT_PH];
424 int32_t result;
425 uint32_t ouflag = 0;
426 uint64_t a_values[SIMD_MAX_VALS];
427 uint64_t b_values[SIMD_MAX_VALS];
428
429 simdUnpack(a, a_values, SIMD_FMT_QB, UNSIGNED);
430 simdUnpack(b, b_values, SIMD_FMT_PH, UNSIGNED);
431
432 switch (mode) {
433 case MODE_L:
434 for (int i = 0; i < nvals; i++)
435 b_values[i] = dspSaturate(a_values[i + 2] * b_values[i],
436 SIMD_FMT_PH, UNSIGNED, &ouflag);
437 break;
438 case MODE_R:
439 for (int i = 0; i < nvals; i++)
440 b_values[i] = dspSaturate(a_values[i] * b_values[i], SIMD_FMT_PH,
441 UNSIGNED, &ouflag);
442 break;
443 }
444
445 simdPack(b_values, &result, SIMD_FMT_PH);
446
447 if (ouflag)
448 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
449 1 << DSP_OUFLAG);
450
451 return result;
452 }
453
454 int32_t
455 MipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl)
456 {
457 int nvals = SIMD_NVALS[SIMD_FMT_W];
458 int32_t result;
459 uint32_t ouflag = 0;
460 uint64_t a_values[SIMD_MAX_VALS];
461 uint64_t b_values[SIMD_MAX_VALS];
462 uint64_t c_values[SIMD_MAX_VALS];
463
464 memset(c_values, 0, sizeof(c_values));
465
466 simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
467 simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
468
469 switch (mode) {
470 case MODE_L:
471 for (int i = 0; i < nvals; i++)
472 c_values[i] = dspSaturate(a_values[i + 1] * b_values[i + 1] << 1,
473 SIMD_FMT_W, SIGNED, &ouflag);
474 break;
475 case MODE_R:
476 for (int i = 0; i < nvals; i++)
477 c_values[i] = dspSaturate(a_values[i] * b_values[i] << 1,
478 SIMD_FMT_W, SIGNED, &ouflag);
479 break;
480 }
481
482 simdPack(c_values, &result, SIMD_FMT_W);
483
484 if (ouflag)
485 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
486 1 << DSP_OUFLAG);
487
488 return result;
489 }
490
491 int64_t
492 MipsISA::dspDpaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
493 int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode,
494 uint32_t *dspctl)
495 {
496 int nvals = SIMD_NVALS[infmt];
497 int64_t result = 0;
498 int64_t temp = 0;
499 uint32_t ouflag = 0;
500 uint64_t a_values[SIMD_MAX_VALS];
501 uint64_t b_values[SIMD_MAX_VALS];
502
503 simdUnpack(a, a_values, infmt, SIGNED);
504 simdUnpack(b, b_values, infmt, SIGNED);
505
506 for (int i = 0; i < nvals; i++) {
507 switch (mode) {
508 case MODE_X:
509 if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] &&
510 b_values[i] == FIXED_SMIN[infmt]) {
511 result += FIXED_SMAX[outfmt];
512 ouflag = 1;
513 }
514 else
515 result += a_values[nvals - 1 - i] * b_values[i] << 1;
516 break;
517 default:
518 if (a_values[i] == FIXED_SMIN[infmt] &&
519 b_values[i] == FIXED_SMIN[infmt]) {
520 result += FIXED_SMAX[outfmt];
521 ouflag = 1;
522 } else {
523 result += a_values[i] * b_values[i] << 1;
524 }
525 break;
526 }
527 }
528
529 if (postsat) {
530 if (outfmt == SIMD_FMT_L) {
531 int signa = bits(dspac, 63, 63);
532 int signb = bits(result, 63, 63);
533
534 temp = dspac + result;
535
536 if (signa == signb && bits(temp, 63, 63) != signa) {
537 ouflag = 1;
538 if (signa)
539 dspac = FIXED_SMIN[outfmt];
540 else
541 dspac = FIXED_SMAX[outfmt];
542 } else {
543 dspac = temp;
544 }
545 } else {
546 dspac = dspSaturate(dspac + result, outfmt, SIGNED, &ouflag);
547 }
548 } else {
549 dspac += result;
550 }
551
552 if (ouflag)
553 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
554
555 return dspac;
556 }
557
558 int64_t
559 MipsISA::dspDpsq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
560 int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode,
561 uint32_t *dspctl)
562 {
563 int nvals = SIMD_NVALS[infmt];
564 int64_t result = 0;
565 int64_t temp = 0;
566 uint32_t ouflag = 0;
567 uint64_t a_values[SIMD_MAX_VALS];
568 uint64_t b_values[SIMD_MAX_VALS];
569
570 simdUnpack(a, a_values, infmt, SIGNED);
571 simdUnpack(b, b_values, infmt, SIGNED);
572
573 for (int i = 0; i < nvals; i++) {
574 switch (mode) {
575 case MODE_X:
576 if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] &&
577 b_values[i] == FIXED_SMIN[infmt]) {
578 result += FIXED_SMAX[outfmt];
579 ouflag = 1;
580 } else {
581 result += a_values[nvals - 1 - i] * b_values[i] << 1;
582 }
583 break;
584 default:
585 if (a_values[i] == FIXED_SMIN[infmt] &&
586 b_values[i] == FIXED_SMIN[infmt]) {
587 result += FIXED_SMAX[outfmt];
588 ouflag = 1;
589 } else {
590 result += a_values[i] * b_values[i] << 1;
591 }
592 break;
593 }
594 }
595
596 if (postsat) {
597 if (outfmt == SIMD_FMT_L) {
598 int signa = bits(dspac, 63, 63);
599 int signb = bits(-result, 63, 63);
600
601 temp = dspac - result;
602
603 if (signa == signb && bits(temp, 63, 63) != signa) {
604 ouflag = 1;
605 if (signa)
606 dspac = FIXED_SMIN[outfmt];
607 else
608 dspac = FIXED_SMAX[outfmt];
609 } else {
610 dspac = temp;
611 }
612 } else {
613 dspac = dspSaturate(dspac - result, outfmt, SIGNED, &ouflag);
614 }
615 } else {
616 dspac -= result;
617 }
618
619 if (ouflag)
620 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
621
622 return dspac;
623 }
624
625 int64_t
626 MipsISA::dspDpa(int64_t dspac, int32_t a, int32_t b, int32_t ac,
627 int32_t fmt, int32_t sign, int32_t mode)
628 {
629 int nvals = SIMD_NVALS[fmt];
630 uint64_t a_values[SIMD_MAX_VALS];
631 uint64_t b_values[SIMD_MAX_VALS];
632
633 simdUnpack(a, a_values, fmt, sign);
634 simdUnpack(b, b_values, fmt, sign);
635
636 for (int i = 0; i < 2; i++) {
637 switch (mode) {
638 case MODE_L:
639 dspac += a_values[nvals - 1 - i] * b_values[nvals - 1 - i];
640 break;
641 case MODE_R:
642 dspac += a_values[nvals - 3 - i] * b_values[nvals - 3 - i];
643 break;
644 case MODE_X:
645 dspac += a_values[nvals - 1 - i] * b_values[i];
646 break;
647 }
648 }
649
650 return dspac;
651 }
652
653 int64_t
654 MipsISA::dspDps(int64_t dspac, int32_t a, int32_t b, int32_t ac,
655 int32_t fmt, int32_t sign, int32_t mode)
656 {
657 int nvals = SIMD_NVALS[fmt];
658 uint64_t a_values[SIMD_MAX_VALS];
659 uint64_t b_values[SIMD_MAX_VALS];
660
661 simdUnpack(a, a_values, fmt, sign);
662 simdUnpack(b, b_values, fmt, sign);
663
664 for (int i = 0; i < 2; i++) {
665 switch (mode) {
666 case MODE_L:
667 dspac -= a_values[nvals - 1 - i] * b_values[nvals - 1 - i];
668 break;
669 case MODE_R:
670 dspac -= a_values[nvals - 3 - i] * b_values[nvals - 3 - i];
671 break;
672 case MODE_X:
673 dspac -= a_values[nvals - 1 - i] * b_values[i];
674 break;
675 }
676 }
677
678 return dspac;
679 }
680
681 int64_t
682 MipsISA::dspMaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
683 int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl)
684 {
685 int nvals = SIMD_NVALS[fmt - 1];
686 uint64_t a_values[SIMD_MAX_VALS];
687 uint64_t b_values[SIMD_MAX_VALS];
688 int64_t temp = 0;
689 uint32_t ouflag = 0;
690
691 simdUnpack(a, a_values, fmt, SIGNED);
692 simdUnpack(b, b_values, fmt, SIGNED);
693
694 for (int i = 0; i < nvals; i++) {
695 switch (mode) {
696 case MODE_L:
697 temp = a_values[i + 1] * b_values[i + 1] << 1;
698 if (a_values[i + 1] == FIXED_SMIN[fmt] &&
699 b_values[i + 1] == FIXED_SMIN[fmt]) {
700 temp = (int64_t)FIXED_SMAX[fmt - 1];
701 ouflag = 1;
702 }
703 break;
704 case MODE_R:
705 temp = a_values[i] * b_values[i] << 1;
706 if (a_values[i] == FIXED_SMIN[fmt] &&
707 b_values[i] == FIXED_SMIN[fmt]) {
708 temp = (int64_t)FIXED_SMAX[fmt - 1];
709 ouflag = 1;
710 }
711 break;
712 }
713
714 temp += dspac;
715
716 if (saturate)
717 temp = dspSaturate(temp, fmt - 1, SIGNED, &ouflag);
718 if (ouflag)
719 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
720 }
721
722 return temp;
723 }
724
725 int64_t
726 MipsISA::dspMulsa(int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt)
727 {
728 uint64_t a_values[SIMD_MAX_VALS];
729 uint64_t b_values[SIMD_MAX_VALS];
730
731 simdUnpack(a, a_values, fmt, SIGNED);
732 simdUnpack(b, b_values, fmt, SIGNED);
733
734 dspac += a_values[1] * b_values[1] - a_values[0] * b_values[0];
735
736 return dspac;
737 }
738
739 int64_t
740 MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
741 int32_t fmt, uint32_t *dspctl)
742 {
743 int nvals = SIMD_NVALS[fmt];
744 uint64_t a_values[SIMD_MAX_VALS];
745 uint64_t b_values[SIMD_MAX_VALS];
746 int64_t temp[2] = {0, 0};
747 uint32_t ouflag = 0;
748
749 simdUnpack(a, a_values, fmt, SIGNED);
750 simdUnpack(b, b_values, fmt, SIGNED);
751
752 for (int i = nvals - 1; i > -1; i--) {
753 temp[i] = a_values[i] * b_values[i] << 1;
754 if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) {
755 temp[i] = FIXED_SMAX[fmt - 1];
756 ouflag = 1;
757 }
758 }
759
760 dspac += temp[1] - temp[0];
761
762 if (ouflag)
763 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
764
765 return dspac;
766 }
767
768 void
769 MipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op,
770 uint32_t *dspctl)
771 {
772 int nvals = SIMD_NVALS[fmt];
773 int ccond = 0;
774 uint64_t a_values[SIMD_MAX_VALS];
775 uint64_t b_values[SIMD_MAX_VALS];
776
777 simdUnpack(a, a_values, fmt, sign);
778 simdUnpack(b, b_values, fmt, sign);
779
780 for (int i = 0; i < nvals; i++) {
781 int cc = 0;
782
783 switch (op) {
784 case CMP_EQ:
785 cc = (a_values[i] == b_values[i]);
786 break;
787 case CMP_LT:
788 cc = (a_values[i] < b_values[i]);
789 break;
790 case CMP_LE:
791 cc = (a_values[i] <= b_values[i]);
792 break;
793 }
794
795 ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i);
796 }
797
798 writeDSPControl(dspctl, ccond, 1 << DSP_CCOND);
799 }
800
801 int32_t
802 MipsISA::dspCmpg(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op)
803 {
804 int nvals = SIMD_NVALS[fmt];
805 int32_t result = 0;
806 uint64_t a_values[SIMD_MAX_VALS];
807 uint64_t b_values[SIMD_MAX_VALS];
808
809 simdUnpack(a, a_values, fmt, sign);
810 simdUnpack(b, b_values, fmt, sign);
811
812 for (int i = 0; i < nvals; i++) {
813 int cc = 0;
814
815 switch (op) {
816 case CMP_EQ:
817 cc = (a_values[i] == b_values[i]);
818 break;
819 case CMP_LT:
820 cc = (a_values[i] < b_values[i]);
821 break;
822 case CMP_LE:
823 cc = (a_values[i] <= b_values[i]);
824 break;
825 }
826
827 result |= cc << i;
828 }
829
830 return result;
831 }
832
833 int32_t
834 MipsISA::dspCmpgd(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op,
835 uint32_t *dspctl)
836 {
837 int nvals = SIMD_NVALS[fmt];
838 int32_t result = 0;
839 int ccond = 0;
840 uint64_t a_values[SIMD_MAX_VALS];
841 uint64_t b_values[SIMD_MAX_VALS];
842
843 simdUnpack(a, a_values, fmt, sign);
844 simdUnpack(b, b_values, fmt, sign);
845
846 for (int i = 0; i < nvals; i++) {
847 int cc = 0;
848
849 switch (op) {
850 case CMP_EQ:
851 cc = (a_values[i] == b_values[i]);
852 break;
853 case CMP_LT:
854 cc = (a_values[i] < b_values[i]);
855 break;
856 case CMP_LE:
857 cc = (a_values[i] <= b_values[i]);
858 break;
859 }
860
861 result |= cc << i;
862 ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i);
863 }
864
865 writeDSPControl(dspctl, ccond, 1 << DSP_CCOND);
866
867 return result;
868 }
869
870 int32_t
871 MipsISA::dspPrece(int32_t a, int32_t infmt, int32_t insign, int32_t outfmt,
872 int32_t outsign, int32_t mode)
873 {
874 int sa = 0;
875 int ninvals = SIMD_NVALS[infmt];
876 int noutvals = SIMD_NVALS[outfmt];
877 int32_t result;
878 uint64_t in_values[SIMD_MAX_VALS];
879 uint64_t out_values[SIMD_MAX_VALS];
880
881 if (insign == SIGNED && outsign == SIGNED)
882 sa = SIMD_NBITS[infmt];
883 else if (insign == UNSIGNED && outsign == SIGNED)
884 sa = SIMD_NBITS[infmt] - 1;
885 else if (insign == UNSIGNED && outsign == UNSIGNED)
886 sa = 0;
887
888 simdUnpack(a, in_values, infmt, insign);
889
890 for (int i = 0; i<noutvals; i++) {
891 switch (mode) {
892 case MODE_L:
893 out_values[i] = in_values[i + (ninvals >> 1)] << sa;
894 break;
895 case MODE_R:
896 out_values[i] = in_values[i] << sa;
897 break;
898 case MODE_LA:
899 out_values[i] = in_values[(i << 1) + 1] << sa;
900 break;
901 case MODE_RA:
902 out_values[i] = in_values[i << 1] << sa;
903 break;
904 }
905 }
906
907 simdPack(out_values, &result, outfmt);
908
909 return result;
910 }
911
912 int32_t
913 MipsISA::dspPrecrqu(int32_t a, int32_t b, uint32_t *dspctl)
914 {
915 uint64_t a_values[SIMD_MAX_VALS];
916 uint64_t b_values[SIMD_MAX_VALS];
917 uint64_t r_values[SIMD_MAX_VALS];
918 uint32_t ouflag = 0;
919 int32_t result = 0;
920
921 simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
922 simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
923
924 for (int i = 0; i<2; i++) {
925 r_values[i] =
926 dspSaturate((int64_t)b_values[i] >> (SIMD_NBITS[SIMD_FMT_QB] - 1),
927 SIMD_FMT_QB, UNSIGNED, &ouflag);
928 r_values[i + 2] =
929 dspSaturate((int64_t)a_values[i] >> (SIMD_NBITS[SIMD_FMT_QB] - 1),
930 SIMD_FMT_QB, UNSIGNED, &ouflag);
931 }
932
933 simdPack(r_values, &result, SIMD_FMT_QB);
934
935 if (ouflag)
936 *dspctl = insertBits(*dspctl, 22, 22, 1);
937
938 return result;
939 }
940
941 int32_t
942 MipsISA::dspPrecrq(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl)
943 {
944 uint64_t a_values[SIMD_MAX_VALS];
945 uint64_t b_values[SIMD_MAX_VALS];
946 uint64_t r_values[SIMD_MAX_VALS];
947 uint32_t ouflag = 0;
948 int32_t result;
949
950 simdUnpack(a, a_values, fmt, SIGNED);
951 simdUnpack(b, b_values, fmt, SIGNED);
952
953 r_values[1] = dspSaturate((int64_t)addHalfLsb(a_values[0], 16) >> 16,
954 fmt + 1, SIGNED, &ouflag);
955 r_values[0] = dspSaturate((int64_t)addHalfLsb(b_values[0], 16) >> 16,
956 fmt + 1, SIGNED, &ouflag);
957
958 simdPack(r_values, &result, fmt + 1);
959
960 if (ouflag)
961 *dspctl = insertBits(*dspctl, 22, 22, 1);
962
963 return result;
964 }
965
966 int32_t
967 MipsISA::dspPrecrSra(int32_t a, int32_t b, int32_t sa, int32_t fmt,
968 int32_t round)
969 {
970 int nvals = SIMD_NVALS[fmt];
971 uint64_t a_values[SIMD_MAX_VALS];
972 uint64_t b_values[SIMD_MAX_VALS];
973 uint64_t c_values[SIMD_MAX_VALS];
974 int32_t result = 0;
975
976 simdUnpack(a, a_values, fmt, SIGNED);
977 simdUnpack(b, b_values, fmt, SIGNED);
978
979 for (int i = 0; i < nvals; i++) {
980 if (round) {
981 c_values[i] = addHalfLsb(b_values[i], sa) >> sa;
982 c_values[i + 1] = addHalfLsb(a_values[i], sa) >> sa;
983 } else {
984 c_values[i] = b_values[i] >> sa;
985 c_values[i + 1] = a_values[i] >> sa;
986 }
987 }
988
989 simdPack(c_values, &result, fmt + 1);
990
991 return result;
992 }
993
994 int32_t
995 MipsISA::dspPick(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl)
996 {
997 int nvals = SIMD_NVALS[fmt];
998 int32_t result;
999 uint64_t a_values[SIMD_MAX_VALS];
1000 uint64_t b_values[SIMD_MAX_VALS];
1001 uint64_t c_values[SIMD_MAX_VALS];
1002
1003 simdUnpack(a, a_values, fmt, UNSIGNED);
1004 simdUnpack(b, b_values, fmt, UNSIGNED);
1005
1006 for (int i = 0; i < nvals; i++) {
1007 int condbit = DSP_CTL_POS[DSP_CCOND] + i;
1008 if (bits(*dspctl, condbit, condbit) == 1)
1009 c_values[i] = a_values[i];
1010 else
1011 c_values[i] = b_values[i];
1012 }
1013
1014 simdPack(c_values, &result, fmt);
1015
1016 return result;
1017 }
1018
1019 int32_t
1020 MipsISA::dspPack(int32_t a, int32_t b, int32_t fmt)
1021 {
1022 int32_t result;
1023 uint64_t a_values[SIMD_MAX_VALS];
1024 uint64_t b_values[SIMD_MAX_VALS];
1025 uint64_t c_values[SIMD_MAX_VALS];
1026
1027 simdUnpack(a, a_values, fmt, UNSIGNED);
1028 simdUnpack(b, b_values, fmt, UNSIGNED);
1029
1030 c_values[0] = b_values[1];
1031 c_values[1] = a_values[0];
1032
1033 simdPack(c_values, &result, fmt);
1034
1035 return result;
1036 }
1037
1038 int32_t
1039 MipsISA::dspExtr(int64_t dspac, int32_t fmt, int32_t sa, int32_t round,
1040 int32_t saturate, uint32_t *dspctl)
1041 {
1042 int32_t result = 0;
1043 uint32_t ouflag = 0;
1044 int64_t temp = 0;
1045
1046 sa = bits(sa, 4, 0);
1047
1048 if (sa > 0) {
1049 if (round) {
1050 temp = (int64_t)addHalfLsb(dspac, sa);
1051
1052 if (dspac > 0 && temp < 0) {
1053 ouflag = 1;
1054 if (saturate)
1055 temp = FIXED_SMAX[SIMD_FMT_L];
1056 }
1057 temp = temp >> sa;
1058 } else {
1059 temp = dspac >> sa;
1060 }
1061 } else {
1062 temp = dspac;
1063 }
1064
1065 dspac = checkOverflow(dspac, fmt, SIGNED, &ouflag);
1066
1067 if (ouflag) {
1068 *dspctl = insertBits(*dspctl, 23, 23, ouflag);
1069
1070 if (saturate)
1071 result = (int32_t)dspSaturate(temp, fmt, SIGNED, &ouflag);
1072 else
1073 result = (int32_t)temp;
1074 } else {
1075 result = (int32_t)temp;
1076 }
1077
1078 return result;
1079 }
1080
1081 int32_t
1082 MipsISA::dspExtp(int64_t dspac, int32_t size, uint32_t *dspctl)
1083 {
1084 int32_t pos = 0;
1085 int32_t result = 0;
1086
1087 pos = bits(*dspctl, 5, 0);
1088 size = bits(size, 4, 0);
1089
1090 if (pos - (size + 1) >= -1) {
1091 result = bits(dspac, pos, pos - size);
1092 *dspctl = insertBits(*dspctl, 14, 14, 0);
1093 } else {
1094 result = 0;
1095 *dspctl = insertBits(*dspctl, 14, 14, 1);
1096 }
1097
1098 return result;
1099 }
1100
1101 int32_t
1102 MipsISA::dspExtpd(int64_t dspac, int32_t size, uint32_t *dspctl)
1103 {
1104 int32_t pos = 0;
1105 int32_t result = 0;
1106
1107 pos = bits(*dspctl, 5, 0);
1108 size = bits(size, 4, 0);
1109
1110 if (pos - (size + 1) >= -1) {
1111 result = bits(dspac, pos, pos - size);
1112 *dspctl = insertBits(*dspctl, 14, 14, 0);
1113 if (pos - (size + 1) >= 0)
1114 *dspctl = insertBits(*dspctl, 5, 0, pos - (size + 1));
1115 else if ((pos - (size + 1)) == -1)
1116 *dspctl = insertBits(*dspctl, 5, 0, 63);
1117 } else {
1118 result = 0;
1119 *dspctl = insertBits(*dspctl, 14, 14, 1);
1120 }
1121
1122 return result;
1123 }
1124
1125 void
1126 MipsISA::simdPack(uint64_t *values_ptr, int32_t *reg, int32_t fmt)
1127 {
1128 int nvals = SIMD_NVALS[fmt];
1129 int nbits = SIMD_NBITS[fmt];
1130
1131 *reg = 0;
1132
1133 for (int i = 0; i < nvals; i++)
1134 *reg |= (int32_t)bits(values_ptr[i], nbits - 1, 0) << nbits * i;
1135 }
1136
1137 void
1138 MipsISA::simdUnpack(int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign)
1139 {
1140 int nvals = SIMD_NVALS[fmt];
1141 int nbits = SIMD_NBITS[fmt];
1142
1143 switch (sign) {
1144 case SIGNED:
1145 for (int i = 0; i < nvals; i++) {
1146 uint64_t tmp = (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i);
1147 values_ptr[i] = signExtend(tmp, fmt);
1148 }
1149 break;
1150 case UNSIGNED:
1151 for (int i = 0; i < nvals; i++) {
1152 values_ptr[i] =
1153 (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i);
1154 }
1155 break;
1156 }
1157 }
1158
1159 void
1160 MipsISA::writeDSPControl(uint32_t *dspctl, uint32_t value, uint32_t mask)
1161 {
1162 uint32_t fmask = 0;
1163
1164 if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS];
1165 if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT];
1166 if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C];
1167 if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG];
1168 if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND];
1169 if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI];
1170
1171 *dspctl &= ~fmask;
1172 value &= fmask;
1173 *dspctl |= value;
1174 }
1175
1176 uint32_t
1177 MipsISA::readDSPControl(uint32_t *dspctl, uint32_t mask)
1178 {
1179 uint32_t fmask = 0;
1180
1181 if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS];
1182 if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT];
1183 if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C];
1184 if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG];
1185 if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND];
1186 if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI];
1187
1188 return *dspctl & fmask;
1189 }