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