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