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
33#include "arch/mips/isa_traits.hh"
34#include "base/bitfield.hh"
35#include "base/logging.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}
1192