dsp.cc revision 5563:4c4b5dfc9944
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/isa_traits.hh"
32#include "arch/mips/dsp.hh"
33#include "config/full_system.hh"
34#include "cpu/static_inst.hh"
35#include "sim/serialize.hh"
36#include "base/bitfield.hh"
37#include "base/misc.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    simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
467    simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
468
469    switch (mode) {
470      case MODE_L:
471        for (int i = 0; i < nvals; i++)
472            c_values[i] = dspSaturate(a_values[i + 1] * b_values[i + 1] << 1,
473                                       SIMD_FMT_W, SIGNED, &ouflag);
474        break;
475      case MODE_R:
476        for (int i = 0; i < nvals; i++)
477            c_values[i] = dspSaturate(a_values[i] * b_values[i] << 1,
478                                       SIMD_FMT_W, SIGNED, &ouflag);
479        break;
480    }
481
482    simdPack(c_values, &result, SIMD_FMT_W);
483
484    if (ouflag)
485        writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
486                        1 << DSP_OUFLAG);
487
488    return result;
489}
490
491int64_t
492MipsISA::dspDpaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
493    int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode,
494    uint32_t *dspctl)
495{
496    int nvals = SIMD_NVALS[infmt];
497    int64_t result = 0;
498    int64_t temp = 0;
499    uint32_t ouflag = 0;
500    uint64_t a_values[SIMD_MAX_VALS];
501    uint64_t b_values[SIMD_MAX_VALS];
502
503    simdUnpack(a, a_values, infmt, SIGNED);
504    simdUnpack(b, b_values, infmt, SIGNED);
505
506    for (int i = 0; i < nvals; i++) {
507        switch (mode) {
508          case MODE_X:
509            if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] &&
510                b_values[i] == FIXED_SMIN[infmt]) {
511                result += FIXED_SMAX[outfmt];
512                ouflag = 1;
513            }
514            else
515                result += a_values[nvals - 1 - i] * b_values[i] << 1;
516            break;
517          default:
518            if (a_values[i] == FIXED_SMIN[infmt] &&
519                b_values[i] == FIXED_SMIN[infmt]) {
520                result += FIXED_SMAX[outfmt];
521                ouflag = 1;
522            } else {
523                result += a_values[i] * b_values[i] << 1;
524            }
525            break;
526        }
527    }
528
529    if (postsat) {
530        if (outfmt == SIMD_FMT_L) {
531            int signa = bits(dspac, 63, 63);
532            int signb = bits(result, 63, 63);
533
534            temp = dspac + result;
535
536            if (signa == signb && bits(temp, 63, 63) != signa) {
537                ouflag = 1;
538                if (signa)
539                    dspac = FIXED_SMIN[outfmt];
540                else
541                    dspac = FIXED_SMAX[outfmt];
542            } else {
543                dspac = temp;
544            }
545        } else {
546            dspac = dspSaturate(dspac + result, outfmt, SIGNED, &ouflag);
547        }
548    } else {
549        dspac += result;
550    }
551
552    if (ouflag)
553        *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
554
555    return dspac;
556}
557
558int64_t
559MipsISA::dspDpsq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
560    int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode,
561    uint32_t *dspctl)
562{
563    int nvals = SIMD_NVALS[infmt];
564    int64_t result = 0;
565    int64_t temp = 0;
566    uint32_t ouflag = 0;
567    uint64_t a_values[SIMD_MAX_VALS];
568    uint64_t b_values[SIMD_MAX_VALS];
569
570    simdUnpack(a, a_values, infmt, SIGNED);
571    simdUnpack(b, b_values, infmt, SIGNED);
572
573    for (int i = 0; i < nvals; i++) {
574        switch (mode) {
575          case MODE_X:
576            if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] &&
577                b_values[i] == FIXED_SMIN[infmt]) {
578                result += FIXED_SMAX[outfmt];
579                ouflag = 1;
580            } else {
581                result += a_values[nvals - 1 - i] * b_values[i] << 1;
582            }
583            break;
584          default:
585            if (a_values[i] == FIXED_SMIN[infmt] &&
586                b_values[i] == FIXED_SMIN[infmt]) {
587                result += FIXED_SMAX[outfmt];
588                ouflag = 1;
589            } else {
590                result += a_values[i] * b_values[i] << 1;
591            }
592            break;
593        }
594    }
595
596    if (postsat) {
597        if (outfmt == SIMD_FMT_L) {
598            int signa = bits(dspac, 63, 63);
599            int signb = bits(-result, 63, 63);
600
601            temp = dspac - result;
602
603            if (signa == signb && bits(temp, 63, 63) != signa) {
604                ouflag = 1;
605                if (signa)
606                    dspac = FIXED_SMIN[outfmt];
607                else
608                    dspac = FIXED_SMAX[outfmt];
609            } else {
610                dspac = temp;
611            }
612        } else {
613            dspac = dspSaturate(dspac - result, outfmt, SIGNED, &ouflag);
614        }
615    } else {
616        dspac -= result;
617    }
618
619    if (ouflag)
620        *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
621
622    return dspac;
623}
624
625int64_t
626MipsISA::dspDpa(int64_t dspac, int32_t a, int32_t b, int32_t ac,
627                int32_t fmt, int32_t sign, int32_t mode)
628{
629    int nvals = SIMD_NVALS[fmt];
630    uint64_t a_values[SIMD_MAX_VALS];
631    uint64_t b_values[SIMD_MAX_VALS];
632
633    simdUnpack(a, a_values, fmt, sign);
634    simdUnpack(b, b_values, fmt, sign);
635
636    for (int i = 0; i < 2; i++) {
637        switch (mode) {
638          case MODE_L:
639            dspac += a_values[nvals - 1 - i] * b_values[nvals - 1 - i];
640            break;
641          case MODE_R:
642            dspac += a_values[nvals - 3 - i] * b_values[nvals - 3 - i];
643            break;
644          case MODE_X:
645            dspac += a_values[nvals - 1 - i] * b_values[i];
646            break;
647        }
648    }
649
650    return dspac;
651}
652
653int64_t
654MipsISA::dspDps(int64_t dspac, int32_t a, int32_t b, int32_t ac,
655                int32_t fmt, int32_t sign, int32_t mode)
656{
657    int nvals = SIMD_NVALS[fmt];
658    uint64_t a_values[SIMD_MAX_VALS];
659    uint64_t b_values[SIMD_MAX_VALS];
660
661    simdUnpack(a, a_values, fmt, sign);
662    simdUnpack(b, b_values, fmt, sign);
663
664    for (int i = 0; i < 2; i++) {
665        switch (mode) {
666          case MODE_L:
667            dspac -= a_values[nvals - 1 - i] * b_values[nvals - 1 - i];
668            break;
669          case MODE_R:
670            dspac -= a_values[nvals - 3 - i] * b_values[nvals - 3 - i];
671            break;
672          case MODE_X:
673            dspac -= a_values[nvals - 1 - i] * b_values[i];
674            break;
675        }
676    }
677
678    return dspac;
679}
680
681int64_t
682MipsISA::dspMaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
683                 int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl)
684{
685    int nvals = SIMD_NVALS[fmt - 1];
686    uint64_t a_values[SIMD_MAX_VALS];
687    uint64_t b_values[SIMD_MAX_VALS];
688    int64_t temp = 0;
689    uint32_t ouflag = 0;
690
691    simdUnpack(a, a_values, fmt, SIGNED);
692    simdUnpack(b, b_values, fmt, SIGNED);
693
694    for (int i = 0; i < nvals; i++) {
695        switch (mode) {
696          case MODE_L:
697            temp = a_values[i + 1] * b_values[i + 1] << 1;
698            if (a_values[i + 1] == FIXED_SMIN[fmt] &&
699                b_values[i + 1] == FIXED_SMIN[fmt]) {
700                temp = (int64_t)FIXED_SMAX[fmt - 1];
701                ouflag = 1;
702            }
703            break;
704          case MODE_R:
705            temp = a_values[i] * b_values[i] << 1;
706            if (a_values[i] == FIXED_SMIN[fmt] &&
707                b_values[i] == FIXED_SMIN[fmt]) {
708                temp = (int64_t)FIXED_SMAX[fmt - 1];
709                ouflag = 1;
710            }
711            break;
712        }
713
714        temp += dspac;
715
716        if (saturate)
717            temp = dspSaturate(temp, fmt - 1, SIGNED, &ouflag);
718        if (ouflag)
719            *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
720    }
721
722    return temp;
723}
724
725int64_t
726MipsISA::dspMulsa(int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt)
727{
728    uint64_t a_values[SIMD_MAX_VALS];
729    uint64_t b_values[SIMD_MAX_VALS];
730
731    simdUnpack(a, a_values, fmt, SIGNED);
732    simdUnpack(b, b_values, fmt, SIGNED);
733
734    dspac += a_values[1] * b_values[1] - a_values[0] * b_values[0];
735
736    return dspac;
737}
738
739int64_t
740MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
741    int32_t fmt, uint32_t *dspctl)
742{
743    int nvals = SIMD_NVALS[fmt];
744    uint64_t a_values[SIMD_MAX_VALS];
745    uint64_t b_values[SIMD_MAX_VALS];
746    int64_t temp[2];
747    uint32_t ouflag = 0;
748
749    simdUnpack(a, a_values, fmt, SIGNED);
750    simdUnpack(b, b_values, fmt, SIGNED);
751
752    for (int i = nvals - 1; i > -1; i--) {
753        temp[i] = a_values[i] * b_values[i] << 1;
754        if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) {
755            temp[i] = FIXED_SMAX[fmt - 1];
756            ouflag = 1;
757        }
758    }
759
760    dspac += temp[1] - temp[0];
761
762    if (ouflag)
763        *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
764
765    return dspac;
766}
767
768void
769MipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op,
770    uint32_t *dspctl)
771{
772    int nvals = SIMD_NVALS[fmt];
773    int ccond = 0;
774    uint64_t a_values[SIMD_MAX_VALS];
775    uint64_t b_values[SIMD_MAX_VALS];
776
777    simdUnpack(a, a_values, fmt, sign);
778    simdUnpack(b, b_values, fmt, sign);
779
780    for (int i = 0; i < nvals; i++) {
781        int cc = 0;
782
783        switch (op) {
784          case CMP_EQ:
785            cc = (a_values[i] == b_values[i]);
786            break;
787          case CMP_LT:
788            cc = (a_values[i] < b_values[i]);
789            break;
790          case CMP_LE:
791            cc = (a_values[i] <= b_values[i]);
792            break;
793        }
794
795        ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i);
796    }
797
798    writeDSPControl(dspctl, ccond, 1 << DSP_CCOND);
799}
800
801int32_t
802MipsISA::dspCmpg(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op)
803{
804    int nvals = SIMD_NVALS[fmt];
805    int32_t result = 0;
806    uint64_t a_values[SIMD_MAX_VALS];
807    uint64_t b_values[SIMD_MAX_VALS];
808
809    simdUnpack(a, a_values, fmt, sign);
810    simdUnpack(b, b_values, fmt, sign);
811
812    for (int i = 0; i < nvals; i++) {
813        int cc = 0;
814
815        switch (op) {
816          case CMP_EQ:
817            cc = (a_values[i] == b_values[i]);
818            break;
819          case CMP_LT:
820            cc = (a_values[i] < b_values[i]);
821            break;
822          case CMP_LE:
823            cc = (a_values[i] <= b_values[i]);
824            break;
825        }
826
827        result |= cc << i;
828    }
829
830    return result;
831}
832
833int32_t
834MipsISA::dspCmpgd(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op,
835    uint32_t *dspctl)
836{
837    int nvals = SIMD_NVALS[fmt];
838    int32_t result = 0;
839    int ccond = 0;
840    uint64_t a_values[SIMD_MAX_VALS];
841    uint64_t b_values[SIMD_MAX_VALS];
842
843    simdUnpack(a, a_values, fmt, sign);
844    simdUnpack(b, b_values, fmt, sign);
845
846    for (int i = 0; i < nvals; i++) {
847        int cc = 0;
848
849        switch (op) {
850          case CMP_EQ:
851            cc = (a_values[i] == b_values[i]);
852            break;
853          case CMP_LT:
854            cc = (a_values[i] < b_values[i]);
855            break;
856          case CMP_LE:
857            cc = (a_values[i] <= b_values[i]);
858            break;
859        }
860
861        result |= cc << i;
862        ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i);
863    }
864
865    writeDSPControl(dspctl, ccond, 1 << DSP_CCOND);
866
867    return result;
868}
869
870int32_t
871MipsISA::dspPrece(int32_t a, int32_t infmt, int32_t insign, int32_t outfmt,
872    int32_t outsign, int32_t mode)
873{
874    int sa = 0;
875    int ninvals = SIMD_NVALS[infmt];
876    int noutvals = SIMD_NVALS[outfmt];
877    int32_t result;
878    uint64_t in_values[SIMD_MAX_VALS];
879    uint64_t out_values[SIMD_MAX_VALS];
880
881    if (insign == SIGNED && outsign == SIGNED)
882      sa = SIMD_NBITS[infmt];
883    else if (insign == UNSIGNED && outsign == SIGNED)
884      sa = SIMD_NBITS[infmt] - 1;
885    else if (insign == UNSIGNED && outsign == UNSIGNED)
886      sa = 0;
887
888    simdUnpack(a, in_values, infmt, insign);
889
890    for (int i = 0; i<noutvals; i++) {
891        switch (mode) {
892          case MODE_L:
893            out_values[i] = in_values[i + (ninvals >> 1)] << sa;
894            break;
895          case MODE_R:
896            out_values[i] = in_values[i] << sa;
897            break;
898          case MODE_LA:
899            out_values[i] = in_values[(i << 1) + 1] << sa;
900            break;
901          case MODE_RA:
902            out_values[i] = in_values[i << 1] << sa;
903            break;
904        }
905    }
906
907    simdPack(out_values, &result, outfmt);
908
909    return result;
910}
911
912int32_t
913MipsISA::dspPrecrqu(int32_t a, int32_t b, uint32_t *dspctl)
914{
915    uint64_t a_values[SIMD_MAX_VALS];
916    uint64_t b_values[SIMD_MAX_VALS];
917    uint64_t r_values[SIMD_MAX_VALS];
918    uint32_t ouflag = 0;
919    int32_t result = 0;
920
921    simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
922    simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
923
924    for (int i = 0; i<2; i++) {
925        r_values[i] =
926            dspSaturate((int64_t)b_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1,
927                        SIMD_FMT_QB, UNSIGNED, &ouflag);
928        r_values[i + 2] =
929            dspSaturate((int64_t)a_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1,
930                        SIMD_FMT_QB, UNSIGNED, &ouflag);
931    }
932
933    simdPack(r_values, &result, SIMD_FMT_QB);
934
935    if (ouflag)
936        *dspctl = insertBits(*dspctl, 22, 22, 1);
937
938    return result;
939}
940
941int32_t
942MipsISA::dspPrecrq(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl)
943{
944    uint64_t a_values[SIMD_MAX_VALS];
945    uint64_t b_values[SIMD_MAX_VALS];
946    uint64_t r_values[SIMD_MAX_VALS];
947    uint32_t ouflag = 0;
948    int32_t result;
949
950    simdUnpack(a, a_values, fmt, SIGNED);
951    simdUnpack(b, b_values, fmt, SIGNED);
952
953    r_values[1] = dspSaturate((int64_t)addHalfLsb(a_values[0], 16) >> 16,
954                              fmt + 1, SIGNED, &ouflag);
955    r_values[0] = dspSaturate((int64_t)addHalfLsb(b_values[0], 16) >> 16,
956                              fmt + 1, SIGNED, &ouflag);
957
958    simdPack(r_values, &result, fmt + 1);
959
960    if (ouflag)
961        *dspctl = insertBits(*dspctl, 22, 22, 1);
962
963    return result;
964}
965
966int32_t
967MipsISA::dspPrecrSra(int32_t a, int32_t b, int32_t sa, int32_t fmt,
968    int32_t round)
969{
970    int nvals = SIMD_NVALS[fmt];
971    uint64_t a_values[SIMD_MAX_VALS];
972    uint64_t b_values[SIMD_MAX_VALS];
973    uint64_t c_values[SIMD_MAX_VALS];
974    int32_t result = 0;
975
976    simdUnpack(a, a_values, fmt, SIGNED);
977    simdUnpack(b, b_values, fmt, SIGNED);
978
979    for (int i = 0; i < nvals; i++) {
980        if (round) {
981            c_values[i] = addHalfLsb(b_values[i], sa) >> sa;
982            c_values[i + 1] = addHalfLsb(a_values[i], sa) >> sa;
983        } else {
984            c_values[i] = b_values[i] >> sa;
985            c_values[i + 1] = a_values[i] >> sa;
986        }
987    }
988
989    simdPack(c_values, &result, fmt + 1);
990
991    return result;
992}
993
994int32_t
995MipsISA::dspPick(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl)
996{
997    int nvals = SIMD_NVALS[fmt];
998    int32_t result;
999    uint64_t a_values[SIMD_MAX_VALS];
1000    uint64_t b_values[SIMD_MAX_VALS];
1001    uint64_t c_values[SIMD_MAX_VALS];
1002
1003    simdUnpack(a, a_values, fmt, UNSIGNED);
1004    simdUnpack(b, b_values, fmt, UNSIGNED);
1005
1006    for (int i = 0; i < nvals; i++) {
1007        int condbit = DSP_CTL_POS[DSP_CCOND] + i;
1008        if (bits(*dspctl, condbit, condbit) == 1)
1009            c_values[i] = a_values[i];
1010        else
1011            c_values[i] = b_values[i];
1012    }
1013
1014    simdPack(c_values, &result, fmt);
1015
1016    return result;
1017}
1018
1019int32_t
1020MipsISA::dspPack(int32_t a, int32_t b, int32_t fmt)
1021{
1022    int32_t result;
1023    uint64_t a_values[SIMD_MAX_VALS];
1024    uint64_t b_values[SIMD_MAX_VALS];
1025    uint64_t c_values[SIMD_MAX_VALS];
1026
1027    simdUnpack(a, a_values, fmt, UNSIGNED);
1028    simdUnpack(b, b_values, fmt, UNSIGNED);
1029
1030    c_values[0] = b_values[1];
1031    c_values[1] = a_values[0];
1032
1033    simdPack(c_values, &result, fmt);
1034
1035    return result;
1036}
1037
1038int32_t
1039MipsISA::dspExtr(int64_t dspac, int32_t fmt, int32_t sa, int32_t round,
1040    int32_t saturate, uint32_t *dspctl)
1041{
1042    int32_t result = 0;
1043    uint32_t ouflag = 0;
1044    int64_t temp = 0;
1045
1046    sa = bits(sa, 4, 0);
1047
1048    if (sa > 0) {
1049        if (round) {
1050            temp = (int64_t)addHalfLsb(dspac, sa);
1051
1052            if (dspac > 0 && temp < 0) {
1053                ouflag = 1;
1054                if (saturate)
1055                    temp = FIXED_SMAX[SIMD_FMT_L];
1056            }
1057            temp = temp >> sa;
1058        } else {
1059            temp = dspac >> sa;
1060        }
1061    } else {
1062        temp = dspac;
1063    }
1064
1065    dspac = checkOverflow(dspac, fmt, SIGNED, &ouflag);
1066
1067    if (ouflag) {
1068        *dspctl = insertBits(*dspctl, 23, 23, ouflag);
1069
1070        if (saturate)
1071            result = (int32_t)dspSaturate(temp, fmt, SIGNED, &ouflag);
1072        else
1073            result = (int32_t)temp;
1074    } else {
1075        result = (int32_t)temp;
1076    }
1077
1078    return result;
1079}
1080
1081int32_t
1082MipsISA::dspExtp(int64_t dspac, int32_t size, uint32_t *dspctl)
1083{
1084    int32_t pos = 0;
1085    int32_t result = 0;
1086
1087    pos = bits(*dspctl, 5, 0);
1088    size = bits(size, 4, 0);
1089
1090    if (pos - (size + 1) >= -1) {
1091        result = bits(dspac, pos, pos - size);
1092        *dspctl = insertBits(*dspctl, 14, 14, 0);
1093    } else {
1094        result = 0;
1095        *dspctl = insertBits(*dspctl, 14, 14, 1);
1096    }
1097
1098    return result;
1099}
1100
1101int32_t
1102MipsISA::dspExtpd(int64_t dspac, int32_t size, uint32_t *dspctl)
1103{
1104    int32_t pos = 0;
1105    int32_t result = 0;
1106
1107    pos = bits(*dspctl, 5, 0);
1108    size = bits(size, 4, 0);
1109
1110    if (pos - (size + 1) >= -1) {
1111        result = bits(dspac, pos, pos - size);
1112        *dspctl = insertBits(*dspctl, 14, 14, 0);
1113        if (pos - (size + 1) >= 0)
1114            *dspctl = insertBits(*dspctl, 5, 0, pos - (size + 1));
1115        else if ((pos - (size + 1)) == -1)
1116            *dspctl = insertBits(*dspctl, 5, 0, 63);
1117    } else {
1118        result = 0;
1119        *dspctl = insertBits(*dspctl, 14, 14, 1);
1120    }
1121
1122    return result;
1123}
1124
1125void
1126MipsISA::simdPack(uint64_t *values_ptr, int32_t *reg, int32_t fmt)
1127{
1128    int nvals = SIMD_NVALS[fmt];
1129    int nbits = SIMD_NBITS[fmt];
1130
1131    *reg = 0;
1132
1133    for (int i = 0; i < nvals; i++)
1134        *reg |= (int32_t)bits(values_ptr[i], nbits - 1, 0) << nbits * i;
1135}
1136
1137void
1138MipsISA::simdUnpack(int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign)
1139{
1140    int nvals = SIMD_NVALS[fmt];
1141    int nbits = SIMD_NBITS[fmt];
1142
1143    switch (sign) {
1144      case SIGNED:
1145        for (int i = 0; i < nvals; i++) {
1146            uint64_t tmp = (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i);
1147            values_ptr[i] = signExtend(tmp, fmt);
1148        }
1149        break;
1150      case UNSIGNED:
1151        for (int i = 0; i < nvals; i++) {
1152            values_ptr[i] =
1153                (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i);
1154        }
1155        break;
1156    }
1157}
1158
1159void
1160MipsISA::writeDSPControl(uint32_t *dspctl, uint32_t value, uint32_t mask)
1161{
1162    uint32_t fmask = 0;
1163
1164    if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS];
1165    if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT];
1166    if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C];
1167    if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG];
1168    if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND];
1169    if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI];
1170
1171    *dspctl &= ~fmask;
1172    value &= fmask;
1173    *dspctl |= value;
1174}
1175
1176uint32_t
1177MipsISA::readDSPControl(uint32_t *dspctl, uint32_t mask)
1178{
1179    uint32_t fmask = 0;
1180
1181    if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS];
1182    if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT];
1183    if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C];
1184    if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG];
1185    if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND];
1186    if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI];
1187
1188    return *dspctl & fmask;
1189}
1190