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