dsp.cc revision 5558:cb98f0fcc6c6
15647Sgblack@eecs.umich.edu/*
29544Sandreas.hansson@arm.com * Copyright (c) 2007 MIPS Technologies, Inc.
38922Swilliam.wang@arm.com * All rights reserved.
48922Swilliam.wang@arm.com *
58922Swilliam.wang@arm.com * Redistribution and use in source and binary forms, with or without
68922Swilliam.wang@arm.com * modification, are permitted provided that the following conditions are
78922Swilliam.wang@arm.com * met: redistributions of source code must retain the above copyright
88922Swilliam.wang@arm.com * notice, this list of conditions and the following disclaimer;
98922Swilliam.wang@arm.com * redistributions in binary form must reproduce the above copyright
108922Swilliam.wang@arm.com * notice, this list of conditions and the following disclaimer in the
118922Swilliam.wang@arm.com * documentation and/or other materials provided with the distribution;
128922Swilliam.wang@arm.com * neither the name of the copyright holders nor the names of its
138922Swilliam.wang@arm.com * contributors may be used to endorse or promote products derived from
145647Sgblack@eecs.umich.edu * this software without specific prior written permission.
155647Sgblack@eecs.umich.edu *
165647Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247087Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267087Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277087Snate@binkert.org *
287087Snate@binkert.org * Authors: Brett Miller
297087Snate@binkert.org */
307087Snate@binkert.org
317087Snate@binkert.org#include "arch/mips/isa_traits.hh"
327087Snate@binkert.org#include "arch/mips/dsp.hh"
337087Snate@binkert.org#include "config/full_system.hh"
345647Sgblack@eecs.umich.edu#include "cpu/static_inst.hh"
357087Snate@binkert.org#include "sim/serialize.hh"
365647Sgblack@eecs.umich.edu#include "base/bitfield.hh"
375647Sgblack@eecs.umich.edu#include "base/misc.hh"
385647Sgblack@eecs.umich.edu
395647Sgblack@eecs.umich.eduusing namespace MipsISA;
405647Sgblack@eecs.umich.eduusing namespace std;
415647Sgblack@eecs.umich.edu
425647Sgblack@eecs.umich.eduint32_t
435647Sgblack@eecs.umich.eduMipsISA::bitrev(int32_t value)
445647Sgblack@eecs.umich.edu{
455647Sgblack@eecs.umich.edu    int32_t result = 0;
465647Sgblack@eecs.umich.edu    int shift;
475647Sgblack@eecs.umich.edu
485647Sgblack@eecs.umich.edu    for (int i = 0; i < 16; i++) {
495647Sgblack@eecs.umich.edu        shift = 2 * i - 15;
505647Sgblack@eecs.umich.edu
515647Sgblack@eecs.umich.edu        if (shift < 0)
528229Snate@binkert.org            result |= (value & 1 << i) << -shift;
535647Sgblack@eecs.umich.edu        else
545654Sgblack@eecs.umich.edu            result |= (value & 1 << i) >> shift;
555647Sgblack@eecs.umich.edu    }
568232Snate@binkert.org
576137Sgblack@eecs.umich.edu    return result;
586137Sgblack@eecs.umich.edu}
596137Sgblack@eecs.umich.edu
605654Sgblack@eecs.umich.eduuint64_t
616046Sgblack@eecs.umich.eduMipsISA::dspSaturate(uint64_t value, int32_t fmt, int32_t sign,
628781Sgblack@eecs.umich.edu    uint32_t *overflow)
635647Sgblack@eecs.umich.edu{
645648Sgblack@eecs.umich.edu    int64_t svalue = (int64_t)value;
655648Sgblack@eecs.umich.edu
665647Sgblack@eecs.umich.edu    switch(sign) {
675647Sgblack@eecs.umich.edu      case SIGNED:
685647Sgblack@eecs.umich.edu        if (svalue > (int64_t)FIXED_SMAX[fmt]) {
695647Sgblack@eecs.umich.edu            *overflow = 1;
705647Sgblack@eecs.umich.edu            svalue = (int64_t)FIXED_SMAX[fmt];
715647Sgblack@eecs.umich.edu        } else if (svalue < (int64_t)FIXED_SMIN[fmt]) {
725647Sgblack@eecs.umich.edu            *overflow = 1;
735647Sgblack@eecs.umich.edu            svalue = (int64_t)FIXED_SMIN[fmt];
745647Sgblack@eecs.umich.edu        }
755648Sgblack@eecs.umich.edu        break;
765647Sgblack@eecs.umich.edu      case UNSIGNED:
775648Sgblack@eecs.umich.edu        if (svalue > (int64_t)FIXED_UMAX[fmt]) {
785648Sgblack@eecs.umich.edu            *overflow = 1;
795648Sgblack@eecs.umich.edu            svalue = FIXED_UMAX[fmt];
805648Sgblack@eecs.umich.edu        } else if (svalue < (int64_t)FIXED_UMIN[fmt]) {
815648Sgblack@eecs.umich.edu            *overflow = 1;
825648Sgblack@eecs.umich.edu            svalue = FIXED_UMIN[fmt];
835648Sgblack@eecs.umich.edu        }
845648Sgblack@eecs.umich.edu        break;
855648Sgblack@eecs.umich.edu    }
865648Sgblack@eecs.umich.edu
875648Sgblack@eecs.umich.edu    return (uint64_t)svalue;
885648Sgblack@eecs.umich.edu}
895648Sgblack@eecs.umich.edu
905648Sgblack@eecs.umich.eduuint64_t
915648Sgblack@eecs.umich.eduMipsISA::checkOverflow(uint64_t value, int32_t fmt, int32_t sign,
925648Sgblack@eecs.umich.edu    uint32_t *overflow)
935648Sgblack@eecs.umich.edu{
945648Sgblack@eecs.umich.edu    int64_t svalue = (int64_t)value;
955648Sgblack@eecs.umich.edu
965648Sgblack@eecs.umich.edu    switch(sign)
975648Sgblack@eecs.umich.edu    {
985648Sgblack@eecs.umich.edu      case SIGNED:
995648Sgblack@eecs.umich.edu        if (svalue > (int64_t)FIXED_SMAX[fmt] ||
1005648Sgblack@eecs.umich.edu            svalue < (int64_t)FIXED_SMIN[fmt])
1015648Sgblack@eecs.umich.edu            *overflow = 1;
1025648Sgblack@eecs.umich.edu        break;
1035648Sgblack@eecs.umich.edu      case UNSIGNED:
1045648Sgblack@eecs.umich.edu        if (svalue > (int64_t)FIXED_UMAX[fmt] ||
1055648Sgblack@eecs.umich.edu            svalue < (int64_t)FIXED_UMIN[fmt])
1065648Sgblack@eecs.umich.edu            *overflow = 1;
1075648Sgblack@eecs.umich.edu        break;
1085648Sgblack@eecs.umich.edu    }
1095648Sgblack@eecs.umich.edu
1105648Sgblack@eecs.umich.edu    return (uint64_t)svalue;
1115648Sgblack@eecs.umich.edu}
1125648Sgblack@eecs.umich.edu
1135648Sgblack@eecs.umich.eduuint64_t
1145648Sgblack@eecs.umich.eduMipsISA::signExtend(uint64_t value, int32_t fmt)
1155648Sgblack@eecs.umich.edu{
1165648Sgblack@eecs.umich.edu    int32_t signpos = SIMD_NBITS[fmt];
1175648Sgblack@eecs.umich.edu    uint64_t sign = uint64_t(1) << (signpos - 1);
1185648Sgblack@eecs.umich.edu    uint64_t ones = ~(0ULL);
1195648Sgblack@eecs.umich.edu
1205648Sgblack@eecs.umich.edu    if (value & sign)
1215648Sgblack@eecs.umich.edu        value |= (ones << signpos); // extend with ones
1225648Sgblack@eecs.umich.edu    else
1235648Sgblack@eecs.umich.edu        value &= (ones >> (64 - signpos)); // extend with zeros
1245648Sgblack@eecs.umich.edu
1255648Sgblack@eecs.umich.edu    return value;
1265648Sgblack@eecs.umich.edu}
1275648Sgblack@eecs.umich.edu
1285648Sgblack@eecs.umich.eduuint64_t
1295648Sgblack@eecs.umich.eduMipsISA::addHalfLsb(uint64_t value, int32_t lsbpos)
1305648Sgblack@eecs.umich.edu{
1315648Sgblack@eecs.umich.edu    return value += ULL(1) << (lsbpos - 1);
1325648Sgblack@eecs.umich.edu}
1335648Sgblack@eecs.umich.edu
1345648Sgblack@eecs.umich.eduint32_t
1355648Sgblack@eecs.umich.eduMipsISA::dspAbs(int32_t a, int32_t fmt, uint32_t *dspctl)
1365648Sgblack@eecs.umich.edu{
1375648Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
1385648Sgblack@eecs.umich.edu    int32_t result;
1395648Sgblack@eecs.umich.edu    int64_t svalue;
1405648Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
1415648Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
1425648Sgblack@eecs.umich.edu
1435648Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, SIGNED);
1445648Sgblack@eecs.umich.edu
1455648Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
1465648Sgblack@eecs.umich.edu        svalue = (int64_t)a_values[i];
1475648Sgblack@eecs.umich.edu
1485648Sgblack@eecs.umich.edu        if (a_values[i] == FIXED_SMIN[fmt]) {
1495648Sgblack@eecs.umich.edu            a_values[i] = FIXED_SMAX[fmt];
1505648Sgblack@eecs.umich.edu            ouflag = 1;
1515648Sgblack@eecs.umich.edu        } else if (svalue < 0) {
1525648Sgblack@eecs.umich.edu            a_values[i] = uint64_t(0 - svalue);
1535648Sgblack@eecs.umich.edu        }
1545648Sgblack@eecs.umich.edu    }
1555648Sgblack@eecs.umich.edu
1565648Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
1575648Sgblack@eecs.umich.edu
1585648Sgblack@eecs.umich.edu    if (ouflag)
1595648Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG],
1605648Sgblack@eecs.umich.edu                        1 << DSP_OUFLAG);
1615648Sgblack@eecs.umich.edu
1625648Sgblack@eecs.umich.edu    return result;
1635648Sgblack@eecs.umich.edu}
1645648Sgblack@eecs.umich.edu
1655648Sgblack@eecs.umich.eduint32_t
1665648Sgblack@eecs.umich.eduMipsISA::dspAdd(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
1675648Sgblack@eecs.umich.edu    int32_t sign, uint32_t *dspctl)
1685648Sgblack@eecs.umich.edu{
1695648Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
1705648Sgblack@eecs.umich.edu    int32_t result;
1715648Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
1725648Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
1735648Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
1745648Sgblack@eecs.umich.edu
1755648Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
1765648Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, sign);
1775648Sgblack@eecs.umich.edu
1785648Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++)
1795648Sgblack@eecs.umich.edu    {
1805648Sgblack@eecs.umich.edu        if (saturate)
1815648Sgblack@eecs.umich.edu            a_values[i] = dspSaturate(a_values[i] + b_values[i], fmt, sign,
1825648Sgblack@eecs.umich.edu                                      &ouflag);
1835648Sgblack@eecs.umich.edu        else
1845648Sgblack@eecs.umich.edu            a_values[i] = checkOverflow(a_values[i] + b_values[i], fmt, sign,
1855648Sgblack@eecs.umich.edu                                        &ouflag);
1865648Sgblack@eecs.umich.edu    }
1875648Sgblack@eecs.umich.edu
1885648Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
1895648Sgblack@eecs.umich.edu
1905648Sgblack@eecs.umich.edu    if (ouflag)
1915648Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG],
1925648Sgblack@eecs.umich.edu                        1 << DSP_OUFLAG);
1935648Sgblack@eecs.umich.edu
1945648Sgblack@eecs.umich.edu    return result;
1955648Sgblack@eecs.umich.edu}
1965648Sgblack@eecs.umich.edu
1975648Sgblack@eecs.umich.eduint32_t
1985648Sgblack@eecs.umich.eduMipsISA::dspAddh(int32_t a, int32_t b, int32_t fmt, int32_t round,
1995648Sgblack@eecs.umich.edu    int32_t sign)
2005648Sgblack@eecs.umich.edu{
2015648Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
2025648Sgblack@eecs.umich.edu    int32_t result;
2035648Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
2045648Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
2055648Sgblack@eecs.umich.edu
2065648Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
2075648Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, sign);
2085648Sgblack@eecs.umich.edu
2095648Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
2105648Sgblack@eecs.umich.edu        if (round)
2115648Sgblack@eecs.umich.edu            a_values[i] = addHalfLsb(a_values[i] + b_values[i], 1) >> 1;
2125648Sgblack@eecs.umich.edu        else
2135648Sgblack@eecs.umich.edu            a_values[i] = (a_values[i] + b_values[i]) >> 1;
2145648Sgblack@eecs.umich.edu    }
2155648Sgblack@eecs.umich.edu
2165648Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
2175648Sgblack@eecs.umich.edu
2185648Sgblack@eecs.umich.edu    return result;
2195648Sgblack@eecs.umich.edu}
2205649Sgblack@eecs.umich.edu
2215649Sgblack@eecs.umich.eduint32_t
2225649Sgblack@eecs.umich.eduMipsISA::dspSub(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
2235648Sgblack@eecs.umich.edu    int32_t sign, uint32_t *dspctl)
2245898Sgblack@eecs.umich.edu{
2255648Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
2265648Sgblack@eecs.umich.edu    int32_t result;
2275648Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
2285648Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
2295648Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
2305648Sgblack@eecs.umich.edu
2315648Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
2325648Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, sign);
2335648Sgblack@eecs.umich.edu
2345648Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
2355648Sgblack@eecs.umich.edu        if (saturate)
2365648Sgblack@eecs.umich.edu            a_values[i] = dspSaturate(a_values[i] - b_values[i], fmt, sign,
2375648Sgblack@eecs.umich.edu                                      &ouflag);
2385649Sgblack@eecs.umich.edu        else
2395649Sgblack@eecs.umich.edu            a_values[i] = checkOverflow(a_values[i] - b_values[i], fmt, sign,
2405649Sgblack@eecs.umich.edu                                        &ouflag);
2415648Sgblack@eecs.umich.edu    }
2425898Sgblack@eecs.umich.edu
2435648Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
2445647Sgblack@eecs.umich.edu
2455691Sgblack@eecs.umich.edu    if (ouflag)
2465691Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG],
2475691Sgblack@eecs.umich.edu                        1 << DSP_OUFLAG);
2485691Sgblack@eecs.umich.edu
2495691Sgblack@eecs.umich.edu    return result;
2505691Sgblack@eecs.umich.edu}
2515691Sgblack@eecs.umich.edu
2525691Sgblack@eecs.umich.eduint32_t
2535691Sgblack@eecs.umich.eduMipsISA::dspSubh(int32_t a, int32_t b, int32_t fmt, int32_t round,
2545691Sgblack@eecs.umich.edu    int32_t sign)
2555691Sgblack@eecs.umich.edu{
2565691Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
2575691Sgblack@eecs.umich.edu    int32_t result;
2585691Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
2595691Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
2605691Sgblack@eecs.umich.edu
2615691Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
2625691Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, sign);
2635691Sgblack@eecs.umich.edu
2645691Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++)
2655691Sgblack@eecs.umich.edu    {
2665691Sgblack@eecs.umich.edu        if (round)
2675691Sgblack@eecs.umich.edu            a_values[i] = addHalfLsb(a_values[i] - b_values[i], 1) >> 1;
2685691Sgblack@eecs.umich.edu        else
2695691Sgblack@eecs.umich.edu            a_values[i] = (a_values[i] - b_values[i]) >> 1;
2705691Sgblack@eecs.umich.edu    }
2715691Sgblack@eecs.umich.edu
2725691Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
2735691Sgblack@eecs.umich.edu
2745691Sgblack@eecs.umich.edu    return result;
2755691Sgblack@eecs.umich.edu}
2765691Sgblack@eecs.umich.edu
2775691Sgblack@eecs.umich.eduint32_t
2785691Sgblack@eecs.umich.eduMipsISA::dspShll(int32_t a, uint32_t sa, int32_t fmt, int32_t saturate,
2795691Sgblack@eecs.umich.edu    int32_t sign, uint32_t *dspctl)
2805691Sgblack@eecs.umich.edu{
2815691Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
2825691Sgblack@eecs.umich.edu    int32_t result;
2835691Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
2846066Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
2856066Sgblack@eecs.umich.edu
2866050Sgblack@eecs.umich.edu    sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0);
2876050Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
2885691Sgblack@eecs.umich.edu
2898745Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++)
2908781Sgblack@eecs.umich.edu    {
2918781Sgblack@eecs.umich.edu        if (saturate)
2925691Sgblack@eecs.umich.edu            a_values[i] = dspSaturate(a_values[i] << sa, fmt, sign, &ouflag);
2935647Sgblack@eecs.umich.edu        else
2946041Sgblack@eecs.umich.edu            a_values[i] = checkOverflow(a_values[i] << sa, fmt, sign, &ouflag);
2956041Sgblack@eecs.umich.edu    }
2966041Sgblack@eecs.umich.edu
2976041Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
2986136Sgblack@eecs.umich.edu
2996136Sgblack@eecs.umich.edu    if (ouflag)
3006136Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 6) << DSP_CTL_POS[DSP_OUFLAG],
3016136Sgblack@eecs.umich.edu                        1 << DSP_OUFLAG);
3026136Sgblack@eecs.umich.edu
3036041Sgblack@eecs.umich.edu    return result;
3046136Sgblack@eecs.umich.edu}
3056136Sgblack@eecs.umich.edu
3069090Sandreas.hansson@arm.comint32_t
3076041Sgblack@eecs.umich.eduMipsISA::dspShrl(int32_t a, uint32_t sa, int32_t fmt, int32_t sign)
3086041Sgblack@eecs.umich.edu{
3096041Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
3106137Sgblack@eecs.umich.edu    int32_t result;
3116137Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
3126137Sgblack@eecs.umich.edu
3137913SBrad.Beckmann@amd.com    sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0);
3147913SBrad.Beckmann@amd.com
3157913SBrad.Beckmann@amd.com    simdUnpack(a, a_values, fmt, UNSIGNED);
3167913SBrad.Beckmann@amd.com
3177913SBrad.Beckmann@amd.com    for (int i = 0; i < nvals; i++)
3186137Sgblack@eecs.umich.edu        a_values[i] = a_values[i] >> sa;
3197913SBrad.Beckmann@amd.com
3208922Swilliam.wang@arm.com    simdPack(a_values, &result, fmt);
3218922Swilliam.wang@arm.com
3228922Swilliam.wang@arm.com    return result;
3236137Sgblack@eecs.umich.edu}
3246137Sgblack@eecs.umich.edu
3256137Sgblack@eecs.umich.eduint32_t
3265651Sgblack@eecs.umich.eduMipsISA::dspShra(int32_t a, uint32_t sa, int32_t fmt, int32_t round,
3275651Sgblack@eecs.umich.edu    int32_t sign, uint32_t *dspctl)
3285651Sgblack@eecs.umich.edu{
3296136Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
3305651Sgblack@eecs.umich.edu    int32_t result;
3315651Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
3325651Sgblack@eecs.umich.edu
3335651Sgblack@eecs.umich.edu    sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0);
3345654Sgblack@eecs.umich.edu
3355654Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, SIGNED);
3365654Sgblack@eecs.umich.edu
3375654Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
3385697Snate@binkert.org        if (round)
3395655Sgblack@eecs.umich.edu            a_values[i] = addHalfLsb(a_values[i], sa) >> sa;
3405691Sgblack@eecs.umich.edu        else
3415691Sgblack@eecs.umich.edu            a_values[i] = a_values[i] >> sa;
3425654Sgblack@eecs.umich.edu    }
3435651Sgblack@eecs.umich.edu
3445651Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
3455651Sgblack@eecs.umich.edu
3465651Sgblack@eecs.umich.edu    return result;
3475651Sgblack@eecs.umich.edu}
3485651Sgblack@eecs.umich.edu
3496064Sgblack@eecs.umich.eduint32_t
3505651Sgblack@eecs.umich.eduMipsISA::dspMulq(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
3515651Sgblack@eecs.umich.edu    int32_t round, uint32_t *dspctl)
3525651Sgblack@eecs.umich.edu{
3535651Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
3546065Sgblack@eecs.umich.edu    int sa = SIMD_NBITS[fmt];
3556065Sgblack@eecs.umich.edu    int32_t result;
3566065Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
3576065Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
3586065Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
3596069Sgblack@eecs.umich.edu    int64_t temp;
3606069Sgblack@eecs.umich.edu
3616069Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, SIGNED);
3626069Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, SIGNED);
3636069Sgblack@eecs.umich.edu
3646069Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
3656065Sgblack@eecs.umich.edu        if (round)
3666065Sgblack@eecs.umich.edu            temp =
3676065Sgblack@eecs.umich.edu                (int64_t)addHalfLsb(a_values[i] * b_values[i] << 1, sa) >> sa;
3686065Sgblack@eecs.umich.edu        else
3696065Sgblack@eecs.umich.edu            temp = (int64_t)(a_values[i] * b_values[i]) >> (sa - 1);
3708711Sandreas.hansson@arm.com
3719090Sandreas.hansson@arm.com        if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) {
3726041Sgblack@eecs.umich.edu            ouflag = 1;
3738711Sandreas.hansson@arm.com
3749235Sandreas.hansson@arm.com            if (saturate)
3759235Sandreas.hansson@arm.com                temp = FIXED_SMAX[fmt];
3769235Sandreas.hansson@arm.com        }
3778711Sandreas.hansson@arm.com
3788711Sandreas.hansson@arm.com        a_values[i] = temp;
3796041Sgblack@eecs.umich.edu    }
3806041Sgblack@eecs.umich.edu
3816041Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
3828711Sandreas.hansson@arm.com
3839090Sandreas.hansson@arm.com    if (ouflag)
3846041Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
3858711Sandreas.hansson@arm.com                        1 << DSP_OUFLAG);
3868711Sandreas.hansson@arm.com
3878711Sandreas.hansson@arm.com    return result;
3888711Sandreas.hansson@arm.com}
3898711Sandreas.hansson@arm.com
3906041Sgblack@eecs.umich.eduint32_t
3916041Sgblack@eecs.umich.eduMipsISA::dspMul(int32_t a, int32_t b, int32_t fmt, int32_t saturate,
3926041Sgblack@eecs.umich.edu    uint32_t *dspctl)
3935647Sgblack@eecs.umich.edu{
3945648Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
3955647Sgblack@eecs.umich.edu    int32_t result;
3965647Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
3975647Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
3985647Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
3995647Sgblack@eecs.umich.edu
4005647Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, SIGNED);
4015647Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, SIGNED);
4025647Sgblack@eecs.umich.edu
4035647Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++)
4045647Sgblack@eecs.umich.edu    {
4055647Sgblack@eecs.umich.edu        if (saturate)
4065647Sgblack@eecs.umich.edu            a_values[i] = dspSaturate(a_values[i] * b_values[i], fmt, SIGNED,
4075647Sgblack@eecs.umich.edu                                      &ouflag);
4085647Sgblack@eecs.umich.edu        else
4095647Sgblack@eecs.umich.edu            a_values[i] = checkOverflow(a_values[i] * b_values[i], fmt, SIGNED,
4105647Sgblack@eecs.umich.edu                                        &ouflag);
4115647Sgblack@eecs.umich.edu    }
4125848Sgblack@eecs.umich.edu
4135848Sgblack@eecs.umich.edu    simdPack(a_values, &result, fmt);
4149544Sandreas.hansson@arm.com
4155848Sgblack@eecs.umich.edu    if (ouflag)
4165848Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
4177823Ssteve.reinhardt@amd.com                        1 << DSP_OUFLAG);
4185848Sgblack@eecs.umich.edu
4195848Sgblack@eecs.umich.edu    return result;
4205848Sgblack@eecs.umich.edu}
4215848Sgblack@eecs.umich.edu
4225848Sgblack@eecs.umich.eduint32_t
4235848Sgblack@eecs.umich.eduMipsISA::dspMuleu(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl)
4245647Sgblack@eecs.umich.edu{
4255647Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[SIMD_FMT_PH];
4265647Sgblack@eecs.umich.edu    int32_t result;
4275647Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
4285648Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
4295647Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
4305647Sgblack@eecs.umich.edu
4315647Sgblack@eecs.umich.edu    simdUnpack(a, a_values, SIMD_FMT_QB, UNSIGNED);
4325648Sgblack@eecs.umich.edu    simdUnpack(b, b_values, SIMD_FMT_PH, UNSIGNED);
4335647Sgblack@eecs.umich.edu
4345647Sgblack@eecs.umich.edu    switch(mode) {
4355647Sgblack@eecs.umich.edu      case MODE_L:
4365647Sgblack@eecs.umich.edu        for (int i = 0; i < nvals; i++)
4375647Sgblack@eecs.umich.edu            b_values[i] = dspSaturate(a_values[i + 2] * b_values[i],
4385647Sgblack@eecs.umich.edu                                      SIMD_FMT_PH, UNSIGNED, &ouflag);
4395647Sgblack@eecs.umich.edu        break;
4405647Sgblack@eecs.umich.edu      case MODE_R:
4415647Sgblack@eecs.umich.edu        for (int i = 0; i < nvals; i++)
4425647Sgblack@eecs.umich.edu            b_values[i] = dspSaturate(a_values[i] * b_values[i], SIMD_FMT_PH,
4435647Sgblack@eecs.umich.edu                                      UNSIGNED, &ouflag);
4445647Sgblack@eecs.umich.edu        break;
4455647Sgblack@eecs.umich.edu    }
4465647Sgblack@eecs.umich.edu
4475647Sgblack@eecs.umich.edu    simdPack(b_values, &result, SIMD_FMT_PH);
4485647Sgblack@eecs.umich.edu
4495647Sgblack@eecs.umich.edu    if (ouflag)
4505647Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
4515647Sgblack@eecs.umich.edu                        1 << DSP_OUFLAG);
4525647Sgblack@eecs.umich.edu
4535647Sgblack@eecs.umich.edu    return result;
4545647Sgblack@eecs.umich.edu}
4555647Sgblack@eecs.umich.edu
4565647Sgblack@eecs.umich.eduint32_t
4575647Sgblack@eecs.umich.eduMipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl)
4585647Sgblack@eecs.umich.edu{
4595647Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[SIMD_FMT_W];
4605647Sgblack@eecs.umich.edu    int32_t result;
4615647Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
4625647Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
4635647Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
4645647Sgblack@eecs.umich.edu    uint64_t c_values[SIMD_MAX_VALS];
4655690Sgblack@eecs.umich.edu
4665690Sgblack@eecs.umich.edu    simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED);
4675690Sgblack@eecs.umich.edu    simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED);
4685690Sgblack@eecs.umich.edu
4695647Sgblack@eecs.umich.edu    switch(mode) {
4705647Sgblack@eecs.umich.edu      case MODE_L:
4715647Sgblack@eecs.umich.edu        for (int i = 0; i < nvals; i++)
4725647Sgblack@eecs.umich.edu            c_values[i] = dspSaturate(a_values[i + 1] * b_values[i + 1] << 1,
4735647Sgblack@eecs.umich.edu                                       SIMD_FMT_W, SIGNED, &ouflag);
4745647Sgblack@eecs.umich.edu        break;
4755647Sgblack@eecs.umich.edu      case MODE_R:
4765647Sgblack@eecs.umich.edu        for (int i = 0; i < nvals; i++)
4775647Sgblack@eecs.umich.edu            c_values[i] = dspSaturate(a_values[i] * b_values[i] << 1,
4785647Sgblack@eecs.umich.edu                                       SIMD_FMT_W, SIGNED, &ouflag);
4795647Sgblack@eecs.umich.edu        break;
4805647Sgblack@eecs.umich.edu    }
4815647Sgblack@eecs.umich.edu
4825647Sgblack@eecs.umich.edu    simdPack(c_values, &result, SIMD_FMT_W);
4835647Sgblack@eecs.umich.edu
4845647Sgblack@eecs.umich.edu    if (ouflag)
4855647Sgblack@eecs.umich.edu        writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG],
4865647Sgblack@eecs.umich.edu                        1 << DSP_OUFLAG);
4875647Sgblack@eecs.umich.edu
4885647Sgblack@eecs.umich.edu    return result;
4895647Sgblack@eecs.umich.edu}
4905647Sgblack@eecs.umich.edu
4915647Sgblack@eecs.umich.eduint64_t
4925647Sgblack@eecs.umich.eduMipsISA::dspDpaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
4935647Sgblack@eecs.umich.edu    int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode,
4946046Sgblack@eecs.umich.edu    uint32_t *dspctl)
4956046Sgblack@eecs.umich.edu{
4966046Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[infmt];
4976046Sgblack@eecs.umich.edu    int64_t result = 0;
4986046Sgblack@eecs.umich.edu    int64_t temp = 0;
4996046Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
5006046Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
5016046Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
5026046Sgblack@eecs.umich.edu
5036046Sgblack@eecs.umich.edu    simdUnpack(a, a_values, infmt, SIGNED);
5046046Sgblack@eecs.umich.edu    simdUnpack(b, b_values, infmt, SIGNED);
5056712Snate@binkert.org
5066046Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
5076046Sgblack@eecs.umich.edu        switch(mode) {
5086046Sgblack@eecs.umich.edu          case MODE_X:
5096046Sgblack@eecs.umich.edu            if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] &&
5106046Sgblack@eecs.umich.edu                b_values[i] == FIXED_SMIN[infmt]) {
5116046Sgblack@eecs.umich.edu                result += FIXED_SMAX[outfmt];
5129524SAndreas.Sandberg@ARM.com                ouflag = 1;
5136065Sgblack@eecs.umich.edu            }
5146065Sgblack@eecs.umich.edu            else
5156138Sgblack@eecs.umich.edu                result += a_values[nvals - 1 - i] * b_values[i] << 1;
5166138Sgblack@eecs.umich.edu            break;
5176046Sgblack@eecs.umich.edu          default:
5186046Sgblack@eecs.umich.edu            if (a_values[i] == FIXED_SMIN[infmt] &&
5196138Sgblack@eecs.umich.edu                b_values[i] == FIXED_SMIN[infmt]) {
5206138Sgblack@eecs.umich.edu                result += FIXED_SMAX[outfmt];
5216138Sgblack@eecs.umich.edu                ouflag = 1;
5226138Sgblack@eecs.umich.edu            } else {
5236138Sgblack@eecs.umich.edu                result += a_values[i] * b_values[i] << 1;
5246138Sgblack@eecs.umich.edu            }
5256138Sgblack@eecs.umich.edu            break;
5266138Sgblack@eecs.umich.edu        }
5276138Sgblack@eecs.umich.edu    }
5286138Sgblack@eecs.umich.edu
5296138Sgblack@eecs.umich.edu    if (postsat) {
5306138Sgblack@eecs.umich.edu        if (outfmt == SIMD_FMT_L) {
5316138Sgblack@eecs.umich.edu            int signa = bits(dspac, 63, 63);
5326138Sgblack@eecs.umich.edu            int signb = bits(result, 63, 63);
5336138Sgblack@eecs.umich.edu
5346138Sgblack@eecs.umich.edu            temp = dspac + result;
5356138Sgblack@eecs.umich.edu
5366138Sgblack@eecs.umich.edu            if (signa == signb && bits(temp, 63, 63) != signa) {
5376138Sgblack@eecs.umich.edu                ouflag = 1;
5386138Sgblack@eecs.umich.edu                if (signa)
5396138Sgblack@eecs.umich.edu                    dspac = FIXED_SMIN[outfmt];
5406138Sgblack@eecs.umich.edu                else
5416138Sgblack@eecs.umich.edu                    dspac = FIXED_SMAX[outfmt];
5426138Sgblack@eecs.umich.edu            } else {
5436138Sgblack@eecs.umich.edu                dspac = temp;
5446138Sgblack@eecs.umich.edu            }
5456138Sgblack@eecs.umich.edu        } else {
5466138Sgblack@eecs.umich.edu            dspac = dspSaturate(dspac + result, outfmt, SIGNED, &ouflag);
5476138Sgblack@eecs.umich.edu        }
5486138Sgblack@eecs.umich.edu    } else {
5496138Sgblack@eecs.umich.edu        dspac += result;
5506046Sgblack@eecs.umich.edu    }
5516046Sgblack@eecs.umich.edu
5526069Sgblack@eecs.umich.edu    if (ouflag)
5536069Sgblack@eecs.umich.edu        *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
5546069Sgblack@eecs.umich.edu
5556046Sgblack@eecs.umich.edu    return dspac;
5566046Sgblack@eecs.umich.edu}
5576069Sgblack@eecs.umich.edu
5586069Sgblack@eecs.umich.eduint64_t
5596069Sgblack@eecs.umich.eduMipsISA::dspDpsq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
5606046Sgblack@eecs.umich.edu    int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode,
5616069Sgblack@eecs.umich.edu    uint32_t *dspctl)
5626069Sgblack@eecs.umich.edu{
5636138Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[infmt];
5646138Sgblack@eecs.umich.edu    int64_t result = 0;
5656069Sgblack@eecs.umich.edu    int64_t temp = 0;
5666069Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
5676069Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
5686046Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
5696046Sgblack@eecs.umich.edu
5706138Sgblack@eecs.umich.edu    simdUnpack(a, a_values, infmt, SIGNED);
5718922Swilliam.wang@arm.com    simdUnpack(b, b_values, infmt, SIGNED);
5726138Sgblack@eecs.umich.edu
5736046Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
5745647Sgblack@eecs.umich.edu        switch(mode) {
5755647Sgblack@eecs.umich.edu          case MODE_X:
5765647Sgblack@eecs.umich.edu            if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] &&
5775647Sgblack@eecs.umich.edu                b_values[i] == FIXED_SMIN[infmt]) {
5785647Sgblack@eecs.umich.edu                result += FIXED_SMAX[outfmt];
5795647Sgblack@eecs.umich.edu                ouflag = 1;
5805647Sgblack@eecs.umich.edu            } else {
5815647Sgblack@eecs.umich.edu                result += a_values[nvals - 1 - i] * b_values[i] << 1;
5825647Sgblack@eecs.umich.edu            }
5835647Sgblack@eecs.umich.edu            break;
5845647Sgblack@eecs.umich.edu          default:
5855647Sgblack@eecs.umich.edu            if (a_values[i] == FIXED_SMIN[infmt] &&
5865647Sgblack@eecs.umich.edu                b_values[i] == FIXED_SMIN[infmt]) {
5875647Sgblack@eecs.umich.edu                result += FIXED_SMAX[outfmt];
5885648Sgblack@eecs.umich.edu                ouflag = 1;
5895648Sgblack@eecs.umich.edu            } else {
5905848Sgblack@eecs.umich.edu                result += a_values[i] * b_values[i] << 1;
5915848Sgblack@eecs.umich.edu            }
5925848Sgblack@eecs.umich.edu            break;
5935648Sgblack@eecs.umich.edu        }
5949544Sandreas.hansson@arm.com    }
5955648Sgblack@eecs.umich.edu
5965648Sgblack@eecs.umich.edu    if (postsat) {
5979544Sandreas.hansson@arm.com        if (outfmt == SIMD_FMT_L) {
5989544Sandreas.hansson@arm.com            int signa = bits(dspac, 63, 63);
5995648Sgblack@eecs.umich.edu            int signb = bits(-result, 63, 63);
6009623Snilay@cs.wisc.edu
6019623Snilay@cs.wisc.edu            temp = dspac - result;
6029623Snilay@cs.wisc.edu
6039623Snilay@cs.wisc.edu            if (signa == signb && bits(temp, 63, 63) != signa) {
6045648Sgblack@eecs.umich.edu                ouflag = 1;
6055648Sgblack@eecs.umich.edu                if (signa)
6065647Sgblack@eecs.umich.edu                    dspac = FIXED_SMIN[outfmt];
6075647Sgblack@eecs.umich.edu                else
6085647Sgblack@eecs.umich.edu                    dspac = FIXED_SMAX[outfmt];
6095647Sgblack@eecs.umich.edu            } else {
6105647Sgblack@eecs.umich.edu                dspac = temp;
6115647Sgblack@eecs.umich.edu            }
6125647Sgblack@eecs.umich.edu        } else {
6135647Sgblack@eecs.umich.edu            dspac = dspSaturate(dspac - result, outfmt, SIGNED, &ouflag);
6145647Sgblack@eecs.umich.edu        }
6155647Sgblack@eecs.umich.edu    } else {
6165648Sgblack@eecs.umich.edu        dspac -= result;
6175647Sgblack@eecs.umich.edu    }
6185647Sgblack@eecs.umich.edu
6195647Sgblack@eecs.umich.edu    if (ouflag)
6206041Sgblack@eecs.umich.edu        *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
6216041Sgblack@eecs.umich.edu
6227900Shestness@cs.utexas.edu    return dspac;
6236041Sgblack@eecs.umich.edu}
6246041Sgblack@eecs.umich.edu
6256041Sgblack@eecs.umich.eduint64_t
6266041Sgblack@eecs.umich.eduMipsISA::dspDpa(int64_t dspac, int32_t a, int32_t b, int32_t ac,
6276041Sgblack@eecs.umich.edu                int32_t fmt, int32_t sign, int32_t mode)
6286050Sgblack@eecs.umich.edu{
6296069Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
6308851Sandreas.hansson@arm.com    uint64_t a_values[SIMD_MAX_VALS];
6319557Sandreas.hansson@arm.com    uint64_t b_values[SIMD_MAX_VALS];
6326041Sgblack@eecs.umich.edu
6336041Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
6346041Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, sign);
6356041Sgblack@eecs.umich.edu
6366041Sgblack@eecs.umich.edu    for (int i = 0; i < 2; i++) {
6376041Sgblack@eecs.umich.edu        switch(mode) {
6386041Sgblack@eecs.umich.edu          case MODE_L:
6396041Sgblack@eecs.umich.edu            dspac += a_values[nvals - 1 - i] * b_values[nvals - 1 - i];
6406041Sgblack@eecs.umich.edu            break;
6416041Sgblack@eecs.umich.edu          case MODE_R:
6425654Sgblack@eecs.umich.edu            dspac += a_values[nvals - 3 - i] * b_values[nvals - 3 - i];
6435704Snate@binkert.org            break;
6445654Sgblack@eecs.umich.edu          case MODE_X:
6455654Sgblack@eecs.umich.edu            dspac += a_values[nvals - 1 - i] * b_values[i];
6465689Sgblack@eecs.umich.edu            break;
6475689Sgblack@eecs.umich.edu        }
6485654Sgblack@eecs.umich.edu    }
6495689Sgblack@eecs.umich.edu
6505655Sgblack@eecs.umich.edu    return dspac;
6515689Sgblack@eecs.umich.edu}
6525689Sgblack@eecs.umich.edu
6535655Sgblack@eecs.umich.eduint64_t
6545689Sgblack@eecs.umich.eduMipsISA::dspDps(int64_t dspac, int32_t a, int32_t b, int32_t ac,
6555655Sgblack@eecs.umich.edu                int32_t fmt, int32_t sign, int32_t mode)
6565689Sgblack@eecs.umich.edu{
6575689Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt];
6585655Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
6595689Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
6605654Sgblack@eecs.umich.edu
6615654Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, sign);
6625654Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, sign);
6635654Sgblack@eecs.umich.edu
6645654Sgblack@eecs.umich.edu    for (int i = 0; i < 2; i++) {
6655704Snate@binkert.org        switch(mode) {
6665654Sgblack@eecs.umich.edu          case MODE_L:
6675704Snate@binkert.org            dspac -= a_values[nvals - 1 - i] * b_values[nvals - 1 - i];
6685655Sgblack@eecs.umich.edu            break;
6695655Sgblack@eecs.umich.edu          case MODE_R:
6705655Sgblack@eecs.umich.edu            dspac -= a_values[nvals - 3 - i] * b_values[nvals - 3 - i];
6715655Sgblack@eecs.umich.edu            break;
6725689Sgblack@eecs.umich.edu          case MODE_X:
6735655Sgblack@eecs.umich.edu            dspac -= a_values[nvals - 1 - i] * b_values[i];
6745655Sgblack@eecs.umich.edu            break;
6755689Sgblack@eecs.umich.edu        }
6765691Sgblack@eecs.umich.edu    }
6775655Sgblack@eecs.umich.edu
6785689Sgblack@eecs.umich.edu    return dspac;
6795691Sgblack@eecs.umich.edu}
6806050Sgblack@eecs.umich.edu
6816050Sgblack@eecs.umich.eduint64_t
6826050Sgblack@eecs.umich.eduMipsISA::dspMaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
6835655Sgblack@eecs.umich.edu                 int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl)
6845655Sgblack@eecs.umich.edu{
6855655Sgblack@eecs.umich.edu    int nvals = SIMD_NVALS[fmt - 1];
6865655Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
6875655Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
6885655Sgblack@eecs.umich.edu    int64_t temp = 0;
6895689Sgblack@eecs.umich.edu    uint32_t ouflag = 0;
6905691Sgblack@eecs.umich.edu
6915655Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, SIGNED);
6925689Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, SIGNED);
6935655Sgblack@eecs.umich.edu
6945655Sgblack@eecs.umich.edu    for (int i = 0; i < nvals; i++) {
6955655Sgblack@eecs.umich.edu        switch(mode) {
6965654Sgblack@eecs.umich.edu          case MODE_L:
6975654Sgblack@eecs.umich.edu            temp = a_values[i + 1] * b_values[i + 1] << 1;
6985654Sgblack@eecs.umich.edu            if (a_values[i + 1] == FIXED_SMIN[fmt] &&
6995704Snate@binkert.org                b_values[i + 1] == FIXED_SMIN[fmt]) {
7005654Sgblack@eecs.umich.edu                temp = (int64_t)FIXED_SMAX[fmt - 1];
7015704Snate@binkert.org                ouflag = 1;
7025655Sgblack@eecs.umich.edu            }
7035655Sgblack@eecs.umich.edu            break;
7045689Sgblack@eecs.umich.edu          case MODE_R:
7055655Sgblack@eecs.umich.edu            temp = a_values[i] * b_values[i] << 1;
7065655Sgblack@eecs.umich.edu            if (a_values[i] == FIXED_SMIN[fmt] &&
7075689Sgblack@eecs.umich.edu                b_values[i] == FIXED_SMIN[fmt]) {
7085655Sgblack@eecs.umich.edu                temp = (int64_t)FIXED_SMAX[fmt - 1];
7095655Sgblack@eecs.umich.edu                ouflag = 1;
7105689Sgblack@eecs.umich.edu            }
7115655Sgblack@eecs.umich.edu            break;
7126066Sgblack@eecs.umich.edu        }
7136050Sgblack@eecs.umich.edu
7146050Sgblack@eecs.umich.edu        temp += dspac;
7156050Sgblack@eecs.umich.edu
7166066Sgblack@eecs.umich.edu        if (saturate)
7175655Sgblack@eecs.umich.edu            temp = dspSaturate(temp, fmt - 1, SIGNED, &ouflag);
7186050Sgblack@eecs.umich.edu        if (ouflag)
7195655Sgblack@eecs.umich.edu            *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
7205655Sgblack@eecs.umich.edu    }
7215655Sgblack@eecs.umich.edu
7225655Sgblack@eecs.umich.edu    return temp;
7235689Sgblack@eecs.umich.edu}
7245655Sgblack@eecs.umich.edu
7255655Sgblack@eecs.umich.eduint64_t
7265655Sgblack@eecs.umich.eduMipsISA::dspMulsa(int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt)
7275655Sgblack@eecs.umich.edu{
7285655Sgblack@eecs.umich.edu    uint64_t a_values[SIMD_MAX_VALS];
7295655Sgblack@eecs.umich.edu    uint64_t b_values[SIMD_MAX_VALS];
7305655Sgblack@eecs.umich.edu
7315654Sgblack@eecs.umich.edu    simdUnpack(a, a_values, fmt, SIGNED);
7325654Sgblack@eecs.umich.edu    simdUnpack(b, b_values, fmt, SIGNED);
7337902Shestness@cs.utexas.edu
7347902Shestness@cs.utexas.edu    dspac += a_values[1] * b_values[1] - a_values[0] * b_values[0];
7357902Shestness@cs.utexas.edu
7367902Shestness@cs.utexas.edu    return dspac;
7377902Shestness@cs.utexas.edu}
7387902Shestness@cs.utexas.edu
7397902Shestness@cs.utexas.eduint64_t
7407902Shestness@cs.utexas.eduMipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac,
7417902Shestness@cs.utexas.edu    int32_t fmt, uint32_t *dspctl)
7427902Shestness@cs.utexas.edu{
7437902Shestness@cs.utexas.edu    int nvals = SIMD_NVALS[fmt];
7447902Shestness@cs.utexas.edu    uint64_t a_values[SIMD_MAX_VALS];
7457902Shestness@cs.utexas.edu    uint64_t b_values[SIMD_MAX_VALS];
7467902Shestness@cs.utexas.edu    int64_t temp[2];
7477902Shestness@cs.utexas.edu    uint32_t ouflag = 0;
7487902Shestness@cs.utexas.edu
7497902Shestness@cs.utexas.edu    simdUnpack(a, a_values, fmt, SIGNED);
7507902Shestness@cs.utexas.edu    simdUnpack(b, b_values, fmt, SIGNED);
7517902Shestness@cs.utexas.edu
7527902Shestness@cs.utexas.edu    for (int i = nvals - 1; i > -1; i--) {
7537902Shestness@cs.utexas.edu        temp[i] = a_values[i] * b_values[i] << 1;
7547902Shestness@cs.utexas.edu        if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) {
7557902Shestness@cs.utexas.edu            temp[i] = FIXED_SMAX[fmt - 1];
7567902Shestness@cs.utexas.edu            ouflag = 1;
7577902Shestness@cs.utexas.edu        }
7587902Shestness@cs.utexas.edu    }
7597902Shestness@cs.utexas.edu
7607902Shestness@cs.utexas.edu    dspac += temp[1] - temp[0];
7617902Shestness@cs.utexas.edu
7627902Shestness@cs.utexas.edu    if (ouflag)
7637902Shestness@cs.utexas.edu        *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1);
7647902Shestness@cs.utexas.edu
7657902Shestness@cs.utexas.edu    return dspac;
7667902Shestness@cs.utexas.edu}
7677902Shestness@cs.utexas.edu
7687902Shestness@cs.utexas.eduvoid
7697902Shestness@cs.utexas.eduMipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op,
7707902Shestness@cs.utexas.edu    uint32_t *dspctl)
7717902Shestness@cs.utexas.edu{
7727902Shestness@cs.utexas.edu    int nvals = SIMD_NVALS[fmt];
7737902Shestness@cs.utexas.edu    int ccond = 0;
7747902Shestness@cs.utexas.edu    uint64_t a_values[SIMD_MAX_VALS];
7757902Shestness@cs.utexas.edu    uint64_t b_values[SIMD_MAX_VALS];
7767902Shestness@cs.utexas.edu
7777902Shestness@cs.utexas.edu    simdUnpack(a, a_values, fmt, sign);
7787902Shestness@cs.utexas.edu    simdUnpack(b, b_values, fmt, sign);
7797902Shestness@cs.utexas.edu
7807902Shestness@cs.utexas.edu    for (int i = 0; i < nvals; i++) {
7817902Shestness@cs.utexas.edu        int cc = 0;
7827902Shestness@cs.utexas.edu
7837902Shestness@cs.utexas.edu        switch(op) {
7847902Shestness@cs.utexas.edu          case CMP_EQ:
7857902Shestness@cs.utexas.edu            cc = (a_values[i] == b_values[i]);
7867902Shestness@cs.utexas.edu            break;
7877902Shestness@cs.utexas.edu          case CMP_LT:
7887902Shestness@cs.utexas.edu            cc = (a_values[i] < b_values[i]);
7897902Shestness@cs.utexas.edu            break;
7905647Sgblack@eecs.umich.edu          case CMP_LE:
7915647Sgblack@eecs.umich.edu            cc = (a_values[i] <= b_values[i]);
7925647Sgblack@eecs.umich.edu            break;
7935647Sgblack@eecs.umich.edu        }
7945647Sgblack@eecs.umich.edu
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