dsp.cc revision 8794:e2ac2b7164dd
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}
1191