diff options
45 files changed, 5272 insertions, 604 deletions
diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 7edb9f3d7..754a64fdb 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -1414,6 +1414,28 @@ class ControlRegOperand(Operand): self.base_name return wb +class ControlBitfieldOperand(ControlRegOperand): + def makeRead(self): + bit_select = 0 + if (self.ctype == 'float' or self.ctype == 'double'): + error(0, 'Attempt to read control register as FP') + base = 'xc->readMiscReg(%s)' % self.reg_spec + name = self.base_name + return '%s = bits(%s, %s_HI, %s_LO);' % \ + (name, base, name, name) + + def makeWrite(self): + if (self.ctype == 'float' or self.ctype == 'double'): + error(0, 'Attempt to write control register as FP') + base = 'xc->readMiscReg(%s)' % self.reg_spec + name = self.base_name + wb_val = 'insertBits(%s, %s_HI, %s_LO, %s)' % \ + (base, name, name, self.base_name) + wb = 'xc->setMiscRegOperand(this, %s, %s );\n' % (self.dest_reg_idx, wb_val) + wb += 'if (traceData) { traceData->setData(%s); }' % \ + self.base_name + return wb + class MemOperand(Operand): def isMem(self): return 1 diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index f959951b3..de209348a 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -35,7 +35,9 @@ Import('*') if env['TARGET_ISA'] == 'mips': Source('faults.cc') Source('isa_traits.cc') + Source('regfile/misc_regfile.cc') Source('utility.cc') + Source('dsp.cc') if env['FULL_SYSTEM']: #Insert Full-System Files Here diff --git a/src/arch/mips/constants.hh b/src/arch/mips/constants.hh new file mode 100755 index 000000000..7e1739b1a --- /dev/null +++ b/src/arch/mips/constants.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ARCH_MIPS_CONSTANTS_HH__ +#define __ARCH_MIPS_CONSTANTS_HH__ + +#include "arch/mips/types.hh" +//#include "config/full_system.hh" + +namespace MipsISA +{ +} // namespace MipsISA + +#endif diff --git a/src/arch/mips/dsp.cc b/src/arch/mips/dsp.cc new file mode 100755 index 000000000..059c15a32 --- /dev/null +++ b/src/arch/mips/dsp.cc @@ -0,0 +1,1227 @@ +/* + * Copyright (c) 2003-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Brett Miller + */ + +#include "arch/mips/isa_traits.hh" +#include "arch/mips/dsp.hh" +#include "arch/mips/constants.hh" +#include "config/full_system.hh" +#include "cpu/static_inst.hh" +#include "sim/serialize.hh" +#include "base/bitfield.hh" +#include "base/misc.hh" + +using namespace MipsISA; +using namespace std; + +int32_t +MipsISA::bitrev( int32_t value ) +{ + int32_t result = 0; + int i, shift; + + for( i=0; i<16; i++ ) + { + shift = 2*i - 15; + + if( shift < 0 ) + result |= (value & 1L<<i) << -shift; + else + result |= (value & 1L<<i) >> shift; + } + + return result; +} + +uint64_t +MipsISA::dspSaturate( uint64_t value, int32_t fmt, int32_t sign, uint32_t *overflow ) +{ + int64_t svalue; + + svalue = (int64_t)value; + + switch( sign ) + { + case SIGNED: + if( svalue > (int64_t)FIXED_SMAX[fmt] ) + { + *overflow = 1; + svalue = (int64_t)FIXED_SMAX[fmt]; + } + else if( svalue < (int64_t)FIXED_SMIN[fmt] ) + { + *overflow = 1; + svalue = (int64_t)FIXED_SMIN[fmt]; + } + break; + case UNSIGNED: + if( svalue > (int64_t)FIXED_UMAX[fmt] ) + { + *overflow = 1; + svalue = FIXED_UMAX[fmt]; + } + else if( svalue < (int64_t)FIXED_UMIN[fmt] ) + { + *overflow = 1; + svalue = FIXED_UMIN[fmt]; + } + break; + } + + return( (uint64_t)svalue ); +} + +uint64_t +MipsISA::checkOverflow( uint64_t value, int32_t fmt, int32_t sign, uint32_t *overflow ) +{ + int64_t svalue; + + svalue = (int64_t)value; + + switch( sign ) + { + case SIGNED: + if( svalue > (int64_t)FIXED_SMAX[fmt] || svalue < (int64_t)FIXED_SMIN[fmt] ) + *overflow = 1; + break; + case UNSIGNED: + if( svalue > (int64_t)FIXED_UMAX[fmt] || svalue < (int64_t)FIXED_UMIN[fmt] ) + *overflow = 1; + break; + } + + return( (uint64_t)svalue ); +} + +uint64_t +MipsISA::signExtend( uint64_t value, int32_t fmt ) +{ + int32_t signpos = SIMD_NBITS[fmt]; + uint64_t sign = uint64_t(1)<<(signpos-1); + uint64_t ones = ~(0ULL); + + if( value & sign ) + value |= (ones << signpos); // extend with ones + else + value &= (ones >> (64 - signpos)); // extend with zeros + + return value; +} + +uint64_t +MipsISA::addHalfLsb( uint64_t value, int32_t lsbpos ) +{ + return( value += ULL(1) << (lsbpos-1) ); +} + +int32_t +MipsISA::dspAbs( int32_t a, int32_t fmt, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + int64_t svalue; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + svalue = (int64_t)a_values[i]; + + if( a_values[i] == FIXED_SMIN[fmt] ) + { + a_values[i] = FIXED_SMAX[fmt]; + ouflag = 1; + } + else if( svalue < 0 ) + { + a_values[i] = uint64_t( 0 - svalue ); + } + } + + simdPack( a_values, &result, fmt ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<4)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspAdd( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + if( saturate ) + a_values[i] = dspSaturate( a_values[i] + b_values[i], fmt, sign, &ouflag ); + else + a_values[i] = checkOverflow( a_values[i] + b_values[i], fmt, sign, &ouflag ); + } + + simdPack( a_values, &result, fmt ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<4)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspAddh( int32_t a, int32_t b, int32_t fmt, int32_t round, int32_t sign ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + if( round ) + a_values[i] = addHalfLsb( a_values[i] + b_values[i], 1 ) >> 1; + else + a_values[i] = ( a_values[i] + b_values[i] ) >> 1; + } + + simdPack( a_values, &result, fmt ); + + return( result ); +} + +int32_t +MipsISA::dspSub( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + if( saturate ) + a_values[i] = dspSaturate( a_values[i] - b_values[i], fmt, sign, &ouflag ); + else + a_values[i] = checkOverflow( a_values[i] - b_values[i], fmt, sign, &ouflag ); + } + + simdPack( a_values, &result, fmt ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<4)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspSubh( int32_t a, int32_t b, int32_t fmt, int32_t round, int32_t sign ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + if( round ) + a_values[i] = addHalfLsb( a_values[i] - b_values[i], 1 ) >> 1; + else + a_values[i] = ( a_values[i] - b_values[i] ) >> 1; + } + + simdPack( a_values, &result, fmt ); + + return( result ); +} + +int32_t +MipsISA::dspShll( int32_t a, uint32_t sa, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + + sa = bits( sa, SIMD_LOG2N[fmt]-1, 0 ); + simdUnpack( a, a_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + if( saturate ) + a_values[i] = dspSaturate( a_values[i] << sa, fmt, sign, &ouflag ); + else + a_values[i] = checkOverflow( a_values[i] << sa, fmt, sign, &ouflag ); + } + + simdPack( a_values, &result, fmt ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<6)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspShrl( int32_t a, uint32_t sa, int32_t fmt, int32_t sign ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint64_t a_values[SIMD_MAX_VALS]; + + sa = bits( sa, SIMD_LOG2N[fmt]-1, 0 ); + + simdUnpack( a, a_values, fmt, UNSIGNED ); + + for( i=0; i<nvals; i++ ) + a_values[i] = a_values[i] >> sa; + + simdPack( a_values, &result, fmt ); + + return( result ); +} + +int32_t +MipsISA::dspShra( int32_t a, uint32_t sa, int32_t fmt, int32_t round, int32_t sign, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint64_t a_values[SIMD_MAX_VALS]; + + sa = bits( sa, SIMD_LOG2N[fmt]-1, 0 ); + + simdUnpack( a, a_values, fmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + if( round ) + a_values[i] = addHalfLsb( a_values[i], sa ) >> sa; + else + a_values[i] = a_values[i] >> sa; + } + + simdPack( a_values, &result, fmt ); + + return( result ); +} + +int32_t +MipsISA::dspMulq( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t round, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int sa = SIMD_NBITS[fmt]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + int64_t temp; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + if( round ) + temp = (int64_t)addHalfLsb( a_values[i] * b_values[i] << 1, sa ) >> sa; + else + temp = (int64_t)(a_values[i] * b_values[i]) >> (sa - 1); + + if( a_values[i] == FIXED_SMIN[fmt] && + b_values[i] == FIXED_SMIN[fmt] ) + { + ouflag = 1; + + if( saturate ) + temp = FIXED_SMAX[fmt]; + } + + a_values[i] = temp; + } + + simdPack( a_values, &result, fmt ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<5)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspMul( int32_t a, int32_t b, int32_t fmt, int32_t saturate, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + if( saturate ) + a_values[i] = dspSaturate( a_values[i] * b_values[i], fmt, SIGNED, &ouflag ); + else + a_values[i] = checkOverflow( a_values[i] * b_values[i], fmt, SIGNED, &ouflag ); + } + + simdPack( a_values, &result, fmt ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<5)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspMuleu( int32_t a, int32_t b, int32_t mode, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[SIMD_FMT_PH]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, SIMD_FMT_QB, UNSIGNED ); + simdUnpack( b, b_values, SIMD_FMT_PH, UNSIGNED ); + + switch( mode ) + { + case MODE_L: + for( i=0; i<nvals; i++ ) + b_values[i] = dspSaturate( a_values[i+2] * b_values[i], SIMD_FMT_PH, UNSIGNED, &ouflag ); + break; + case MODE_R: + for( i=0; i<nvals; i++ ) + b_values[i] = dspSaturate( a_values[i] * b_values[i], SIMD_FMT_PH, UNSIGNED, &ouflag ); + break; + } + + simdPack( b_values, &result, SIMD_FMT_PH ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<5)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int32_t +MipsISA::dspMuleq( int32_t a, int32_t b, int32_t mode, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[SIMD_FMT_W]; + int32_t result; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + uint64_t c_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, SIMD_FMT_PH, SIGNED ); + simdUnpack( b, b_values, SIMD_FMT_PH, SIGNED ); + + switch( mode ) + { + case MODE_L: + for( i=0; i<nvals; i++ ) + c_values[i] = dspSaturate( a_values[i+1] * b_values[i+1] << 1, + SIMD_FMT_W, SIGNED, &ouflag ); + break; + case MODE_R: + for( i=0; i<nvals; i++ ) + c_values[i] = dspSaturate( a_values[i] * b_values[i] << 1, + SIMD_FMT_W, SIGNED, &ouflag ); + break; + } + + simdPack( c_values, &result, SIMD_FMT_W ); + + if( ouflag ) + writeDSPControl( dspctl, (ouflag<<5)<<DSP_CTL_POS[DSP_OUFLAG], 1<<DSP_OUFLAG); + + return( result ); +} + +int64_t +MipsISA::dspDpaq( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t infmt, + int32_t outfmt, int32_t postsat, int32_t mode, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[infmt]; + int64_t result = 0; + int64_t temp = 0; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, infmt, SIGNED ); + simdUnpack( b, b_values, infmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + switch( mode ) + { + case MODE_X: + if( a_values[nvals-1-i] == FIXED_SMIN[infmt] && + b_values[i] == FIXED_SMIN[infmt] ) + { + result += FIXED_SMAX[outfmt]; + ouflag = 1; + } + else + result += a_values[nvals-1-i] * b_values[i] << 1; + break; + default: + if( a_values[i] == FIXED_SMIN[infmt] && + b_values[i] == FIXED_SMIN[infmt] ) + { + result += FIXED_SMAX[outfmt]; + ouflag = 1; + } + else + result += a_values[i] * b_values[i] << 1; + break; + } + } + + if( postsat ) + { + if( outfmt == SIMD_FMT_L ) + { + int signa = bits( dspac, 63, 63 ); + int signb = bits( result, 63, 63 ); + + temp = dspac + result; + + if( ( signa == signb ) && + ( bits( temp, 63, 63 ) != signa ) ) + { + ouflag = 1; + if( signa ) + dspac = FIXED_SMIN[outfmt]; + else + dspac = FIXED_SMAX[outfmt]; + } + else + dspac = temp; + } + else + dspac = dspSaturate( dspac + result, outfmt, SIGNED, &ouflag ); + } + else + dspac += result; + + if( ouflag ) + *dspctl = insertBits( *dspctl, 16+ac, 16+ac, 1 ); + + return( dspac ); +} + +int64_t +MipsISA::dspDpsq( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t infmt, + int32_t outfmt, int32_t postsat, int32_t mode, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[infmt]; + int64_t result = 0; + int64_t temp = 0; + uint32_t ouflag = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, infmt, SIGNED ); + simdUnpack( b, b_values, infmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + switch( mode ) + { + case MODE_X: + if( a_values[nvals-1-i] == FIXED_SMIN[infmt] && + b_values[i] == FIXED_SMIN[infmt] ) + { + result += FIXED_SMAX[outfmt]; + ouflag = 1; + } + else + result += a_values[nvals-1-i] * b_values[i] << 1; + break; + default: + if( a_values[i] == FIXED_SMIN[infmt] && + b_values[i] == FIXED_SMIN[infmt] ) + { + result += FIXED_SMAX[outfmt]; + ouflag = 1; + } + else + result += a_values[i] * b_values[i] << 1; + break; + } + } + + if( postsat ) + { + if( outfmt == SIMD_FMT_L ) + { + int signa = bits( dspac, 63, 63 ); + int signb = bits( -result, 63, 63 ); + + temp = dspac - result; + + if( ( signa == signb ) && + ( bits( temp, 63, 63 ) != signa ) ) + { + ouflag = 1; + if( signa ) + dspac = FIXED_SMIN[outfmt]; + else + dspac = FIXED_SMAX[outfmt]; + } + else + dspac = temp; + } + else + dspac = dspSaturate( dspac - result, outfmt, SIGNED, &ouflag ); + } + else + dspac -= result; + + if( ouflag ) + *dspctl = insertBits( *dspctl, 16+ac, 16+ac, 1 ); + + return( dspac ); +} + +int64_t +MipsISA::dspDpa( int64_t dspac, int32_t a, int32_t b, int32_t ac, + int32_t fmt, int32_t sign, int32_t mode ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<2; i++ ) + { + switch( mode ) + { + case MODE_L: + dspac += a_values[nvals-1-i] * b_values[nvals-1-i]; + break; + case MODE_R: + dspac += a_values[nvals-3-i] * b_values[nvals-3-i]; + break; + case MODE_X: + dspac += a_values[nvals-1-i] * b_values[i]; + break; + } + } + + return dspac; +} + +int64_t +MipsISA::dspDps( int64_t dspac, int32_t a, int32_t b, int32_t ac, + int32_t fmt, int32_t sign, int32_t mode ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<2; i++ ) + { + switch( mode ) + { + case MODE_L: + dspac -= a_values[nvals-1-i] * b_values[nvals-1-i]; + break; + case MODE_R: + dspac -= a_values[nvals-3-i] * b_values[nvals-3-i]; + break; + case MODE_X: + dspac -= a_values[nvals-1-i] * b_values[i]; + break; + } + } + + return dspac; +} + +int64_t +MipsISA::dspMaq( int64_t dspac, int32_t a, int32_t b, int32_t ac, + int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt-1]; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + int64_t temp = 0; + uint32_t ouflag = 0; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + switch( mode ) + { + case MODE_L: + temp = a_values[i+1] * b_values[i+1] << 1; + if( a_values[i+1] == FIXED_SMIN[fmt] && b_values[i+1] == FIXED_SMIN[fmt] ) + { + temp = (int64_t)FIXED_SMAX[fmt-1]; + ouflag = 1; + } + break; + case MODE_R: + temp = a_values[i] * b_values[i] << 1; + if( a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt] ) + { + temp = (int64_t)FIXED_SMAX[fmt-1]; + ouflag = 1; + } + break; + } + + temp += dspac; + + if( saturate ) + temp = dspSaturate( temp, fmt-1, SIGNED, &ouflag ); + if( ouflag ) + *dspctl = insertBits( *dspctl, 16+ac, 16+ac, 1 ); + } + + return temp; +} + +int64_t +MipsISA::dspMulsa( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt ) +{ + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + dspac += a_values[1] * b_values[1] - a_values[0] * b_values[0]; + + return dspac; +} + +int64_t +MipsISA::dspMulsaq( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + int64_t temp[2]; + uint32_t ouflag = 0; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + for( i=nvals-1; i>-1; i-- ) + { + temp[i] = a_values[i] * b_values[i] << 1; + if( a_values[i] == FIXED_SMIN[fmt] && + b_values[i] == FIXED_SMIN[fmt] ) + { + temp[i] = FIXED_SMAX[fmt-1]; + ouflag = 1; + } + } + + dspac += temp[1] - temp[0]; + + if( ouflag ) + *dspctl = insertBits( *dspctl, 16+ac, 16+ac, 1 ); + + return dspac; +} + +void +MipsISA::dspCmp( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int ccond = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + int cc = 0; + + switch( op ) + { + case CMP_EQ: cc = ( a_values[i] == b_values[i] ); break; + case CMP_LT: cc = ( a_values[i] < b_values[i] ); break; + case CMP_LE: cc = ( a_values[i] <= b_values[i] ); break; + } + + ccond |= cc << ( DSP_CTL_POS[DSP_CCOND] + i ); + } + + writeDSPControl( dspctl, ccond, 1<<DSP_CCOND ); +} + +int32_t +MipsISA::dspCmpg( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + int cc = 0; + + switch( op ) + { + case CMP_EQ: cc = ( a_values[i] == b_values[i] ); break; + case CMP_LT: cc = ( a_values[i] < b_values[i] ); break; + case CMP_LE: cc = ( a_values[i] <= b_values[i] ); break; + } + + result |= cc << i; + } + + return( result ); +} + +int32_t +MipsISA::dspCmpgd( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, uint32_t *dspctl ) +{ + int i = 0;; + int nvals = SIMD_NVALS[fmt]; + int32_t result = 0; + int ccond = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, sign ); + simdUnpack( b, b_values, fmt, sign ); + + for( i=0; i<nvals; i++ ) + { + int cc = 0;; + + switch( op ) + { + case CMP_EQ: cc = ( a_values[i] == b_values[i] ); break; + case CMP_LT: cc = ( a_values[i] < b_values[i] ); break; + case CMP_LE: cc = ( a_values[i] <= b_values[i] ); break; + } + + result |= cc << i; + ccond |= cc << ( DSP_CTL_POS[DSP_CCOND] + i ); + } + + writeDSPControl( dspctl, ccond, 1<<DSP_CCOND ); + + return( result ); +} + +int32_t +MipsISA::dspPrece( int32_t a, int32_t infmt, int32_t insign, int32_t outfmt, int32_t outsign, int32_t mode ) +{ + int i = 0; + int sa = 0; + int ninvals = SIMD_NVALS[infmt]; + int noutvals = SIMD_NVALS[outfmt]; + int32_t result; + uint64_t in_values[SIMD_MAX_VALS]; + uint64_t out_values[SIMD_MAX_VALS]; + + if( insign == SIGNED && outsign == SIGNED ) + sa = SIMD_NBITS[infmt]; + else if( insign == UNSIGNED && outsign == SIGNED ) + sa = SIMD_NBITS[infmt] - 1; + else if( insign == UNSIGNED && outsign == UNSIGNED ) + sa = 0; + + simdUnpack( a, in_values, infmt, insign ); + + for( i=0; i<noutvals; i++ ) + { + switch( mode ) + { + case MODE_L: out_values[i] = in_values[i+(ninvals>>1)] << sa; break; + case MODE_R: out_values[i] = in_values[i] << sa; break; + case MODE_LA: out_values[i] = in_values[(i<<1)+1] << sa; break; + case MODE_RA: out_values[i] = in_values[i<<1] << sa; break; + } + } + + simdPack( out_values, &result, outfmt ); + + return( result ); +} + +int32_t +MipsISA::dspPrecrqu( int32_t a, int32_t b, uint32_t *dspctl ) +{ + int i = 0; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + uint64_t r_values[SIMD_MAX_VALS]; + uint32_t ouflag = 0; + int32_t result = 0; + + simdUnpack( a, a_values, SIMD_FMT_PH, SIGNED ); + simdUnpack( b, b_values, SIMD_FMT_PH, SIGNED ); + + for( i=0; i<2; i++ ) + { + r_values[i] = dspSaturate( (int64_t)b_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, + SIMD_FMT_QB, UNSIGNED, &ouflag ); + r_values[i+2] = dspSaturate( (int64_t)a_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, + SIMD_FMT_QB, UNSIGNED, &ouflag ); + } + + simdPack( r_values, &result, SIMD_FMT_QB ); + + if( ouflag ) + *dspctl = insertBits( *dspctl, 22, 22, 1 ); + + return result; +} + +int32_t +MipsISA::dspPrecrq( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ) +{ + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + uint64_t r_values[SIMD_MAX_VALS]; + uint32_t ouflag = 0; + int32_t result; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + r_values[1] = dspSaturate( (int64_t)addHalfLsb( a_values[0], 16 ) >> 16, + fmt+1, SIGNED, &ouflag ); + r_values[0] = dspSaturate( (int64_t)addHalfLsb( b_values[0], 16 ) >> 16, + fmt+1, SIGNED, &ouflag ); + + simdPack( r_values, &result, fmt+1 ); + + if( ouflag ) + *dspctl = insertBits( *dspctl, 22, 22, 1 ); + + return result; +} + +int32_t +MipsISA::dspPrecrSra( int32_t a, int32_t b, int32_t sa, int32_t fmt, int32_t round ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + uint64_t c_values[SIMD_MAX_VALS]; + int32_t result = 0; + + simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack( b, b_values, fmt, SIGNED ); + + for( i=0; i<nvals; i++ ) + { + if( round ) + { + c_values[i] = addHalfLsb( b_values[i], sa ) >> sa; + c_values[i+1] = addHalfLsb( a_values[i], sa ) >> sa; + } + else + { + c_values[i] = b_values[i] >> sa; + c_values[i+1] = a_values[i] >> sa; + } + } + + simdPack( c_values, &result, fmt+1 ); + + return result; +} + +int32_t +MipsISA::dspPick( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int32_t result; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + uint64_t c_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, UNSIGNED ); + simdUnpack( b, b_values, fmt, UNSIGNED ); + + for( i=0; i<nvals; i++ ) + { + int condbit = DSP_CTL_POS[DSP_CCOND] + i; + if( bits( *dspctl, condbit, condbit ) == 1 ) + c_values[i] = a_values[i]; + else + c_values[i] = b_values[i]; + } + + simdPack( c_values, &result, fmt ); + + return( result ); +} + +int32_t +MipsISA::dspPack( int32_t a, int32_t b, int32_t fmt ) +{ + int32_t result; + uint64_t a_values[SIMD_MAX_VALS]; + uint64_t b_values[SIMD_MAX_VALS]; + uint64_t c_values[SIMD_MAX_VALS]; + + simdUnpack( a, a_values, fmt, UNSIGNED ); + simdUnpack( b, b_values, fmt, UNSIGNED ); + + c_values[0] = b_values[1]; + c_values[1] = a_values[0]; + + simdPack( c_values, &result, fmt ); + + return( result ); +} + +int32_t +MipsISA::dspExtr( int64_t dspac, int32_t fmt, int32_t sa, int32_t round, int32_t saturate, uint32_t *dspctl ) +{ + int32_t result = 0; + uint32_t ouflag = 0; + int64_t temp = 0; + + sa = bits( sa, 4, 0 ); + + if( sa > 0 ) + { + if( round ) + { + temp = (int64_t)addHalfLsb( dspac, sa ); + + if( dspac > 0 && temp < 0 ) + { + ouflag = 1; + if( saturate ) + temp = FIXED_SMAX[SIMD_FMT_L]; + } + temp = temp >> sa; + } + else + temp = dspac >> sa; + } + else + temp = dspac; + + dspac = checkOverflow( dspac, fmt, SIGNED, &ouflag ); + + if( ouflag ) + { + *dspctl = insertBits( *dspctl, 23, 23, ouflag ); + + if( saturate ) + result = (int32_t)dspSaturate( temp, fmt, SIGNED, &ouflag ); + else + result = (int32_t)temp; + } + else + result = (int32_t)temp; + + return( result ); +} + +int32_t +MipsISA::dspExtp( int64_t dspac, int32_t size, uint32_t *dspctl ) +{ + int32_t pos = 0; + int32_t result = 0; + + pos = bits( *dspctl, 5, 0 ); + size = bits( size, 4, 0 ); + + if( pos - (size+1) >= -1 ) + { + result = bits( dspac, pos, pos-size ); + *dspctl = insertBits( *dspctl, 14, 14, 0 ); + } + else + { + result = 0; + *dspctl = insertBits( *dspctl, 14, 14, 1 ); + } + + return( result ); +} + +int32_t +MipsISA::dspExtpd( int64_t dspac, int32_t size, uint32_t *dspctl ) +{ + int32_t pos = 0; + int32_t result = 0; + + pos = bits( *dspctl, 5, 0 ); + size = bits( size, 4, 0 ); + + if( pos - (size+1) >= -1 ) + { + result = bits( dspac, pos, pos-size ); + *dspctl = insertBits( *dspctl, 14, 14, 0 ); + if( pos - (size+1) >= 0 ) + *dspctl = insertBits( *dspctl, 5, 0, pos - (size+1) ); + else if( (pos - (size+1)) == -1 ) + *dspctl = insertBits( *dspctl, 5, 0, 63 ); + } + else + { + result = 0; + *dspctl = insertBits( *dspctl, 14, 14, 1 ); + } + + return( result ); +} + +void +MipsISA::simdPack( uint64_t *values_ptr, int32_t *reg, int32_t fmt ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int nbits = SIMD_NBITS[fmt]; + + *reg = 0; + + for( i=0; i<nvals; i++ ) + *reg |= (int32_t)bits( values_ptr[i], nbits-1, 0 ) << nbits*i; +} + +void +MipsISA::simdUnpack( int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign ) +{ + int i = 0; + int nvals = SIMD_NVALS[fmt]; + int nbits = SIMD_NBITS[fmt]; + + switch( sign ) + { + case SIGNED: + for( i=0; i<nvals; i++ ) + { + values_ptr[i] = (uint64_t)bits( reg, nbits*(i+1)-1, nbits*i ); + values_ptr[i] = signExtend( values_ptr[i], fmt ); + } + break; + case UNSIGNED: + for( i=0; i<nvals; i++ ) + { + values_ptr[i] = (uint64_t)bits( reg, nbits*(i+1)-1, nbits*i ); + } + break; + } +} + +void +MipsISA::writeDSPControl( uint32_t *dspctl, uint32_t value, uint32_t mask ) +{ + uint32_t fmask = 0; + + if( mask & 0x01 ) fmask |= DSP_CTL_MASK[DSP_POS]; + if( mask & 0x02 ) fmask |= DSP_CTL_MASK[DSP_SCOUNT]; + if( mask & 0x04 ) fmask |= DSP_CTL_MASK[DSP_C]; + if( mask & 0x08 ) fmask |= DSP_CTL_MASK[DSP_OUFLAG]; + if( mask & 0x10 ) fmask |= DSP_CTL_MASK[DSP_CCOND]; + if( mask & 0x20 ) fmask |= DSP_CTL_MASK[DSP_EFI]; + + *dspctl &= ~fmask; + value &= fmask; + *dspctl |= value; +} + +uint32_t +MipsISA::readDSPControl( uint32_t *dspctl, uint32_t mask ) +{ + uint32_t fmask = 0; + + if( mask & 0x01 ) fmask |= DSP_CTL_MASK[DSP_POS]; + if( mask & 0x02 ) fmask |= DSP_CTL_MASK[DSP_SCOUNT]; + if( mask & 0x04 ) fmask |= DSP_CTL_MASK[DSP_C]; + if( mask & 0x08 ) fmask |= DSP_CTL_MASK[DSP_OUFLAG]; + if( mask & 0x10 ) fmask |= DSP_CTL_MASK[DSP_CCOND]; + if( mask & 0x20 ) fmask |= DSP_CTL_MASK[DSP_EFI]; + + return( *dspctl & fmask ); +} diff --git a/src/arch/mips/dsp.hh b/src/arch/mips/dsp.hh new file mode 100755 index 000000000..03ee333ec --- /dev/null +++ b/src/arch/mips/dsp.hh @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Brett Miller + */ + +#ifndef __ARCH_MIPS_DSP_HH__ +#define __ARCH_MIPS_DSP_HH__ + +#include "arch/mips/types.hh" +#include "arch/mips/isa_traits.hh" +#include "base/misc.hh" +#include "config/full_system.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace MipsISA { + + // SIMD formats + enum { + SIMD_FMT_L, // long word + SIMD_FMT_W, // word + SIMD_FMT_PH, // paired halfword + SIMD_FMT_QB, // quad byte + SIMD_NUM_FMTS + }; + + // DSPControl Fields + enum { + DSP_POS, // insertion bitfield position + DSP_SCOUNT, // insertion bitfield size + DSP_C, // carry bit + DSP_OUFLAG, // overflow-underflow flag + DSP_CCOND, // condition code + DSP_EFI, // extract fail indicator bit + DSP_NUM_FIELDS + }; + + // compare instruction operations + enum { + CMP_EQ, // equal + CMP_LT, // less than + CMP_LE // less than or equal + }; + + // SIMD operation order modes + enum { + MODE_L, // left + MODE_R, // right + MODE_LA, // left-alternate + MODE_RA, // right-alternate + MODE_X // cross + }; + + // dsp operation parameters + enum { UNSIGNED, SIGNED }; + enum { NOSATURATE, SATURATE }; + enum { NOROUND, ROUND }; + + // DSPControl field positions and masks + const uint32_t DSP_CTL_POS[DSP_NUM_FIELDS] = { 0, 7, 13, 16, 24, 14 }; + const uint32_t DSP_CTL_MASK[DSP_NUM_FIELDS] = { 0x0000003f, 0x00001f80, 0x00002000, + 0x00ff0000, 0x0f000000, 0x00004000 }; + + // SIMD format constants + const uint32_t SIMD_MAX_VALS = 4; // maximum values per register + const uint32_t SIMD_NVALS[SIMD_NUM_FMTS] = { 1, 1, 2, 4 }; // number of values in fmt + const uint32_t SIMD_NBITS[SIMD_NUM_FMTS] = { 64, 32, 16, 8 }; // number of bits per value + const uint32_t SIMD_LOG2N[SIMD_NUM_FMTS] = { 6, 5, 4, 3 }; // log2( bits per value ) + + // DSP maximum values + const uint64_t FIXED_L_SMAX = ULL(0x7fffffffffffffff); + const uint64_t FIXED_W_SMAX = ULL(0x000000007fffffff); + const uint64_t FIXED_H_SMAX = ULL(0x0000000000007fff); + const uint64_t FIXED_B_SMAX = ULL(0x000000000000007f); + const uint64_t FIXED_L_UMAX = ULL(0xffffffffffffffff); + const uint64_t FIXED_W_UMAX = ULL(0x00000000ffffffff); + const uint64_t FIXED_H_UMAX = ULL(0x000000000000ffff); + const uint64_t FIXED_B_UMAX = ULL(0x00000000000000ff); + const uint64_t FIXED_SMAX[SIMD_NUM_FMTS] = { FIXED_L_SMAX, FIXED_W_SMAX, FIXED_H_SMAX, FIXED_B_SMAX }; + const uint64_t FIXED_UMAX[SIMD_NUM_FMTS] = { FIXED_L_UMAX, FIXED_W_UMAX, FIXED_H_UMAX, FIXED_B_UMAX }; + + // DSP minimum values + const uint64_t FIXED_L_SMIN = ULL(0x8000000000000000); + const uint64_t FIXED_W_SMIN = ULL(0xffffffff80000000); + const uint64_t FIXED_H_SMIN = ULL(0xffffffffffff8000); + const uint64_t FIXED_B_SMIN = ULL(0xffffffffffffff80); + const uint64_t FIXED_L_UMIN = ULL(0x0000000000000000); + const uint64_t FIXED_W_UMIN = ULL(0x0000000000000000); + const uint64_t FIXED_H_UMIN = ULL(0x0000000000000000); + const uint64_t FIXED_B_UMIN = ULL(0x0000000000000000); + const uint64_t FIXED_SMIN[SIMD_NUM_FMTS] = { FIXED_L_SMIN, FIXED_W_SMIN, FIXED_H_SMIN, FIXED_B_SMIN }; + const uint64_t FIXED_UMIN[SIMD_NUM_FMTS] = { FIXED_L_UMIN, FIXED_W_UMIN, FIXED_H_UMIN, FIXED_B_UMIN }; + + // DSP utility functions + int32_t bitrev( int32_t value ); + uint64_t dspSaturate( uint64_t value, int32_t fmt, int32_t sign, uint32_t *overflow ); + uint64_t checkOverflow( uint64_t value, int32_t fmt, int32_t sign, uint32_t *overflow ); + uint64_t signExtend( uint64_t value, int32_t signpos ); + uint64_t addHalfLsb( uint64_t value, int32_t lsbpos ); + int32_t dspAbs( int32_t a, int32_t fmt, uint32_t *dspctl ); + int32_t dspAdd( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ); + int32_t dspAddh( int32_t a, int32_t b, int32_t fmt, int32_t round, int32_t sign ); + int32_t dspSub( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ); + int32_t dspSubh( int32_t a, int32_t b, int32_t fmt, int32_t round, int32_t sign ); + int32_t dspShll( int32_t a, uint32_t sa, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ); + int32_t dspShrl( int32_t a, uint32_t sa, int32_t fmt, int32_t sign ); + int32_t dspShra( int32_t a, uint32_t sa, int32_t fmt, int32_t round, int32_t sign, uint32_t *dspctl ); + int32_t dspMul( int32_t a, int32_t b, int32_t fmt, int32_t saturate, uint32_t *dspctl ); + int32_t dspMulq( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t round, uint32_t *dspctl ); + int32_t dspMuleu( int32_t a, int32_t b, int32_t mode, uint32_t *dspctl ); + int32_t dspMuleq( int32_t a, int32_t b, int32_t mode, uint32_t *dspctl ); + int64_t dspDpaq( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t infmt, + int32_t outfmt, int32_t postsat, int32_t mode, uint32_t *dspctl ); + int64_t dspDpsq( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t infmt, + int32_t outfmt, int32_t postsat, int32_t mode, uint32_t *dspctl ); + int64_t dspDpa( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt, int32_t sign, int32_t mode ); + int64_t dspDps( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt, int32_t sign, int32_t mode ); + int64_t dspMaq( int64_t dspac, int32_t a, int32_t b, int32_t ac, + int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl ); + int64_t dspMulsa( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt ); + int64_t dspMulsaq( int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt, uint32_t *dspctl ); + void dspCmp( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, uint32_t *dspctl ); + int32_t dspCmpg( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op ); + int32_t dspCmpgd( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, uint32_t *dspctl ); + int32_t dspPrece( int32_t a, int32_t infmt, int32_t insign, int32_t outfmt, int32_t outsign, int32_t mode ); + int32_t dspPrecrqu( int32_t a, int32_t b, uint32_t *dspctl ); + int32_t dspPrecrq( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ); + int32_t dspPrecrSra( int32_t a, int32_t b, int32_t sa, int32_t fmt, int32_t round ); + int32_t dspPick( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ); + int32_t dspPack( int32_t a, int32_t b, int32_t fmt ); + int32_t dspExtr( int64_t dspac, int32_t fmt, int32_t sa, int32_t round, + int32_t saturate, uint32_t *dspctl ); + int32_t dspExtp( int64_t dspac, int32_t size, uint32_t *dspctl ); + int32_t dspExtpd( int64_t dspac, int32_t size, uint32_t *dspctl ); + + // SIMD pack/unpack utility functions + void simdPack( uint64_t *values_ptr, int32_t *reg, int32_t fmt ); + void simdUnpack( int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign ); + + // DSPControl r/w utility functions + void writeDSPControl( uint32_t *dspctl, uint32_t value, uint32_t mask ); + uint32_t readDSPControl( uint32_t *dspctl, uint32_t mask ); +}; + +#endif diff --git a/src/arch/mips/dt_constants.hh b/src/arch/mips/dt_constants.hh new file mode 100755 index 000000000..bad1d7b8f --- /dev/null +++ b/src/arch/mips/dt_constants.hh @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Jaidev Patwardhan + */ + +#ifndef __ARCH_MIPS_DT_CONSTANTS_HH__ +#define __ARCH_MIPS_DT_CONSTANTS_HH__ + +#include "arch/mips/types.hh" +//#include "config/full_system.hh" + +namespace MipsISA +{ + // See the EJTAG Specification - Revision 4.10 + // Also see PDTrace Specification - Revision 4.30 + + // Debug Register - CP0 Reg 23, Sel 0 + const unsigned Debug_DBD = 31; + const unsigned Debug_DM_HI = 30; + const unsigned Debug_DM_LO = 30; + const unsigned Debug_NODCR = 29; + const unsigned Debug_LSNM = 28; + const unsigned Debug_DOZE = 27; + const unsigned Debug_HALT = 26; + const unsigned Debug_COUNTDM = 25; + const unsigned Debug_IBUSEP = 24; + const unsigned Debug_MCHECKEP = 23; + const unsigned Debug_CACHEEP = 22; + const unsigned Debug_DBUSEP = 21; + const unsigned Debug_IEXI_HI = 20; + const unsigned Debug_IEXI_LO = 20; + const unsigned Debug_DDBS_IMPR = 19; + const unsigned Debug_DDBL_IMPR = 18; + const unsigned Debug_EJTAGVER_2 =17; + const unsigned Debug_EJTAGVER_1 =16; + const unsigned Debug_EJTAGVER_0 =15; + const unsigned Debug_EJTAGVER_HI = 17; + const unsigned Debug_EJTAGVER_LO = 15; + const unsigned Debug_DEXC_CODE_HI = 14; + const unsigned Debug_DEXC_CODE_LO = 10; + const unsigned Debug_NOSST = 9; + const unsigned Debug_SST = 8; + const unsigned Debug_OFFLINE = 7; + const unsigned Debug_DIBIMPR = 6; + const unsigned Debug_DINT = 5; + const unsigned Debug_DIB = 4; + const unsigned Debug_DDBS = 3; + const unsigned Debug_DDBL = 2; + const unsigned Debug_DBp = 1; + const unsigned Debug_DSS = 0; + + + // TraceControl Register - CP0 Reg 23, Sel 1 + const unsigned TraceControl_TS = 31; + const unsigned TraceControl_UT = 30; + const unsigned TraceControl_TB = 27; + const unsigned TraceControl_IO = 26; + const unsigned TraceControl_D = 25; + const unsigned TraceControl_E = 24; + const unsigned TraceControl_K = 23; + const unsigned TraceControl_S = 22; + const unsigned TraceControl_U = 21; + const unsigned TraceControl_ASID_M_HI = 20; + const unsigned TraceControl_ASID_M_LO = 13; + const unsigned TraceControl_ASID_HI = 12; + const unsigned TraceControl_ASID_LO = 5; + const unsigned TraceControl_G = 4; + const unsigned TraceControl_TFCR = 3; + const unsigned TraceControl_TLSM = 2; + const unsigned TraceControl_TIM = 1; + const unsigned TraceControl_ON = 0; + + // TraceControl2 Register - CP0 Reg 23, Sel 2 + const unsigned TraceControl2_CPUIDV = 29; + const unsigned TraceControl2_CPUID_HI = 28; + const unsigned TraceControl2_CPUID_LO = 21; + const unsigned TraceControl2_TCV = 20; + const unsigned TraceControl2_TCNUM_HI = 19; + const unsigned TraceControl2_TCNUM_LO = 12; + const unsigned TraceControl2_MODE_HI = 11; + const unsigned TraceControl2_MODE_LO = 7; + const unsigned TraceControl2_VALIDMODES_HI = 6; + const unsigned TraceControl2_VALIDMODES_LO = 5; + const unsigned TraceControl2_TBI = 4; + const unsigned TraceControl2_TBU = 3; + const unsigned TraceControl2_SYP_HI = 2; + const unsigned TraceControl2_SYP_LO = 0; + + // UserTraceData Register - CP0 Reg 23, Sel 3 + // Just holds 32-bits (or 64-bits) of data + + // TraceIBPC Register - CP0 Reg 23, Sel 4 + const unsigned TraceIBPC_MB = 31; + const unsigned TraceIBPC_IE = 28; + const unsigned TraceIBPC_ATE = 27; + const unsigned TraceIBPC_IBPC8_HI = 26; + const unsigned TraceIBPC_IBPC8_LO = 24; + const unsigned TraceIBPC_IBPC7_HI = 23; + const unsigned TraceIBPC_IBPC7_LO = 21; + const unsigned TraceIBPC_IBPC6_HI = 20; + const unsigned TraceIBPC_IBPC6_LO = 18; + const unsigned TraceIBPC_IBPC5_HI = 17; + const unsigned TraceIBPC_IBPC5_LO = 15; + const unsigned TraceIBPC_IBPC4_HI = 14; + const unsigned TraceIBPC_IBPC4_LO = 12; + const unsigned TraceIBPC_IBPC3_HI = 11; + const unsigned TraceIBPC_IBPC3_LO = 9; + const unsigned TraceIBPC_IBPC2_HI = 8; + const unsigned TraceIBPC_IBPC2_LO = 6; + const unsigned TraceIBPC_IBPC1_HI = 5; + const unsigned TraceIBPC_IBPC1_LO = 3; + const unsigned TraceIBPC_IBPC0_HI = 2; + const unsigned TraceIBPC_IBPC0_LO = 0; + + + // TraceDBPC Register - CP0 Reg 23, Sel 5 + const unsigned TRACEDBPC_MB = 31; + const unsigned TRACEDBPC_DE = 28; + const unsigned TRACEDBPC_ATE = 27; + const unsigned TRACEDBPC_DBPC8_HI = 26; + const unsigned TRACEDBPC_DBPC8_LO = 24; + const unsigned TRACEDBPC_DBPC7_HI = 23; + const unsigned TRACEDBPC_DBPC7_LO = 21; + const unsigned TRACEDBPC_DBPC6_HI = 20; + const unsigned TRACEDBPC_DBPC6_LO = 18; + const unsigned TRACEDBPC_DBPC5_HI = 17; + const unsigned TRACEDBPC_DBPC5_LO = 15; + const unsigned TRACEDBPC_DBPC4_HI = 14; + const unsigned TRACEDBPC_DBPC4_LO = 12; + const unsigned TRACEDBPC_DBPC3_HI = 11; + const unsigned TRACEDBPC_DBPC3_LO = 9; + const unsigned TRACEDBPC_DBPC2_HI = 8; + const unsigned TRACEDBPC_DBPC2_LO = 6; + const unsigned TRACEDBPC_DBPC1_HI = 5; + const unsigned TRACEDBPC_DBPC1_LO = 3; + const unsigned TRACEDBPC_DBPC0_HI = 2; + const unsigned TRACEDBPC_DBPC0_LO = 0; + + // TraceIBPC2 - Not part of CP0, but part of TRACE + const unsigned TraceIBPC_IBPC14_HI = 17; + const unsigned TraceIBPC_IBPC14_LO = 15; + const unsigned TraceIBPC_IBPC13_HI = 14; + const unsigned TraceIBPC_IBPC13_LO = 12; + const unsigned TraceIBPC_IBPC12_HI = 11; + const unsigned TraceIBPC_IBPC12_LO = 9; + const unsigned TraceIBPC_IBPC11_HI = 8; + const unsigned TraceIBPC_IBPC11_LO = 6; + const unsigned TraceIBPC_IBPC10_HI = 5; + const unsigned TraceIBPC_IBPC10_LO = 3; + const unsigned TraceIBPC_IBPC9_HI = 2; + const unsigned TraceIBPC_IBPC9_LO = 0; + + + // TraceDBPC2 - Not part of CP0, but part of TRACE + const unsigned TRACEDBPC_DBPC14_HI = 17; + const unsigned TRACEDBPC_DBPC14_LO = 15; + const unsigned TRACEDBPC_DBPC13_HI = 14; + const unsigned TRACEDBPC_DBPC13_LO = 12; + const unsigned TRACEDBPC_DBPC12_HI = 11; + const unsigned TRACEDBPC_DBPC12_LO = 9; + const unsigned TRACEDBPC_DBPC11_HI = 8; + const unsigned TRACEDBPC_DBPC11_LO = 6; + const unsigned TRACEDBPC_DBPC10_HI = 5; + const unsigned TRACEDBPC_DBPC10_LO = 3; + const unsigned TRACEDBPC_DBPC9_HI = 2; + const unsigned TRACEDBPC_DBPC9_LO = 0; + + + // Debug Register 2 - CP0 Reg 23, Sel 6 + const unsigned DEBUG2_PRM = 3; + const unsigned DEBUG2_DQ = 2; + const unsigned DEBUG2_TUP = 1; + const unsigned DEBUG2_PACO = 0; + + // DEPC Register - CP0 Reg 24, Sel 0 + // Debug Exception Program Counter + const unsigned DEPC_HI = 31; + const unsigned DEPC_LO = 0; + + + + // DESAVE - CP0 Reg 31, Sel 0 + // Debug Exception Save Register + const unsigned DESAVE_HI = 31; + const unsigned DESAVE_LO = 0; + + + +} // namespace MipsISA + +#endif diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index c9e6aa75b..39a2fa997 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -54,10 +54,33 @@ FaultName ResetFault::_name = "reset"; FaultVect ResetFault::_vect = 0x0001; FaultStat ResetFault::_count; +FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable"; +FaultVect CoprocessorUnusableFault::_vect = 0xF001; +FaultStat CoprocessorUnusableFault::_count; + +FaultName ReservedInstructionFault::_name = "Reserved Instruction"; +FaultVect ReservedInstructionFault::_vect = 0x0F01; +FaultStat ReservedInstructionFault::_count; + +FaultName ThreadFault::_name = "thread"; +FaultVect ThreadFault::_vect = 0x00F1; +FaultStat ThreadFault::_count; + + FaultName ArithmeticFault::_name = "arith"; FaultVect ArithmeticFault::_vect = 0x0501; FaultStat ArithmeticFault::_count; +FaultName UnimplementedOpcodeFault::_name = "opdec"; +FaultVect UnimplementedOpcodeFault::_vect = 0x0481; +FaultStat UnimplementedOpcodeFault::_count; + +#if !FULL_SYSTEM +//FaultName PageTableFault::_name = "page_table_fault"; +//FaultVect PageTableFault::_vect = 0x0000; +//FaultStat PageTableFault::_count; +#endif + FaultName InterruptFault::_name = "interrupt"; FaultVect InterruptFault::_vect = 0x0101; FaultStat InterruptFault::_count; @@ -90,21 +113,77 @@ FaultName ItbAcvFault::_name = "iaccvio"; FaultVect ItbAcvFault::_vect = 0x0081; FaultStat ItbAcvFault::_count; -FaultName UnimplementedOpcodeFault::_name = "opdec"; -FaultVect UnimplementedOpcodeFault::_vect = 0x0481; -FaultStat UnimplementedOpcodeFault::_count; - FaultName FloatEnableFault::_name = "fen"; FaultVect FloatEnableFault::_vect = 0x0581; FaultStat FloatEnableFault::_count; -FaultName PalFault::_name = "pal"; -FaultVect PalFault::_vect = 0x2001; -FaultStat PalFault::_count; - FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; +FaultName DspStateDisabledFault::_name = "intover"; +FaultVect DspStateDisabledFault::_vect = 0x001a; +FaultStat DspStateDisabledFault::_count; + + +/*void PageTableFault::invoke(ThreadContext *tc) +{ + Process *p = tc->getProcessPtr(); + + Addr page_addr = p->pTable->pageAlign(vaddr); + + warn("%i: [tid:%i]: %s encountered @ addr %x. Allocating new page for address range %x - %x.\n", + curTick, tc->getThreadNum(), name(), vaddr, page_addr, page_addr+VMPageSize); + + p->pTable->allocate(page_addr, VMPageSize); + + return; +} +*/ + /* address is higher than the stack region or in the current stack region + if (vaddr > p->stack_base || vaddr > p->stack_min) + FaultBase::invoke(tc); + + // We've accessed the next page + if (vaddr > p->stack_min - PageBytes) { + p->stack_min -= PageBytes; + if (p->stack_base - p->stack_min > 8*1024*1024) { + warn("Already allocated Over max stack size for one thread\n"); + } + warn("%i: Allocating page for range %x - %x", + curTick, p->stack_min, p->stack_min-PageBytes); + + p->pTable->allocate(p->stack_min, PageBytes); + warn("Increasing stack size by one page."); + } else { + FaultBase::invoke(tc); + }*/ + +void ResetFault::invoke(ThreadContext *tc) +{ + warn("[tid:%i]: %s encountered.\n", tc->getThreadNum(), name()); + //tc->getCpuPtr()->reset(); +} + +void CoprocessorUnusableFault::invoke(ThreadContext *tc) +{ + panic("[tid:%i]: %s encountered.\n", tc->getThreadNum(), name()); +} + +void ReservedInstructionFault::invoke(ThreadContext *tc) +{ + panic("[tid:%i]: %s encountered.\n", tc->getThreadNum(), name()); +} + +void ThreadFault::invoke(ThreadContext *tc) +{ + panic("[tid:%i]: %s encountered.\n", tc->getThreadNum(), name()); +} + +void DspStateDisabledFault::invoke(ThreadContext *tc) +{ + panic("[tid:%i]: %s encountered.\n", tc->getThreadNum(), name()); +} + } // namespace MipsISA diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 86c742413..05a86acd7 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -80,6 +80,42 @@ class AlignmentFault : public MipsFault bool isAlignmentFault() {return true;} }; +class UnimplementedOpcodeFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} +}; + +#if !FULL_SYSTEM +//class PageTableFault : public MipsFault +//{ +//private: +// Addr vaddr; +// static FaultName _name; +// static FaultVect _vect; +// static FaultStat _count; +//public: +// PageTableFault(Addr va) +// : vaddr(va) {} +// FaultName name() {return _name;} +// FaultVect vect() {return _vect;} +// FaultStat & countStat() {return _count;} +// void invoke(ThreadContext * tc); +//}; + +static inline Fault genPageTableFault(Addr va) +{ + return new PageTableFault(va); +} +#endif + + static inline Fault genMachineCheckFault() { return new MachineCheckFault; @@ -100,8 +136,49 @@ class ResetFault : public MipsFault FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); }; +class CoprocessorUnusableFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +class ReservedInstructionFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + +class ThreadFault : public MipsFault +{ + private: + static FaultName _name; + static FaultVect _vect; + static FaultStat _count; + public: + FaultName name() {return _name;} + FaultVect vect() {return _vect;} + FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); +}; + + class ArithmeticFault : public MipsFault { protected: @@ -217,18 +294,6 @@ class ItbAcvFault : public MipsFault FaultStat & countStat() {return _count;} }; -class UnimplementedOpcodeFault : public MipsFault -{ - private: - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - FaultName name() {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} -}; - class FloatEnableFault : public MipsFault { private: @@ -241,10 +306,8 @@ class FloatEnableFault : public MipsFault FaultStat & countStat() {return _count;} }; -class PalFault : public MipsFault +class IntegerOverflowFault : public MipsFault { - protected: - bool skipFaultingInstruction() {return true;} private: static FaultName _name; static FaultVect _vect; @@ -255,7 +318,7 @@ class PalFault : public MipsFault FaultStat & countStat() {return _count;} }; -class IntegerOverflowFault : public MipsFault +class DspStateDisabledFault : public MipsFault { private: static FaultName _name; @@ -265,6 +328,7 @@ class IntegerOverflowFault : public MipsFault FaultName name() {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); }; } // MipsISA namespace diff --git a/src/arch/mips/isa/bitfields.isa b/src/arch/mips/isa/bitfields.isa index 35815bf1f..87be5ad13 100644 --- a/src/arch/mips/isa/bitfields.isa +++ b/src/arch/mips/isa/bitfields.isa @@ -28,6 +28,7 @@ // // Authors: Korey Sewell +//@TODO: Make sure the naming convention is consistent here. //////////////////////////////////////////////////////////////////// // // Bitfield definitions. @@ -58,6 +59,7 @@ def bitfield RT_RD <20:11>; def bitfield RD <15:11>; def bitfield INTIMM <15: 0>; +def bitfield RS_RT_INTIMM <25: 0>; // Floating-point operate format def bitfield FMT <25:21>; @@ -81,7 +83,7 @@ def bitfield BRANCH_CC <20:18>; // CP0 Register Select def bitfield SEL < 2: 0>; -// Interrupts +// INTERRUPTS def bitfield SC < 5: 5>; // Branch format @@ -100,3 +102,20 @@ def bitfield LSB <10: 6>; // M5 instructions def bitfield M5FUNC <7:0>; + +// DSP instructions +def bitfield OP <10:6>; +def bitfield OP_HI <10:9>; +def bitfield OP_LO <8:6>; +def bitfield DSPSA <23:21>; +def bitfield HILOSA <25:20>; +def bitfield RDDSPMASK <21:16>; +def bitfield WRDSPMASK <16:11>; +def bitfield ACSRC <22:21>; +def bitfield ACDST <12:11>; +def bitfield BP <12:11>; + +// MT Instructions +def bitfield POS <10: 6>; +def bitfield MT_U <5:5>; +def bitfield MT_H <4:4>; diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index b5d1df4fc..0af84e36b 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -35,7 +35,7 @@ // The following instructions are specified in the MIPS32 ISA // Specification. Decoding closely follows the style specified // in the MIPS32 ISA specification document starting with Table -// A-2 (document available @ www.mips.com) +// A-2 (document available @ http://www.mips.com) // decode OPCODE_HI default Unknown::unknown() { //Table A-2 @@ -55,7 +55,7 @@ decode OPCODE_HI default Unknown::unknown() { //functions 0x0: decode RS { 0x0: decode RT_RD { - 0x0: decode SA default Nop::nop(){ + 0x0: decode SA default Nop::nop() { 0x1: WarnUnimpl::ssnop(); 0x3: WarnUnimpl::ehb(); } @@ -123,10 +123,9 @@ decode OPCODE_HI default Unknown::unknown() { } 0x1: decode HINT { - 0x1: jalr_hb({{ Rd = NNPC; NNPC = Rs; }}, IsCall, Link + 0x1: jalr_hb({{ Rd = NNPC; NNPC = Rs; }}, IsCall , ClearHazards); - default: jalr({{ Rd = NNPC; NNPC = Rs; }}, IsCall, - Link); + default: jalr({{ Rd = NNPC; NNPC = Rs; }}, IsCall); } } @@ -144,34 +143,29 @@ decode OPCODE_HI default Unknown::unknown() { } 0x2: decode FUNCTION_LO { - format HiLoMiscOp { - 0x0: mfhi({{ Rd = HI; }}); - 0x1: mthi({{ HI = Rs; }}); - 0x2: mflo({{ Rd = LO; }}); - 0x3: mtlo({{ LO = Rs; }}); - } + 0x0: HiLoRsSelOp::mfhi({{ Rd = HI_RS_SEL; }}); + 0x1: HiLoRdSelOp::mthi({{ HI_RD_SEL = Rs; }}); + 0x2: HiLoRsSelOp::mflo({{ Rd = LO_RS_SEL; }}); + 0x3: HiLoRdSelOp::mtlo({{ LO_RD_SEL = Rs; }}); } 0x3: decode FUNCTION_LO { + format HiLoRdSelValOp { + 0x0: mult({{ val = Rs.sd * Rt.sd; }}); + 0x1: multu({{ val = Rs.ud * Rt.ud; }}); + } + format HiLoOp { - 0x0: mult({{ int64_t val = Rs.sd * Rt.sd; }}); - 0x1: multu({{ uint64_t val = Rs.ud * Rt.ud; }}); - 0x2: div({{ //Initialized to placate g++ - int64_t val = 0; - if (Rt.sd != 0) { - int64_t hi = Rs.sd % Rt.sd; - int64_t lo = Rs.sd / Rt.sd; - val = (hi << 32) | lo; - } - }}); - 0x3: divu({{ //Initialized to placate g++ - uint64_t val = 0; - if (Rt.ud != 0) { - uint64_t hi = Rs.ud % Rt.ud; - uint64_t lo = Rs.ud / Rt.ud; - val = (hi << 32) | lo; - } - }}); + 0x2: div({{ if (Rt.sd != 0) { + HI0 = Rs.sd % Rt.sd; + LO0 = Rs.sd / Rt.sd; + } + }}); + 0x3: divu({{ if (Rt.ud != 0) { + HI0 = Rs.ud % Rt.ud; + LO0 = Rs.ud / Rt.ud; + } + }}); } } @@ -245,6 +239,8 @@ decode OPCODE_HI default Unknown::unknown() { } 0x3: decode REGIMM_LO { + // from Table 5-4 MIPS32 REGIMM Encoding of rt Field (DSP ASE MANUAL) + 0x4: DspBranch::bposge32({{ cond = (dspctl<5:0> >= 32); }}); format WarnUnimpl { 0x7: synci(); } @@ -273,7 +269,15 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}}); 0x1: addiu({{ Rt.sw = Rs.sw + imm;}}); 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }}); - 0x3: sltiu({{ Rt.uw = ( Rs.uw < (uint32_t)sextImm ) ? 1 : 0 }}); + + //Edited to include MIPS AVP Pass/Fail instructions and + //default to the sltiu instruction + 0x3: decode RS_RT_INTIMM { + 0xabc1: BasicOp::fail({{ exitSimLoop("AVP/SRVP Test Failed"); }}); + 0xabc2: BasicOp::pass({{ exitSimLoop("AVP/SRVP Test Passed"); }}); + default: sltiu({{ Rt.uw = ( Rs.uw < (uint32_t)sextImm ) ? 1 : 0 }}); + } + 0x4: andi({{ Rt.sw = Rs.sw & zextImm;}}); 0x5: ori({{ Rt.sw = Rs.sw | zextImm;}}); 0x6: xori({{ Rt.sw = Rs.sw ^ zextImm;}}); @@ -289,47 +293,296 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode RS_MSB { 0x0: decode RS { format CP0Control { - 0x0: mfc0({{ Rt = xc->readMiscRegNoEffect(RD << 5 | SEL); }}); - 0x4: mtc0({{ xc->setMiscRegNoEffect(RD << 5 | SEL, Rt); }}); + 0x0: mfc0({{ Rt = CP0_RD_SEL; }}); + 0x4: mtc0({{ CP0_RD_SEL = Rt; }}); } - format MipsMT { - 0x8: mftr(); - 0xC: mttr(); - 0xB: decode RD { - 0x0: decode SC { - 0x0: dvpe(); - 0x1: evpe(); - } - 0x1: decode SC { - 0x0: dmt(); - 0x1: emt(); - 0xC: decode SC { - 0x0: di(); - 0x1: ei(); + + format MT_MFTR { // Decode MIPS MT MFTR instruction into sub-instructions + 0x8: decode MT_U { + 0x0: mftc0({{ data = xc->readRegOtherThread((RT << 3 | SEL) + + Ctrl_Base_DepTag); + }}); + 0x1: decode SEL { + 0x0: mftgpr({{ data = xc->readRegOtherThread(RT); }}); + 0x1: decode RT { + 0x0: mftlo_dsp0({{ data = xc->readRegOtherThread(MipsISA::DSPLo0); }}); + 0x1: mfthi_dsp0({{ data = xc->readRegOtherThread(MipsISA::DSPHi0); }}); + 0x2: mftacx_dsp0({{ data = xc->readRegOtherThread(MipsISA::DSPACX0); }}); + 0x4: mftlo_dsp1({{ data = xc->readRegOtherThread(MipsISA::DSPLo1); }}); + 0x5: mfthi_dsp1({{ data = xc->readRegOtherThread(MipsISA::DSPHi1); }}); + 0x6: mftacx_dsp1({{ data = xc->readRegOtherThread(MipsISA::DSPACX1); }}); + 0x8: mftlo_dsp2({{ data = xc->readRegOtherThread(MipsISA::DSPLo2); }}); + 0x9: mfthi_dsp2({{ data = xc->readRegOtherThread(MipsISA::DSPHi2); }}); + 0x10: mftacx_dsp2({{ data = xc->readRegOtherThread(MipsISA::DSPACX2); }}); + 0x12: mftlo_dsp3({{ data = xc->readRegOtherThread(MipsISA::DSPLo3); }}); + 0x13: mfthi_dsp3({{ data = xc->readRegOtherThread(MipsISA::DSPHi3); }}); + 0x14: mftacx_dsp3({{ data = xc->readRegOtherThread(MipsISA::DSPACX3); }}); + 0x16: mftdsp({{ data = xc->readRegOtherThread(MipsISA::DSPControl); }}); } + 0x2: decode MT_H { + 0x0: mftc1({{ data = xc->readRegOtherThread(RT + + FP_Base_DepTag); + }}); + 0x1: mfthc1({{ data = xc->readRegOtherThread(RT + + FP_Base_DepTag); + }}); + } + 0x3: cftc1({{ uint32_t fcsr_val = xc->readRegOtherThread(MipsISA::FCSR + + FP_Base_DepTag); + switch (RT) + { + case 0: + data = xc->readRegOtherThread(MipsISA::FIR + + Ctrl_Base_DepTag); + break; + case 25: + data = 0 | fcsr_val & 0xFE000000 >> 24 + | fcsr_val & 0x00800000 >> 23; + break; + case 26: + data = 0 | fcsr_val & 0x0003F07C; + break; + case 28: + data = 0 | fcsr_val & 0x00000F80 + | fcsr_val & 0x01000000 >> 21 + | fcsr_val & 0x00000003; + break; + case 31: + data = fcsr_val; + break; + default: + fatal("FP Control Value (%d) Not Valid"); + } + }}); } } } - format FailUnimpl { - 0xA: rdpgpr(); - 0xE: wrpgpr(); + format MT_MTTR { // Decode MIPS MT MTTR instruction into sub-instructions + 0xC: decode MT_U { + 0x0: mttc0({{ xc->setRegOtherThread((RD << 3 | SEL) + Ctrl_Base_DepTag, + Rt); + }}); + 0x1: decode SEL { + 0x0: mttgpr({{ xc->setRegOtherThread(RD, Rt); }}); + 0x1: decode RT { + 0x0: mttlo_dsp0({{ xc->setRegOtherThread(MipsISA::DSPLo0, Rt); + }}); + 0x1: mtthi_dsp0({{ xc->setRegOtherThread(MipsISA::DSPHi0, + Rt); + }}); + 0x2: mttacx_dsp0({{ xc->setRegOtherThread(MipsISA::DSPACX0, + Rt); + }}); + 0x4: mttlo_dsp1({{ xc->setRegOtherThread(MipsISA::DSPLo1, + Rt); + }}); + 0x5: mtthi_dsp1({{ xc->setRegOtherThread(MipsISA::DSPHi1, + Rt); + }}); + 0x6: mttacx_dsp1({{ xc->setRegOtherThread(MipsISA::DSPACX1, + Rt); + }}); + 0x8: mttlo_dsp2({{ xc->setRegOtherThread(MipsISA::DSPLo2, + Rt); + }}); + 0x9: mtthi_dsp2({{ xc->setRegOtherThread(MipsISA::DSPHi2, + Rt); + }}); + 0x10: mttacx_dsp2({{ xc->setRegOtherThread(MipsISA::DSPACX2, + Rt); + }}); + 0x12: mttlo_dsp3({{ xc->setRegOtherThread(MipsISA::DSPLo3, + Rt); + }}); + 0x13: mtthi_dsp3({{ xc->setRegOtherThread(MipsISA::DSPHi3, + Rt); + }}); + 0x14: mttacx_dsp3({{ xc->setRegOtherThread(MipsISA::DSPACX3, Rt); + }}); + 0x16: mttdsp({{ xc->setRegOtherThread(MipsISA::DSPControl, Rt); }}); + } + 0x2: mttc1({{ uint64_t data = xc->readRegOtherThread(RD + + FP_Base_DepTag); + data = insertBits(data, top_bit, bottom_bit, Rt); + xc->setRegOtherThread(RD + FP_Base_DepTag, data); + }}); + 0x3: cttc1({{ uint32_t data; + switch (RD) + { + case 25: + data = 0 | (Rt.uw<7:1> << 25) // move 31...25 + | (FCSR & 0x01000000) // bit 24 + | (FCSR & 0x004FFFFF);// bit 22...0 + break; + + case 26: + data = 0 | (FCSR & 0xFFFC0000) // move 31...18 + | Rt.uw<17:12> << 12 // bit 17...12 + | (FCSR & 0x00000F80) << 7// bit 11...7 + | Rt.uw<6:2> << 2 // bit 6...2 + | (FCSR & 0x00000002); // bit 1...0 + break; + + case 28: + data = 0 | (FCSR & 0xFE000000) // move 31...25 + | Rt.uw<2:2> << 24 // bit 24 + | (FCSR & 0x00FFF000) << 23// bit 23...12 + | Rt.uw<11:7> << 7 // bit 24 + | (FCSR & 0x000007E) + | Rt.uw<1:0>;// bit 22...0 + break; + + case 31: + data = Rt.uw; + break; + + default: + panic("FP Control Value (%d) Not Available. Ignoring Access to" + "Floating Control Status Register", FS); + } + xc->setRegOtherThread(FCSR, data); + }}); + } + } + } + + + 0xB: decode RD { + format MT_Control { + 0x0: decode POS { + 0x0: decode SEL { + 0x1: decode SC { + 0x0: dvpe({{ Rt = MVPControl; + if (VPEConf0<VPEC0_MVP:> == 1) { + MVPControl = insertBits(MVPControl, MVPC_EVP, 0); + } + }}); + 0x1: evpe({{ Rt = MVPControl; + if (VPEConf0<VPEC0_MVP:> == 1) { + MVPControl = insertBits(MVPControl, MVPC_EVP, 1); + } + }}); + } + } + } + + 0x1: decode POS { + 0xF: decode SEL { + 0x1: decode SC { + 0x0: dmt({{ Rt = VPEControl; + VPEControl = insertBits(VPEControl, VPEC_TE, 0); + }}); + 0x1: emt({{ Rt = VPEControl; + VPEControl = insertBits(VPEControl, VPEC_TE, 1); + }}); + + } + } + } + } + 0xC: decode POS { + 0x0: decode SC { + 0x0: CP0Control::di({{ + if(Config_AR >= 1) // Rev 2.0 or beyond? + { + Rt = Status; + Status_IE = 0; + } + else // Enable this else branch once we actually set values for Config on init + { + fault = new ReservedInstructionFault(); + } + }}); + 0x1: CP0Control::ei({{ + if(Config_AR >= 1) + { + Rt = Status; + Status_IE = 1; + } + else + { + fault = new ReservedInstructionFault(); + } + }}); + } + } + } + + format CP0Control { + 0xA: rdpgpr({{ + if(Config_AR >= 1) + { // Rev 2 of the architecture + Rd = xc->tcBase()->readIntReg(Rt + NumIntRegs * SRSCtl_PSS); + } + else + { + fault = new ReservedInstructionFault(); + } + }}); + 0xE: wrpgpr({{ + if(Config_AR >= 1) + { // Rev 2 of the architecture + xc->tcBase()->setIntReg(Rd + NumIntRegs * SRSCtl_PSS,Rt); + } + else + { + fault = new ReservedInstructionFault(); + } + + }}); + } + } //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO 0x1: decode FUNCTION { - format FailUnimpl { - 0x01: tlbr(); - 0x02: tlbwi(); - 0x06: tlbwr(); - 0x08: tlbp(); + format CP0Control { + 0x18: eret({{ + if(Status_ERL == 1){ + Status_ERL = 0; + NPC = ErrorEPC; + } + else{ + NPC = EPC; + Status_EXL = 0; + if(Config_AR >= 1 && SRSCtl_HSS > 0 && Status_BEV == 0){ + SRSCtl_CSS = SRSCtl_PSS; + } + } + // LLFlag = 0; + // ClearHazards(); ? + }}); + + 0x1F: deret({{ + // if(EJTagImplemented()) { + if(Debug_DM == 1){ + Debug_DM = 1; + Debug_IEXI = 0; + NPC = DEPC; + } + else + { + // Undefined; + } + //} // EJTag Implemented + //else { + // Reserved Instruction Exception + //} + }}); + } + + format FailUnimpl { + 0x01: tlbr(); // Need to hook up to TLB + 0x02: tlbwi(); // Need to hook up to TLB + 0x06: tlbwr();// Need to hook up to TLB + 0x08: tlbp();// Need to hook up to TLB - 0x18: eret(); - 0x1F: deret(); 0x20: wait(); } + } } @@ -949,45 +1202,37 @@ decode OPCODE_HI default Unknown::unknown() { 0x4: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { 0x2: IntOp::mul({{ int64_t temp1 = Rs.sd * Rt.sd; - Rd.sw = temp1<31:0> + Rd.sw = temp1<31:0>; }}); - format HiLoOp { - 0x0: madd({{ int64_t val = ((int64_t) HI << 32 | LO) + - (Rs.sd * Rt.sd); - }}); - 0x1: maddu({{ uint64_t val = ((uint64_t) HI << 32 | LO) + - (Rs.ud * Rt.ud); - }}); - 0x4: msub({{ int64_t val = ((int64_t) HI << 32 | LO) - - (Rs.sd * Rt.sd); - }}); - 0x5: msubu({{ uint64_t val = ((uint64_t) HI << 32 | LO) - - (Rs.ud * Rt.ud); - }}); + format HiLoRdSelValOp { + 0x0: madd({{ val = ((int64_t)HI_RD_SEL << 32 | LO_RD_SEL) + (Rs.sd * Rt.sd); }}); + 0x1: maddu({{ val = ((uint64_t)HI_RD_SEL << 32 | LO_RD_SEL) + (Rs.ud * Rt.ud); }}); + 0x4: msub({{ val = ((int64_t)HI_RD_SEL << 32 | LO_RD_SEL) - (Rs.sd * Rt.sd); }}); + 0x5: msubu({{ val = ((uint64_t)HI_RD_SEL << 32 | LO_RD_SEL) - (Rs.ud * Rt.ud); }}); } } 0x4: decode FUNCTION_LO { format BasicOp { 0x0: clz({{ int cnt = 32; - for (int idx = 31; idx >= 0; idx--) { - if( Rs<idx:idx> == 1) { - cnt = 31 - idx; - break; - } - } - Rd.uw = cnt; - }}); + for (int idx = 31; idx >= 0; idx--) { + if( Rs<idx:idx> == 1) { + cnt = 31 - idx; + break; + } + } + Rd.uw = cnt; + }}); 0x1: clo({{ int cnt = 32; - for (int idx = 31; idx >= 0; idx--) { - if( Rs<idx:idx> == 0) { - cnt = 31 - idx; - break; - } - } - Rd.uw = cnt; - }}); + for (int idx = 31; idx >= 0; idx--) { + if( Rs<idx:idx> == 0) { + cnt = 31 - idx; + break; + } + } + Rd.uw = cnt; + }}); } } @@ -1010,9 +1255,337 @@ decode OPCODE_HI default Unknown::unknown() { } 0x1: decode FUNCTION_LO { - format MipsMT { - 0x0: fork(); - 0x1: yield(); + format MT_Control { + 0x0: fork({{ forkThread(xc->tcBase(), fault, RD, Rs, Rt); }}, + UserMode); + 0x1: yield({{ Rd.sw = yieldThread(xc->tcBase(), fault, Rs.sw, YQMask); }}, + UserMode); + } + + //Table 5-9 MIPS32 LX Encoding of the op Field (DSP ASE MANUAL) + 0x2: decode OP_HI { + 0x0: decode OP_LO { + format LoadIndexedMemory { + 0x0: lwx({{ Rd.sw = Mem.sw; }}); + 0x4: lhx({{ Rd.sw = Mem.sh; }}); + 0x6: lbux({{ Rd.uw = Mem.ub; }}); + } + } + } + 0x4: DspIntOp::insv({{ int pos = dspctl<5:0>; + int size = dspctl<12:7>-1; + Rt.uw = insertBits( Rt.uw, pos+size, pos, Rs.uw<size:0> ); }}); + } + + 0x2: decode FUNCTION_LO { + + //Table 5-5 MIPS32 ADDU.QB Encoding of the op Field (DSP ASE MANUAL) + 0x0: decode OP_HI { + 0x0: decode OP_LO { + format DspIntOp { + 0x0: addu_qb({{ Rd.uw = dspAdd( Rs.uw, Rt.uw, SIMD_FMT_QB, + NOSATURATE, UNSIGNED, &dspctl ); }}); + 0x1: subu_qb({{ Rd.uw = dspSub( Rs.uw, Rt.uw, SIMD_FMT_QB, + NOSATURATE, UNSIGNED, &dspctl ); }}); + 0x4: addu_s_qb({{ Rd.uw = dspAdd( Rs.uw, Rt.uw, SIMD_FMT_QB, + SATURATE, UNSIGNED, &dspctl ); }}); + 0x5: subu_s_qb({{ Rd.uw = dspSub( Rs.uw, Rt.uw, SIMD_FMT_QB, + SATURATE, UNSIGNED, &dspctl ); }}); + 0x6: muleu_s_ph_qbl({{ Rd.uw = dspMuleu( Rs.uw, Rt.uw, + MODE_L, &dspctl ); }}); + 0x7: muleu_s_ph_qbr({{ Rd.uw = dspMuleu( Rs.uw, Rt.uw, + MODE_R, &dspctl ); }}); + } + } + 0x1: decode OP_LO { + format DspIntOp { + 0x0: addu_ph({{ Rd.uw = dspAdd( Rs.uw, Rt.uw, SIMD_FMT_PH, + NOSATURATE, UNSIGNED, &dspctl ); }}); + 0x1: subu_ph({{ Rd.uw = dspSub( Rs.uw, Rt.uw, SIMD_FMT_PH, + NOSATURATE, UNSIGNED, &dspctl ); }}); + 0x2: addq_ph({{ Rd.uw = dspAdd( Rs.uw, Rt.uw, SIMD_FMT_PH, + NOSATURATE, SIGNED, &dspctl ); }}); + 0x3: subq_ph({{ Rd.uw = dspSub( Rs.uw, Rt.uw, SIMD_FMT_PH, + NOSATURATE, SIGNED, &dspctl ); }}); + 0x4: addu_s_ph({{ Rd.uw = dspAdd( Rs.uw, Rt.uw, SIMD_FMT_PH, + SATURATE, UNSIGNED, &dspctl ); }}); + 0x5: subu_s_ph({{ Rd.uw = dspSub( Rs.uw, Rt.uw, SIMD_FMT_PH, + SATURATE, UNSIGNED, &dspctl ); }}); + 0x6: addq_s_ph({{ Rd.uw = dspAdd( Rs.uw, Rt.uw, SIMD_FMT_PH, + SATURATE, SIGNED, &dspctl ); }}); + 0x7: subq_s_ph({{ Rd.uw = dspSub( Rs.uw, Rt.uw, SIMD_FMT_PH, + SATURATE, SIGNED, &dspctl ); }}); + } + } + 0x2: decode OP_LO { + format DspIntOp { + 0x0: addsc({{ int64_t dresult; + dresult = Rs.ud + Rt.ud; + Rd.sw = dresult<31:0>; + dspctl = insertBits( dspctl, 13, 13, + dresult<32:32> ); }}); + 0x1: addwc({{ int64_t dresult; + dresult = Rs.sd + Rt.sd + dspctl<13:13>; + Rd.sw = dresult<31:0>; + if( dresult<32:32> != dresult<31:31> ) + dspctl = insertBits( dspctl, 20, 20, 1 ); }}); + 0x2: modsub({{ Rd.sw = (Rs.sw == 0) ? Rt.sw<23:8> : Rs.sw - Rt.sw<7:0>; }}); + 0x4: raddu_w_qb({{ Rd.uw = Rs.uw<31:24> + Rs.uw<23:16> + + Rs.uw<15:8> + Rs.uw<7:0>; }}); + 0x6: addq_s_w({{ Rd.sw = dspAdd( Rs.sw, Rt.sw, SIMD_FMT_W, + SATURATE, SIGNED, &dspctl ); }}); + 0x7: subq_s_w({{ Rd.sw = dspSub( Rs.sw, Rt.sw, SIMD_FMT_W, + SATURATE, SIGNED, &dspctl ); }}); + } + } + 0x3: decode OP_LO { + format DspIntOp { + 0x4: muleq_s_w_phl({{ Rd.sw = dspMuleq( Rs.sw, Rt.sw, + MODE_L, &dspctl ); }}); + 0x5: muleq_s_w_phr({{ Rd.sw = dspMuleq( Rs.sw, Rt.sw, + MODE_R, &dspctl ); }}); + 0x6: mulq_s_ph({{ Rd.sw = dspMulq( Rs.sw, Rt.sw, SIMD_FMT_PH, + SATURATE, NOROUND, &dspctl ); }}); + 0x7: mulq_rs_ph({{ Rd.sw = dspMulq( Rs.sw, Rt.sw, SIMD_FMT_PH, + SATURATE, ROUND, &dspctl ); }}); + } + } + } + + //Table 5-6 MIPS32 CMPU_EQ_QB Encoding of the op Field (DSP ASE MANUAL) + 0x1: decode OP_HI { + 0x0: decode OP_LO { + format DspIntOp { + 0x0: cmpu_eq_qb({{ dspCmp( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_EQ, &dspctl ); }}); + 0x1: cmpu_lt_qb({{ dspCmp( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_LT, &dspctl ); }}); + 0x2: cmpu_le_qb({{ dspCmp( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_LE, &dspctl ); }}); + 0x3: pick_qb({{ Rd.uw = dspPick( Rs.uw, Rt.uw, + SIMD_FMT_QB, &dspctl ); }}); + 0x4: cmpgu_eq_qb({{ Rd.uw = dspCmpg( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_EQ ); }}); + 0x5: cmpgu_lt_qb({{ Rd.uw = dspCmpg( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_LT ); }}); + 0x6: cmpgu_le_qb({{ Rd.uw = dspCmpg( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_LE ); }}); + } + } + 0x1: decode OP_LO { + format DspIntOp { + 0x0: cmp_eq_ph({{ dspCmp( Rs.uw, Rt.uw, SIMD_FMT_PH, + SIGNED, CMP_EQ, &dspctl ); }}); + 0x1: cmp_lt_ph({{ dspCmp( Rs.uw, Rt.uw, SIMD_FMT_PH, + SIGNED, CMP_LT, &dspctl ); }}); + 0x2: cmp_le_ph({{ dspCmp( Rs.uw, Rt.uw, SIMD_FMT_PH, + SIGNED, CMP_LE, &dspctl ); }}); + 0x3: pick_ph({{ Rd.uw = dspPick( Rs.uw, Rt.uw, + SIMD_FMT_PH, &dspctl ); }}); + 0x4: precrq_qb_ph({{ Rd.uw = Rs.uw<31:24> << 24 | + Rs.uw<15:8> << 16 | + Rt.uw<31:24> << 8 | + Rt.uw<15:8>; }}); + 0x5: precr_qb_ph({{ Rd.uw = Rs.uw<23:16> << 24 | + Rs.uw<7:0> << 16 | + Rt.uw<23:16> << 8 | + Rt.uw<7:0>; }}); + 0x6: packrl_ph({{ Rd.uw = dspPack( Rs.uw, Rt.uw, + SIMD_FMT_PH ); }}); + 0x7: precrqu_s_qb_ph({{ Rd.uw = dspPrecrqu( Rs.uw, Rt.uw, &dspctl ); }}); + } + } + 0x2: decode OP_LO { + format DspIntOp { + 0x4: precrq_ph_w({{ Rd.uw = Rs.uw<31:16> << 16 | Rt.uw<31:16>; }}); + 0x5: precrq_rs_ph_w({{ Rd.uw = dspPrecrq( Rs.uw, Rt.uw, SIMD_FMT_W, &dspctl ); }}); + } + } + 0x3: decode OP_LO { + format DspIntOp { + 0x0: cmpgdu_eq_qb({{ Rd.uw = dspCmpgd( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_EQ, &dspctl ); }}); + 0x1: cmpgdu_lt_qb({{ Rd.uw = dspCmpgd( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_LT, &dspctl ); }}); + 0x2: cmpgdu_le_qb({{ Rd.uw = dspCmpgd( Rs.uw, Rt.uw, SIMD_FMT_QB, + UNSIGNED, CMP_LE, &dspctl ); }}); + 0x6: precr_sra_ph_w({{ Rt.uw = dspPrecrSra( Rt.uw, Rs.uw, RD, + SIMD_FMT_W, NOROUND ); }}); + 0x7: precr_sra_r_ph_w({{ Rt.uw = dspPrecrSra( Rt.uw, Rs.uw, RD, + SIMD_FMT_W, ROUND ); }}); + } + } + } + + //Table 5-7 MIPS32 ABSQ_S.PH Encoding of the op Field (DSP ASE MANUAL) + 0x2: decode OP_HI { + 0x0: decode OP_LO { + format DspIntOp { + 0x1: absq_s_qb({{ Rd.sw = dspAbs( Rt.sw, SIMD_FMT_QB, &dspctl );}}); + 0x2: repl_qb({{ Rd.uw = RS_RT<7:0> << 24 | + RS_RT<7:0> << 16 | + RS_RT<7:0> << 8 | + RS_RT<7:0>; }}); + 0x3: replv_qb({{ Rd.sw = Rt.uw<7:0> << 24 | + Rt.uw<7:0> << 16 | + Rt.uw<7:0> << 8 | + Rt.uw<7:0>; }}); + 0x4: precequ_ph_qbl({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, SIGNED, MODE_L ); }}); + 0x5: precequ_ph_qbr({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, SIGNED, MODE_R ); }}); + 0x6: precequ_ph_qbla({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, SIGNED, MODE_LA ); }}); + 0x7: precequ_ph_qbra({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, SIGNED, MODE_RA ); }}); + } + } + 0x1: decode OP_LO { + format DspIntOp { + 0x1: absq_s_ph({{ Rd.sw = dspAbs( Rt.sw, SIMD_FMT_PH, &dspctl ); }}); + 0x2: repl_ph({{ Rd.uw = (sext<10>(RS_RT))<15:0> << 16 | + (sext<10>(RS_RT))<15:0>; }}); + 0x3: replv_ph({{ Rd.uw = Rt.uw<15:0> << 16 | + Rt.uw<15:0>; }}); + 0x4: preceq_w_phl({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_PH, SIGNED, + SIMD_FMT_W, SIGNED, MODE_L ); }}); + 0x5: preceq_w_phr({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_PH, SIGNED, + SIMD_FMT_W, SIGNED, MODE_R ); }}); + } + } + 0x2: decode OP_LO { + format DspIntOp { + 0x1: absq_s_w({{ Rd.sw = dspAbs( Rt.sw, SIMD_FMT_W, &dspctl ); }}); + } + } + 0x3: decode OP_LO { + 0x3: IntOp::bitrev({{ Rd.uw = bitrev( Rt.uw<15:0> ); }}); + format DspIntOp { + 0x4: preceu_ph_qbl({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, UNSIGNED, MODE_L ); }}); + 0x5: preceu_ph_qbr({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, UNSIGNED, MODE_R ); }}); + 0x6: preceu_ph_qbla({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, UNSIGNED, MODE_LA ); }}); + 0x7: preceu_ph_qbra({{ Rd.uw = dspPrece( Rt.uw, SIMD_FMT_QB, UNSIGNED, + SIMD_FMT_PH, UNSIGNED, MODE_RA ); }}); + } + } + } + + //Table 5-8 MIPS32 SHLL.QB Encoding of the op Field (DSP ASE MANUAL) + 0x3: decode OP_HI { + 0x0: decode OP_LO { + format DspIntOp { + 0x0: shll_qb({{ Rd.sw = dspShll( Rt.sw, RS, SIMD_FMT_QB, + NOSATURATE, UNSIGNED, &dspctl ); }}); + 0x1: shrl_qb({{ Rd.sw = dspShrl( Rt.sw, RS, SIMD_FMT_QB, + UNSIGNED ); }}); + 0x2: shllv_qb({{ Rd.sw = dspShll( Rt.sw, Rs.sw, SIMD_FMT_QB, + NOSATURATE, UNSIGNED, &dspctl ); }}); + 0x3: shrlv_qb({{ Rd.sw = dspShrl( Rt.sw, Rs.sw, SIMD_FMT_QB, + UNSIGNED ); }}); + 0x4: shra_qb({{ Rd.sw = dspShra( Rt.sw, RS, SIMD_FMT_QB, + NOROUND, SIGNED, &dspctl ); }}); + 0x5: shra_r_qb({{ Rd.sw = dspShra( Rt.sw, RS, SIMD_FMT_QB, + ROUND, SIGNED, &dspctl ); }}); + 0x6: shrav_qb({{ Rd.sw = dspShra( Rt.sw, Rs.sw, SIMD_FMT_QB, + NOROUND, SIGNED, &dspctl ); }}); + 0x7: shrav_r_qb({{ Rd.sw = dspShra( Rt.sw, Rs.sw, SIMD_FMT_QB, + ROUND, SIGNED, &dspctl ); }}); + } + } + 0x1: decode OP_LO { + format DspIntOp { + 0x0: shll_ph({{ Rd.uw = dspShll( Rt.uw, RS, SIMD_FMT_PH, + NOSATURATE, SIGNED, &dspctl ); }}); + 0x1: shra_ph({{ Rd.sw = dspShra( Rt.sw, RS, SIMD_FMT_PH, + NOROUND, SIGNED, &dspctl ); }}); + 0x2: shllv_ph({{ Rd.sw = dspShll( Rt.sw, Rs.sw, SIMD_FMT_PH, + NOSATURATE, SIGNED, &dspctl ); }}); + 0x3: shrav_ph({{ Rd.sw = dspShra( Rt.sw, Rs.sw, SIMD_FMT_PH, + NOROUND, SIGNED, &dspctl ); }}); + 0x4: shll_s_ph({{ Rd.sw = dspShll( Rt.sw, RS, SIMD_FMT_PH, + SATURATE, SIGNED, &dspctl ); }}); + 0x5: shra_r_ph({{ Rd.sw = dspShra( Rt.sw, RS, SIMD_FMT_PH, + ROUND, SIGNED, &dspctl ); }}); + 0x6: shllv_s_ph({{ Rd.sw = dspShll( Rt.sw, Rs.sw, SIMD_FMT_PH, + SATURATE, SIGNED, &dspctl ); }}); + 0x7: shrav_r_ph({{ Rd.sw = dspShra( Rt.sw, Rs.sw, SIMD_FMT_PH, + ROUND, SIGNED, &dspctl ); }}); + } + } + 0x2: decode OP_LO { + format DspIntOp { + 0x4: shll_s_w({{ Rd.sw = dspShll( Rt.sw, RS, SIMD_FMT_W, + SATURATE, SIGNED, &dspctl ); }}); + 0x5: shra_r_w({{ Rd.sw = dspShra( Rt.sw, RS, SIMD_FMT_W, + ROUND, SIGNED, &dspctl ); }}); + 0x6: shllv_s_w({{ Rd.sw = dspShll( Rt.sw, Rs.sw, SIMD_FMT_W, + SATURATE, SIGNED, &dspctl ); }}); + 0x7: shrav_r_w({{ Rd.sw = dspShra( Rt.sw, Rs.sw, SIMD_FMT_W, + ROUND, SIGNED, &dspctl ); }}); + } + } + 0x3: decode OP_LO { + format DspIntOp { + 0x1: shrl_ph({{ Rd.sw = dspShrl( Rt.sw, RS, SIMD_FMT_PH, + UNSIGNED ); }}); + 0x3: shrlv_ph({{ Rd.sw = dspShrl( Rt.sw, Rs.sw, SIMD_FMT_PH, + UNSIGNED ); }}); + } + } + } + } + + 0x3: decode FUNCTION_LO { + + //Table 3.12 MIPS32 ADDUH.QB Encoding of the op Field (DSP ASE Rev2 Manual) + 0x0: decode OP_HI { + 0x0: decode OP_LO { + format DspIntOp { + 0x0: adduh_qb({{ Rd.uw = dspAddh( Rs.sw, Rt.sw, SIMD_FMT_QB, + NOROUND, UNSIGNED ); }}); + 0x1: subuh_qb({{ Rd.uw = dspSubh( Rs.sw, Rt.sw, SIMD_FMT_QB, + NOROUND, UNSIGNED ); }}); + 0x2: adduh_r_qb({{ Rd.uw = dspAddh( Rs.sw, Rt.sw, SIMD_FMT_QB, + ROUND, UNSIGNED ); }}); + 0x3: subuh_r_qb({{ Rd.uw = dspSubh( Rs.sw, Rt.sw, SIMD_FMT_QB, + ROUND, UNSIGNED ); }}); + } + } + 0x1: decode OP_LO { + format DspIntOp { + 0x0: addqh_ph({{ Rd.uw = dspAddh( Rs.sw, Rt.sw, SIMD_FMT_PH, + NOROUND, SIGNED ); }}); + 0x1: subqh_ph({{ Rd.uw = dspSubh( Rs.sw, Rt.sw, SIMD_FMT_PH, + NOROUND, SIGNED ); }}); + 0x2: addqh_r_ph({{ Rd.uw = dspAddh( Rs.sw, Rt.sw, SIMD_FMT_PH, + ROUND, SIGNED ); }}); + 0x3: subqh_r_ph({{ Rd.uw = dspSubh( Rs.sw, Rt.sw, SIMD_FMT_PH, + ROUND, SIGNED ); }}); + 0x4: mul_ph({{ Rd.sw = dspMul( Rs.sw, Rt.sw, SIMD_FMT_PH, + NOSATURATE, &dspctl ); }}); + 0x6: mul_s_ph({{ Rd.sw = dspMul( Rs.sw, Rt.sw, SIMD_FMT_PH, + SATURATE, &dspctl ); }}); + } + } + 0x2: decode OP_LO { + format DspIntOp { + 0x0: addqh_w({{ Rd.uw = dspAddh( Rs.sw, Rt.sw, SIMD_FMT_W, + NOROUND, SIGNED ); }}); + 0x1: subqh_w({{ Rd.uw = dspSubh( Rs.sw, Rt.sw, SIMD_FMT_W, + NOROUND, SIGNED ); }}); + 0x2: addqh_r_w({{ Rd.uw = dspAddh( Rs.sw, Rt.sw, SIMD_FMT_W, + ROUND, SIGNED ); }}); + 0x3: subqh_r_w({{ Rd.uw = dspSubh( Rs.sw, Rt.sw, SIMD_FMT_W, + ROUND, SIGNED ); }}); + 0x6: mulq_s_w({{ Rd.sw = dspMulq( Rs.sw, Rt.sw, SIMD_FMT_W, + SATURATE, NOROUND, &dspctl ); }}); + 0x7: mulq_rs_w({{ Rd.sw = dspMulq( Rs.sw, Rt.sw, SIMD_FMT_W, + SATURATE, ROUND, &dspctl ); }}); + } + } } } @@ -1020,9 +1593,9 @@ decode OPCODE_HI default Unknown::unknown() { 0x4: decode SA { format BasicOp { 0x02: wsbh({{ Rd.uw = Rt.uw<23:16> << 24 | - Rt.uw<31:24> << 16 | - Rt.uw<7:0> << 8 | - Rt.uw<15:8>; + Rt.uw<31:24> << 16 | + Rt.uw<7:0> << 8 | + Rt.uw<15:8>; }}); 0x10: seb({{ Rd.sw = Rt.sb; }}); 0x18: seh({{ Rd.sw = Rt.sh; }}); @@ -1030,8 +1603,145 @@ decode OPCODE_HI default Unknown::unknown() { } 0x6: decode FUNCTION_LO { + + //Table 5-10 MIPS32 DPAQ.W.PH Encoding of the op Field (DSP ASE MANUAL) + 0x0: decode OP_HI { + 0x0: decode OP_LO { + format DspHiLoOp { + 0x0: dpa_w_ph({{ dspac = dspDpa( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_PH, SIGNED, MODE_L ); }}); + 0x1: dps_w_ph({{ dspac = dspDps( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_PH, SIGNED, MODE_L ); }}); + 0x2: mulsa_w_ph({{ dspac = dspMulsa( dspac, Rs.sw, Rt.sw, + ACDST, SIMD_FMT_PH ); }}); + 0x3: dpau_h_qbl({{ dspac = dspDpa( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_QB, UNSIGNED, MODE_L ); }}); + 0x4: dpaq_s_w_ph({{ dspac = dspDpaq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_PH, + SIMD_FMT_W, NOSATURATE, MODE_L, &dspctl ); }}); + 0x5: dpsq_s_w_ph({{ dspac = dspDpsq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_PH, + SIMD_FMT_W, NOSATURATE, MODE_L, &dspctl ); }}); + 0x6: mulsaq_s_w_ph({{ dspac = dspMulsaq( dspac, Rs.sw, Rt.sw, + ACDST, SIMD_FMT_PH, &dspctl ); }}); + 0x7: dpau_h_qbr({{ dspac = dspDpa( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_QB, UNSIGNED, MODE_R ); }}); + } + } + 0x1: decode OP_LO { + format DspHiLoOp { + 0x0: dpax_w_ph({{ dspac = dspDpa( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_PH, SIGNED, MODE_X ); }}); + 0x1: dpsx_w_ph({{ dspac = dspDps( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_PH, SIGNED, MODE_X ); }}); + 0x3: dpsu_h_qbl({{ dspac = dspDps( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_QB, UNSIGNED, MODE_L ); }}); + 0x4: dpaq_sa_l_w({{ dspac = dspDpaq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_W, + SIMD_FMT_L, SATURATE, MODE_L, &dspctl ); }}); + 0x5: dpsq_sa_l_w({{ dspac = dspDpsq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_W, + SIMD_FMT_L, SATURATE, MODE_L, &dspctl ); }}); + 0x7: dpsu_h_qbr({{ dspac = dspDps( dspac, Rs.sw, Rt.sw, ACDST, + SIMD_FMT_QB, UNSIGNED, MODE_R ); }}); + } + } + 0x2: decode OP_LO { + format DspHiLoOp { + 0x0: maq_sa_w_phl({{ dspac = dspMaq( dspac, Rs.uw, Rt.uw, ACDST, SIMD_FMT_PH, + MODE_L, SATURATE, &dspctl ); }}); + 0x2: maq_sa_w_phr({{ dspac = dspMaq( dspac, Rs.uw, Rt.uw, ACDST, SIMD_FMT_PH, + MODE_R, SATURATE, &dspctl ); }}); + 0x4: maq_s_w_phl({{ dspac = dspMaq( dspac, Rs.uw, Rt.uw, ACDST, SIMD_FMT_PH, + MODE_L, NOSATURATE, &dspctl ); }}); + 0x6: maq_s_w_phr({{ dspac = dspMaq( dspac, Rs.uw, Rt.uw, ACDST, SIMD_FMT_PH, + MODE_R, NOSATURATE, &dspctl ); }}); + } + } + 0x3: decode OP_LO { + format DspHiLoOp { + 0x0: dpaqx_s_w_ph({{ dspac = dspDpaq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_PH, + SIMD_FMT_W, NOSATURATE, MODE_X, &dspctl ); }}); + 0x1: dpsqx_s_w_ph({{ dspac = dspDpsq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_PH, + SIMD_FMT_W, NOSATURATE, MODE_X, &dspctl ); }}); + 0x2: dpaqx_sa_w_ph({{ dspac = dspDpaq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_PH, + SIMD_FMT_W, SATURATE, MODE_X, &dspctl ); }}); + 0x3: dpsqx_sa_w_ph({{ dspac = dspDpsq( dspac, Rs.sw, Rt.sw, ACDST, SIMD_FMT_PH, + SIMD_FMT_W, SATURATE, MODE_X, &dspctl ); }}); + } + } + } + + //Table 3.3 MIPS32 APPEND Encoding of the op Field + 0x1: decode OP_HI { + 0x0: decode OP_LO { + format IntOp { + 0x0: append({{ Rt.uw = (Rt.uw << RD) | bits(Rs.uw,RD-1,0); }}); + 0x1: prepend({{ Rt.uw = (Rt.uw >> RD) | (bits(Rs.uw,RD-1,0) << 32-RD); }}); + } + } + 0x2: decode OP_LO { + format IntOp { + 0x0: balign({{ Rt.uw = (Rt.uw << (8*BP)) | (Rs.uw >> (8*(4-BP))); }}); + } + } + } + 0x7: FailUnimpl::rdhwr(); } + + 0x7: decode FUNCTION_LO { + + //Table 5-11 MIPS32 EXTR.W Encoding of the op Field (DSP ASE MANUAL) + 0x0: decode OP_HI { + 0x0: decode OP_LO { + format DspHiLoOp { + 0x0: extr_w({{ Rt.uw = dspExtr( dspac, SIMD_FMT_W, RS, + NOROUND, NOSATURATE, &dspctl ); }}); + 0x1: extrv_w({{ Rt.uw = dspExtr( dspac, SIMD_FMT_W, Rs.uw, + NOROUND, NOSATURATE, &dspctl ); }}); + 0x2: extp({{ Rt.uw = dspExtp( dspac, RS, &dspctl ); }}); + 0x3: extpv({{ Rt.uw = dspExtp( dspac, Rs.uw, &dspctl ); }}); + 0x4: extr_r_w({{ Rt.uw = dspExtr( dspac, SIMD_FMT_W, RS, + ROUND, NOSATURATE, &dspctl ); }}); + 0x5: extrv_r_w({{ Rt.uw = dspExtr( dspac, SIMD_FMT_W, Rs.uw, + ROUND, NOSATURATE, &dspctl ); }}); + 0x6: extr_rs_w({{ Rt.uw = dspExtr( dspac, SIMD_FMT_W, RS, + ROUND, SATURATE, &dspctl ); }}); + 0x7: extrv_rs_w({{ Rt.uw = dspExtr( dspac, SIMD_FMT_W, Rs.uw, + ROUND, SATURATE, &dspctl ); }}); + } + } + 0x1: decode OP_LO { + format DspHiLoOp { + 0x2: extpdp({{ Rt.uw = dspExtpd( dspac, RS, &dspctl ); }}); + 0x3: extpdpv({{ Rt.uw = dspExtpd( dspac, Rs.uw, &dspctl ); }}); + 0x6: extr_s_h({{ Rt.uw = dspExtr( dspac, SIMD_FMT_PH, RS, + NOROUND, SATURATE, &dspctl ); }}); + 0x7: extrv_s_h({{ Rt.uw = dspExtr( dspac, SIMD_FMT_PH, Rs.uw, + NOROUND, SATURATE, &dspctl ); }}); + } + } + 0x2: decode OP_LO { + format DspIntOp { + 0x2: rddsp({{ Rd.uw = readDSPControl( &dspctl, RDDSPMASK ); }}); + 0x3: wrdsp({{ writeDSPControl( &dspctl, Rs.uw, WRDSPMASK ); }}); + } + } + 0x3: decode OP_LO { + format DspHiLoOp { + 0x2: shilo({{ if( sext<6>(HILOSA) < 0 ) + dspac = (uint64_t)dspac << -sext<6>(HILOSA); + else + dspac = (uint64_t)dspac >> sext<6>(HILOSA); }}); + 0x3: shilov({{ if( sext<6>(Rs.sw<5:0>) < 0 ) + dspac = (uint64_t)dspac << -sext<6>(Rs.sw<5:0>); + else + dspac = (uint64_t)dspac >> sext<6>(Rs.sw<5:0>); }}); + 0x7: mthlip({{ dspac = dspac << 32; + dspac |= Rs.uw; + dspctl = insertBits( dspctl, 5, 0, + dspctl<5:0>+32 ); }}); + } + } + } + } } } @@ -1047,13 +1757,13 @@ decode OPCODE_HI default Unknown::unknown() { format LoadUnalignedMemory { 0x2: lwl({{ uint32_t mem_shift = 24 - (8 * byte_offset); Rt.uw = mem_word << mem_shift | - Rt.uw & mask(mem_shift); + Rt.uw & mask(mem_shift); }}); 0x6: lwr({{ uint32_t mem_shift = 8 * byte_offset; Rt.uw = Rt.uw & (mask(mem_shift) << (32 - mem_shift)) | - mem_word >> mem_shift; + mem_word >> mem_shift; }}); - } + } } 0x5: decode OPCODE_LO { @@ -1093,9 +1803,6 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: StoreCond::sc({{ Mem.uw = Rt.uw;}}, {{ uint64_t tmp = write_result; Rt.uw = (tmp == 0 || tmp == 1) ? tmp : Rt.uw; - if (tmp == 1) { - xc->setStCondFailures(0); - } }}, mem_flags=LOCKED, inst_flags = IsStoreConditional); format StoreMemory { diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index a67f04dca..e959e4c1b 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -36,6 +36,7 @@ output header {{ #include <iostream> + using namespace std; /** * Base class for instructions whose disassembly is not purely a @@ -216,7 +217,7 @@ output decoder {{ } }}; -def format Branch(code,*opt_flags) {{ +def format Branch(code, *opt_flags) {{ not_taken_code = ' NNPC = NNPC;\n' not_taken_code += '} \n' @@ -230,13 +231,13 @@ def format Branch(code,*opt_flags) {{ not_taken_code = ' NPC = NNPC;\n' not_taken_code += ' NNPC = NNPC + 4;\n' not_taken_code += '} \n' - inst_flags = ('IsCondDelaySlot', ) + inst_flags += ('IsCondDelaySlot', ) else: inst_flags += (x, ) #Take into account uncond. branch instruction - if 'cond == 1' in code: - inst_flags += ('IsUnCondControl', ) + if 'cond = 1' in code: + inst_flags += ('IsUncondControl', ) else: inst_flags += ('IsCondControl', ) @@ -254,6 +255,51 @@ def format Branch(code,*opt_flags) {{ exec_output = BasicExecute.subst(iop) }}; +def format DspBranch(code, *opt_flags) {{ + not_taken_code = ' NNPC = NNPC;\n' + not_taken_code += '} \n' + + #Build Instruction Flags + #Use Link & Likely Flags to Add Link/Condition Code + inst_flags = ('IsDirectControl', ) + for x in opt_flags: + if x == 'Link': + code += 'R31 = NNPC;\n' + elif x == 'Likely': + not_taken_code = ' NPC = NNPC;\n' + not_taken_code += ' NNPC = NNPC + 4;\n' + not_taken_code += '} \n' + inst_flags += ('IsCondDelaySlot', ) + else: + inst_flags += (x, ) + + #Take into account uncond. branch instruction + if 'cond = 1' in code: + inst_flags += ('IsUncondControl', ) + else: + inst_flags += ('IsCondControl', ) + + #Declaration code + decl_code = 'bool cond;\n' + decl_code += 'uint32_t dspctl;\n' + + #Fetch code + fetch_code = 'dspctl = DSPControl;\n' + + #Condition code + code = decl_code + fetch_code + code + code += 'if (cond) {\n' + code += ' NNPC = NPC + disp;\n' + code += '} else {\n' + code += not_taken_code + + iop = InstObjParams(name, Name, 'Branch', code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + def format Jump(code, *opt_flags) {{ #Build Instruction Flags #Use Link Flag to Add Link Code diff --git a/src/arch/mips/isa/formats/control.isa b/src/arch/mips/isa/formats/control.isa index 1c63a6e22..1de2948be 100644 --- a/src/arch/mips/isa/formats/control.isa +++ b/src/arch/mips/isa/formats/control.isa @@ -30,45 +30,32 @@ //////////////////////////////////////////////////////////////////// // -// Integer operate instructions +// Coprocessor instructions // //Outputs to decoder.hh output header {{ - class Control : public MipsStaticInst - { - protected: - - /// Constructor - Control(const char *mnem, MachInst _machInst, OpClass __opClass) : - MipsStaticInst(mnem, _machInst, __opClass) - { - } - - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; - - class CP0Control : public Control + class CP0Control : public MipsStaticInst { protected: /// Constructor CP0Control(const char *mnem, MachInst _machInst, OpClass __opClass) : - Control(mnem, _machInst, __opClass) + MipsStaticInst(mnem, _machInst, __opClass) { } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; - class CP1Control : public Control + class CP1Control : public MipsStaticInst { protected: /// Constructor CP1Control(const char *mnem, MachInst _machInst, OpClass __opClass) : - Control(mnem, _machInst, __opClass) + MipsStaticInst(mnem, _machInst, __opClass) { } @@ -77,46 +64,34 @@ output header {{ }}; -//Outputs to decoder.cc -output decoder {{ - std::string Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const +// Basic instruction class execute method template. +def template ControlExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - std::stringstream ss; - - ccprintf(ss, "%-10s ", mnemonic); - - if (mnemonic == "mfc0" || mnemonic == "mtc0") { - ccprintf(ss, "%-10s %d,%d,%d", mnemonic,RT,RD,SEL); - } else { - - // just print the first dest... if there's a second one, - // it's generally implicit - if (_numDestRegs > 0) { - printReg(ss, _destRegIdx[0]); - } - - ss << ", "; - - // just print the first two source regs... if there's - // a third one, it's a read-modify-write dest (Rc), - // e.g. for CMOVxx - if (_numSrcRegs > 0) { - printReg(ss, _srcRegIdx[0]); + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + + if (isCoprocessorEnabled(xc, 0)) { + %(code)s; + } else { + fault = new CoprocessorUnusableFault(); } - if (_numSrcRegs > 1) { - ss << ", "; - printReg(ss, _srcRegIdx[1]); + if(fault == NoFault) + { + %(op_wb)s; } - } - - return ss.str(); + return fault; } +}}; +//Outputs to decoder.cc +output decoder {{ std::string CP0Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; - ccprintf(ss, "%-10s r%d, r%d, %d", mnemonic, RT, RD, SEL); + ccprintf(ss, "%-10s r%d, %d, %d", mnemonic, RT, RD, SEL); return ss.str(); } @@ -129,28 +104,50 @@ output decoder {{ }}; -def format System(code, *flags) {{ - iop = InstObjParams(name, Name, 'Control', code, flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) +output exec {{ + bool isCoprocessorEnabled(%(CPU_exec_context)s *xc, unsigned cop_num) + { + switch(cop_num) + { + case 0: +#if FULL_SYSTEM + if((xc->readMiscReg(MipsISA::Status) & 0x10000006) == 0 && (xc->readMiscReg(MipsISA::Debug) & 0x40000000 ) == 0) { + // Unable to use Status_CU0, etc directly, using bitfields & masks + return false; + } +#else + //printf("Syscall Emulation Mode: CP0 Enable Check defaults to TRUE\n"); +#endif + break; + case 1: + break; + case 2: + break; + case 3: + break; + default: panic("Invalid Coprocessor Number Specified"); + break; + } + return true; + } }}; def format CP0Control(code, *flags) {{ - iop = InstObjParams(name, Name, 'CP0Control', code, flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + flags += ('IsNonSpeculative', ) + iop = InstObjParams(name, Name, 'CP0Control', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = ControlExecute.subst(iop) }}; def format CP1Control(code, *flags) {{ - iop = InstObjParams(name, Name, 'CP1Control', code, flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + flags += ('IsNonSpeculative', ) + iop = InstObjParams(name, Name, 'CP1Control', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = ControlExecute.subst(iop) }}; diff --git a/src/arch/mips/isa/formats/dsp.isa b/src/arch/mips/isa/formats/dsp.isa new file mode 100755 index 000000000..768f3dd7d --- /dev/null +++ b/src/arch/mips/isa/formats/dsp.isa @@ -0,0 +1,218 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2006 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Korey Sewell + +//////////////////////////////////////////////////////////////////// +// +// DSP integer operate instructions +// +output header {{ +#include <iostream> + using namespace std; + /** + * Base class for integer operations. + */ + class DspIntOp : public MipsStaticInst + { + protected: + + /// Constructor + DspIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + MipsStaticInst(mnem, _machInst, __opClass) + { + } + }; + + class DspHiLoOp : public MipsStaticInst + { + protected: + + /// Constructor + DspHiLoOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + MipsStaticInst(mnem, _machInst, __opClass) + { + } + }; +}}; + +// Dsp instruction class execute method template. +def template DspExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + + if (isDspPresent(xc)) + { + if (isDspEnabled(xc)) + { + %(op_rd)s; + %(code)s; + } + else + { + fault = new DspStateDisabledFault(); + } + } + else + { + fault = new ReservedInstructionFault(); + } + + if(fault == NoFault) + { + %(op_wb)s; + } + return fault; + } +}}; + +// DspHiLo instruction class execute method template. +def template DspHiLoExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + + if (isDspPresent(xc)) + { + if (isDspEnabled(xc)) + { + %(op_rd)s; + %(code)s; + } + else + { + fault = new DspStateDisabledFault(); + } + } + else + { + fault = new ReservedInstructionFault(); + } + + if(fault == NoFault) + { + %(op_wb)s; + //If there are 2 Destination Registers then + //concatenate the values for the traceData + if(traceData && _numDestRegs == 2) { + // FIXME - set the trace value correctly here + //uint64_t hilo_final_val = (uint64_t)HI_RD_SEL << 32 | LO_RD_SEL; + //traceData->setData(hilo_final_val); + } + } + return fault; + } +}}; + +//Outputs to decoder.cc +output decoder {{ +}}; + +output exec {{ + bool isDspEnabled(%(CPU_exec_context)s *xc) + { +#if FULL_SYSTEM + if( bits( xc->readMiscReg(MipsISA::Status), 24, 24 ) == 0 ) + return false; +#else + //printf("Syscall Emulation Mode: isDspEnabled() check defaults to TRUE\n"); +#endif + return true; + } +}}; + +output exec {{ + bool isDspPresent(%(CPU_exec_context)s *xc) + { +#if FULL_SYSTEM + if( bits( xc->readMiscReg(MipsISA::Config3), 10, 10 ) == 0 ) + return false; +#else + //printf("Syscall Emulation Mode: isDspPresent() check defaults to TRUE\n"); +#endif + return true; + } +}}; + +// add code to fetch the DSPControl register +// and write it back after execution, giving +// the instruction the opportunity to modify +// it if necessary +def format DspIntOp(code, *opt_flags) {{ + + decl_code = 'uint32_t dspctl;\n' + decl_code += 'dspctl = DSPControl;\n' + + write_code = 'DSPControl = dspctl;\n' + + code = decl_code + code + write_code + + iop = InstObjParams(name, Name, 'DspIntOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = DspExecute.subst(iop) +}}; + +// add code to fetch the DSPControl register +// and write it back after execution, giving +// the instruction the opportunity to modify +// it if necessary; also, fetch the appropriate +// HI/LO register pair, based on the AC +// instruction field. + +def format DspHiLoOp(code, *opt_flags) {{ + + decl_code = 'int64_t dspac;\n' + decl_code += 'uint32_t dspctl;\n' + + fetch_code = 'dspctl = DSPControl;\n' + fetch_code += 'dspac = HI_RD_SEL;\n' + fetch_code += 'dspac = dspac << 32 | LO_RD_SEL;\n' + + write_code = 'DSPControl = dspctl;\n' + write_code += 'HI_RD_SEL = dspac<63:32>;\n' + write_code += 'LO_RD_SEL = dspac<31:0>;\n' + + code = decl_code + fetch_code + code + write_code + + iop = InstObjParams(name, Name, 'DspHiLoOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = DspHiLoExecute.subst(iop) + +}}; + + + diff --git a/src/arch/mips/isa/formats/formats.isa b/src/arch/mips/isa/formats/formats.isa index 4c3eec132..1cff9732f 100644 --- a/src/arch/mips/isa/formats/formats.isa +++ b/src/arch/mips/isa/formats/formats.isa @@ -44,6 +44,9 @@ //Include the integer formats ##include "int.isa" +//Include the DSP integer format +##include "dsp.isa" + //Include the floatOp format ##include "fp.isa" diff --git a/src/arch/mips/isa/formats/fp.isa b/src/arch/mips/isa/formats/fp.isa index ac6805cc7..4b340e2e6 100644 --- a/src/arch/mips/isa/formats/fp.isa +++ b/src/arch/mips/isa/formats/fp.isa @@ -87,6 +87,12 @@ output decoder {{ }}; output exec {{ + inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) + { + //@TODO: Implement correct CP0 checks to see if the CP1 + // unit is enable or not + return NoFault; + } //If any operand is Nan return the appropriate QNaN template <class T> @@ -145,7 +151,7 @@ output exec {{ uint32_t fcsr_bits = cpu->tcBase()->readFloatRegBits(FCSR); //Write FCSR from FloatRegFile - cpu->tcBase()->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits)); + cpu->tcBase()->setFloatRegOperandBits(FCSR, genInvalidVector(fcsr_bits)); if (traceData) { traceData->setData(mips_nan); } return true; @@ -160,6 +166,7 @@ output exec {{ //Read FCSR from FloatRegFile uint32_t fcsr = cpu->tcBase()->readFloatRegBits(FCSR); + // TODO: Use utility function here fcsr = bits(fcsr, 31, 18) << 18 | bits(fcsr, 11, 0); //Write FCSR from FloatRegFile diff --git a/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa index 2f131f6d9..7fa8e4817 100644 --- a/src/arch/mips/isa/formats/int.isa +++ b/src/arch/mips/isa/formats/int.isa @@ -34,6 +34,7 @@ // output header {{ #include <iostream> + using namespace std; /** * Base class for integer operations. */ @@ -64,12 +65,12 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; - class HiLoMiscOp: public HiLoOp + class HiLoRsSelOp: public HiLoOp { protected: /// Constructor - HiLoMiscOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + HiLoRsSelOp(const char *mnem, MachInst _machInst, OpClass __opClass) : HiLoOp(mnem, _machInst, __opClass) { } @@ -77,6 +78,31 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; + class HiLoRdSelOp: public HiLoOp + { + protected: + + /// Constructor + HiLoRdSelOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + HiLoOp(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + class HiLoRdSelValOp: public HiLoOp + { + protected: + + /// Constructor + HiLoRdSelValOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + HiLoOp(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; class IntImmOp : public MipsStaticInst { @@ -105,9 +131,7 @@ output header {{ }}; -// HiLo<Misc> instruction class execute method template. -// Mainly to get instruction trace data to print out -// correctly +// HiLo instruction class execute method template. def template HiLoExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -121,12 +145,58 @@ def template HiLoExecute {{ if(fault == NoFault) { %(op_wb)s; - //If there are 2 Destination Registers then - //concatenate the values for the traceData - if(traceData && _numDestRegs == 2) { - uint64_t hilo_final_val = (uint64_t)HI << 32 | LO; - traceData->setData(hilo_final_val); - } + } + return fault; + } +}}; + +// HiLoRsSel instruction class execute method template. +def template HiLoRsSelExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + + if( ACSRC > 0 && !isDspEnabled(xc) ) + { + fault = new DspStateDisabledFault(); + } + else + { + %(op_rd)s; + %(code)s; + } + + if(fault == NoFault) + { + %(op_wb)s; + } + return fault; + } +}}; + +// HiLoRdSel instruction class execute method template. +def template HiLoRdSelExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + + if( ACDST > 0 && !isDspEnabled(xc) ) + { + fault = new DspStateDisabledFault(); + } + else + { + %(op_rd)s; + %(code)s; + } + + if(fault == NoFault) + { + %(op_wb)s; } return fault; } @@ -181,7 +251,37 @@ output decoder {{ return ss.str(); } - std::string HiLoMiscOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + std::string HiLoRsSelOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0 && _destRegIdx[0] < 32) { + printReg(ss, _destRegIdx[0]); + } else if (_numSrcRegs > 0 && _srcRegIdx[0] < 32) { + printReg(ss, _srcRegIdx[0]); + } + + return ss.str(); + } + + std::string HiLoRdSelOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + if (_numDestRegs > 0 && _destRegIdx[0] < 32) { + printReg(ss, _destRegIdx[0]); + } else if (_numSrcRegs > 0 && _srcRegIdx[0] < 32) { + printReg(ss, _srcRegIdx[0]); + } + + return ss.str(); + } + + std::string HiLoRdSelValOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; @@ -239,26 +339,43 @@ def format IntImmOp(code, *opt_flags) {{ exec_output = BasicExecute.subst(iop) }}; -def format HiLoOp(code, *opt_flags) {{ - code += 'HI = val<63:32>;\n' - code += 'LO = val<31:0>;\n' - - iop = InstObjParams(name, Name, 'HiLoOp', code, opt_flags) +def format HiLoRsSelOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'HiLoRsSelOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) - exec_output = HiLoExecute.subst(iop) + exec_output = HiLoRsSelExecute.subst(iop) }}; -def format HiLoMiscOp(code, *opt_flags) {{ - iop = InstObjParams(name, Name, 'HiLoMiscOp', code, opt_flags) +def format HiLoRdSelOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'HiLoRdSelOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + exec_output = HiLoRdSelExecute.subst(iop) }}; +def format HiLoRdSelValOp(code, *opt_flags) {{ + if '.sd' in code: + code = 'int64_t ' + code + elif '.ud' in code: + code = 'uint64_t ' + code + code += 'HI_RD_SEL = val<63:32>;\n' + code += 'LO_RD_SEL = val<31:0>;\n' + iop = InstObjParams(name, Name, 'HiLoRdSelOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = HiLoRdSelExecute.subst(iop) +}}; +def format HiLoOp(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'HiLoOp', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = HiLoExecute.subst(iop) +}}; diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index df80e7a1f..c8e85a754 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -69,6 +69,8 @@ output header {{ const StaticInstPtr &eaCompInst() const { return eaCompPtr; } const StaticInstPtr &memAccInst() const { return memAccPtr; } + + unsigned memAccFlags() { return memAccessFlags; } }; /** @@ -108,6 +110,37 @@ output decoder {{ flags[IsFloating] ? FD : RD, RS, RT); } + +}}; + +output exec {{ + /** return data in cases where there the size of data is only + known in the packet + */ + uint64_t getStoreData(Packet *packet) { + switch (packet->getSize()) + { + case 8: + return packet->get<uint8_t>(); + + case 16: + return packet->get<uint16_t>(); + + case 32: + return packet->get<uint32_t>(); + + case 864: + return packet->get<uint64_t>(); + + default: + std::cerr << "bad store data size = " << packet->getSize() << std::endl; + + assert(0); + return 0; + } + } + + }}; def template LoadStoreDeclare {{ @@ -125,7 +158,7 @@ def template LoadStoreDeclare {{ { public: /// Constructor - EAComp(MachInst machInst); + EAComp(ExtMachInst machInst); %(BasicExecDeclare)s }; @@ -137,7 +170,7 @@ def template LoadStoreDeclare {{ { public: /// Constructor - MemAcc(MachInst machInst); + MemAcc(ExtMachInst machInst); %(BasicExecDeclare)s }; @@ -145,13 +178,15 @@ def template LoadStoreDeclare {{ public: /// Constructor. - %(class_name)s(MachInst machInst); + %(class_name)s(ExtMachInst machInst); %(BasicExecDeclare)s %(InitiateAccDeclare)s %(CompleteAccDeclare)s + + %(MemAccSizeDeclare)s }; }}; @@ -162,15 +197,18 @@ def template InitiateAccDeclare {{ def template CompleteAccDeclare {{ - Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; + Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; +def template MemAccSizeDeclare {{ + int memAccSize(%(CPU_exec_context)s *xc); +}}; def template EACompConstructor {{ /** TODO: change op_class to AddrGenOp or something (requires * creating new member of OpClass enum in op_class.hh, updating * config files, etc.). */ - inline %(class_name)s::EAComp::EAComp(MachInst machInst) + inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) { %(constructor)s; @@ -179,7 +217,7 @@ def template EACompConstructor {{ def template MemAccConstructor {{ - inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) + inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) { %(constructor)s; @@ -188,7 +226,7 @@ def template MemAccConstructor {{ def template LoadStoreConstructor {{ - inline %(class_name)s::%(class_name)s(MachInst machInst) + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, new EAComp(machInst), new MemAcc(machInst)) { @@ -210,8 +248,8 @@ def template EACompExecute {{ %(op_rd)s; %(ea_code)s; + // NOTE: Trace Data is written using execute or completeAcc templates if (fault == NoFault) { - %(op_wb)s; xc->setEA(EA); } @@ -227,19 +265,16 @@ def template LoadMemAccExecute {{ Addr EA; Fault fault = NoFault; - %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; + EA = xc->getEA(); - if (fault == NoFault) { - fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); - %(memacc_code)s; - } + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); - if (fault == NoFault) { - %(op_wb)s; - } + %(memacc_code)s; + + // NOTE: Write back data using execute or completeAcc templates return fault; } @@ -292,9 +327,8 @@ def template LoadInitiateAcc {{ } }}; - def template LoadCompleteAcc {{ - Fault %(class_name)s::completeAcc(PacketPtr pkt, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -302,6 +336,7 @@ def template LoadCompleteAcc {{ %(fp_enable_check)s; %(op_decl)s; + %(op_rd)s; Mem = pkt->get<typeof(Mem)>(); @@ -318,6 +353,15 @@ def template LoadCompleteAcc {{ }}; + +def template LoadStoreMemAccSize {{ + int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) + { + // Return the memory access size in bytes + return (%(mem_acc_size)d / 8); + } +}}; + def template StoreMemAccExecute {{ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, @@ -325,10 +369,12 @@ def template StoreMemAccExecute {{ { Addr EA; Fault fault = NoFault; + uint64_t write_result = 0; %(fp_enable_check)s; %(op_decl)s; %(op_rd)s; + EA = xc->getEA(); if (fault == NoFault) { @@ -337,16 +383,9 @@ def template StoreMemAccExecute {{ if (fault == NoFault) { fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, - memAccessFlags, NULL); - if (traceData) { traceData->setData(Mem); } - } - - if (fault == NoFault) { - %(postacc_code)s; - } - - if (fault == NoFault) { - %(op_wb)s; + memAccessFlags, &write_result); + // @NOTE: Need to Call Complete Access to Set Trace Data + //if (traceData) { traceData->setData(Mem); } } return fault; @@ -389,13 +428,13 @@ def template StoreCondMemAccExecute {{ } }}; - def template StoreExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { Addr EA; Fault fault = NoFault; + uint64_t write_result = 0; %(fp_enable_check)s; %(op_decl)s; @@ -408,7 +447,7 @@ def template StoreExecute {{ if (fault == NoFault) { fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, - memAccessFlags, NULL); + memAccessFlags, &write_result); if (traceData) { traceData->setData(Mem); } } @@ -487,7 +526,7 @@ def template StoreInitiateAcc {{ def template StoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(PacketPtr pkt, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -502,6 +541,8 @@ def template StoreCompleteAcc {{ if (fault == NoFault) { %(op_wb)s; + + if (traceData) { traceData->setData(getStoreData(pkt)); } } return fault; @@ -509,7 +550,7 @@ def template StoreCompleteAcc {{ }}; def template StoreCondCompleteAcc {{ - Fault %(class_name)s::completeAcc(PacketPtr pkt, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -584,7 +625,7 @@ def template MiscInitiateAcc {{ def template MiscCompleteAcc {{ - Fault %(class_name)s::completeAcc(PacketPtr pkt, + Fault %(class_name)s::completeAcc(Packet *pkt, %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -594,6 +635,15 @@ def template MiscCompleteAcc {{ } }}; + +def template MiscMemAccSize {{ + int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) + { + panic("Misc instruction does not support split access method!"); + return 0; + } +}}; + def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ @@ -650,6 +700,7 @@ def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; decl_code += '\tbyte_offset ^= 3;\n' decl_code += '#endif\n' decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n' + #decl_code += 'xc->readFunctional(EA,(uint32_t&)mem_word);' memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n' (header_output, decoder_output, decode_block, exec_output) = \ diff --git a/src/arch/mips/isa/formats/mt.isa b/src/arch/mips/isa/formats/mt.isa index d7240335e..b3520050a 100644 --- a/src/arch/mips/isa/formats/mt.isa +++ b/src/arch/mips/isa/formats/mt.isa @@ -37,46 +37,185 @@ output header {{ /** * Base class for MIPS MT ASE operations. */ - class MT : public MipsStaticInst + class MTOp : public MipsStaticInst { protected: /// Constructor - MT(const char *mnem, MachInst _machInst, OpClass __opClass) : - MipsStaticInst(mnem, _machInst, __opClass) + MTOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + MipsStaticInst(mnem, _machInst, __opClass), user_mode(false) { } - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + bool user_mode; + }; + + class MTUserModeOp : public MTOp + { + protected: + + /// Constructor + MTUserModeOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + MTOp(mnem, _machInst, __opClass) + { + user_mode = true; + } + + //std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; }}; output decoder {{ - //Edit This Template When MT is Implemented - std::string MT::generateDisassembly(Addr pc, const SymbolTable *symtab) const - { - return "Disassembly of MT instruction\n"; + std::string MTOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + if (mnemonic == "mttc0" || mnemonic == "mftc0") { + ccprintf(ss, "%-10s r%d, r%d, %d", mnemonic, RT, RD, SEL); + } else if (mnemonic == "mftgpr") { + ccprintf(ss, "%-10s r%d, r%d", mnemonic, RD, RT); + } else { + ccprintf(ss, "%-10s r%d, r%d", mnemonic, RT, RD); } + + return ss.str(); + } }}; -def template MTExecute {{ - //Edit This Template When MT is Implemented +output exec {{ + void getThrRegExValues(%(CPU_exec_context)s *xc, unsigned &vpe_conf0, unsigned &tc_bind_mt, unsigned &tc_bind, unsigned &vpe_control, unsigned &mvp_conf0) + { + vpe_conf0 = xc->readMiscReg(VPEConf0); + tc_bind_mt = xc->readRegOtherThread(TCBind + Ctrl_Base_DepTag); + tc_bind = xc->readMiscReg(TCBind); + vpe_control = xc->readMiscReg(VPEControl); + mvp_conf0 = xc->readMiscReg(MVPConf0); + } + + void getMTExValues(%(CPU_exec_context)s *xc, unsigned &config3) + { + config3 = xc->readMiscReg(Config3_MT); + } +}}; + +def template ThreadRegisterExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - //Write the resulting state to the execution context + Fault fault = NoFault; + int64_t data; + %(op_decl)s; + %(op_rd)s; + + unsigned vpe_conf0, tc_bind_mt, tc_bind, vpe_control, mvp_conf0; + + getThrRegExValues(xc, vpe_conf0, tc_bind_mt, tc_bind, vpe_control, mvp_conf0); + + if (isCoprocessorEnabled(xc, 0)) { + if (bits(vpe_conf0, VPEC0_MVP) == 0 && + bits(tc_bind_mt, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) != + bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) { + data = -1; + } else if (bits(vpe_control, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO) > + bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO)) { + data = -1; + } else { + int top_bit = 0; + int bottom_bit = 0; + + if (MT_H == 1) { + top_bit = 63; + bottom_bit = 32; + } else { + top_bit = 31; + bottom_bit = 0; + } + + %(code)s; + } + } else { + fault = new CoprocessorUnusableFault(); + } + + if(fault == NoFault) + { %(op_wb)s; + } - //Call into the trap handler with the appropriate fault - return No_Fault; + return fault; + } +}}; + +def template MTExecute{{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + %(op_decl)s; + %(op_rd)s; + + unsigned config3; + + getMTExValues(xc, config3); + + if (isCoprocessorEnabled(xc, 0)) { + if (bits(config3, CFG3_MT) == 1) { + %(code)s; + } else { + fault = new ReservedInstructionFault(); + } + } else { + fault = new CoprocessorUnusableFault(); + } + + if(fault == NoFault) + { + %(op_wb)s; + } + return fault; } }}; // Primary format for integer operate instructions: -def format MipsMT() {{ - code = 'panic(\"Mips MT Is Currently Unimplemented.\");\n' - iop = InstObjParams(name, Name, 'MT', code) +def format MT_Control(code, *opt_flags) {{ + inst_flags = ('IsNonSpeculative', ) + op_type = 'MTOp' + + for x in opt_flags: + if x == 'UserMode': + op_type = 'MTUserModeOp' + else: + inst_flags += (x, ) + + iop = InstObjParams(name, Name, op_type, code, inst_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = MTExecute.subst(iop) +}}; + +def format MT_MFTR(code, *flags) {{ + flags += ('IsNonSpeculative', ) +# code = 'std::cerr << curTick << \": T\" << xc->tcBase()->getThreadNum() << \": Executing MT INST: ' + name + '\" << endl;\n' + code + + code += 'if (MT_H == 1) {\n' + code += 'data = bits(data, top_bit, bottom_bit);\n' + code += '}\n' + code += 'Rd = data;\n' + + iop = InstObjParams(name, Name, 'MTOp', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = ThreadRegisterExecute.subst(iop) +}}; + +def format MT_MTTR(code, *flags) {{ + flags += ('IsNonSpeculative', ) +# code = 'std::cerr << curTick << \": T\" << xc->tcBase()->getThreadNum() << \": Executing MT INST: ' + name + '\" << endl;\n' + code + iop = InstObjParams(name, Name, 'MTOp', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) - exec_output = BasicExecute.subst(iop) + exec_output = ThreadRegisterExecute.subst(iop) }}; diff --git a/src/arch/mips/isa/formats/tlbop.isa b/src/arch/mips/isa/formats/tlbop.isa index dbfbb8ce1..b6db7864f 100644 --- a/src/arch/mips/isa/formats/tlbop.isa +++ b/src/arch/mips/isa/formats/tlbop.isa @@ -70,7 +70,9 @@ def template TlbOpExecute {{ // Primary format for integer operate instructions: def format TlbOp(code, *opt_flags) {{ - iop = InstObjParams(name, Name, 'MipsStaticInst', code, opt_flags) + orig_code = code + cblk = code + iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop) diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 884e6f727..eea616568 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -88,7 +88,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + completeAccTemplate.subst(iop)) }}; - output header {{ std::string inst2string(MachInst machInst); }}; @@ -97,7 +96,7 @@ output decoder {{ std::string inst2string(MachInst machInst) { - std::string str = ""; + string str = ""; uint32_t mask = 0x80000000; for(int i=0; i < 32; i++) { @@ -114,40 +113,3 @@ std::string inst2string(MachInst machInst) } }}; -output exec {{ - - using namespace MipsISA; - - /// CLEAR ALL CPU INST/EXE HAZARDS - inline void - clear_exe_inst_hazards() - { - //CODE HERE - } - - - /// Check "FP enabled" machine status bit. Called when executing any FP - /// instruction in full-system mode. - /// @retval Full-system mode: NoFault if FP is enabled, FenFault - /// if not. Non-full-system mode: always returns NoFault. -#if FULL_SYSTEM - inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) - { - Fault fault = NoFault; // dummy... this ipr access should not fault - if (!Mips34k::ICSR_FPE(xc->readIpr(MipsISA::IPR_ICSR, fault))) { - fault = FloatEnableFault; - } - return fault; - } -#else - inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) - { - return NoFault; - } -#endif - - - -}}; - - diff --git a/src/arch/mips/isa/includes.isa b/src/arch/mips/isa/includes.isa index 274fdcaa1..0e0cf44eb 100644 --- a/src/arch/mips/isa/includes.isa +++ b/src/arch/mips/isa/includes.isa @@ -44,19 +44,23 @@ output header {{ }}; output decoder {{ -#include <cmath> -#if defined(linux) -#include <fenv.h> -#endif - -#include "arch/mips/faults.hh" #include "arch/mips/isa_traits.hh" -#include "arch/mips/isa_traits.hh" -#include "arch/mips/isa_traits.hh" -#include "arch/mips/utility.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" +#include "arch/mips/faults.hh" +#include "arch/mips/isa_traits.hh" +#include "arch/mips/pra_constants.hh" +#include "arch/mips/dt_constants.hh" +#include "arch/mips/mt_constants.hh" +#include "arch/mips/utility.hh" +#include "arch/mips/dsp.hh" +#include "mem/packet.hh" + +#include <math.h> +#if defined(linux) +#include <fenv.h> +#endif using namespace MipsISA; }}; @@ -65,20 +69,25 @@ output exec {{ #include "arch/mips/faults.hh" #include "arch/mips/isa_traits.hh" #include "arch/mips/utility.hh" +#include "arch/mips/dsp.hh" +#include "arch/mips/pra_constants.hh" +#include "arch/mips/dt_constants.hh" +#include "arch/mips/mt_constants.hh" #include <math.h> #if defined(linux) #include <fenv.h> #endif -#ifdef FULL_SYSTEM -//#include "arch/alpha/pseudo_inst.hh" -#endif #include "cpu/base.hh" #include "cpu/exetrace.hh" + #include "mem/packet.hh" #include "mem/packet_access.hh" + #include "sim/sim_exit.hh" +#include "sim/eventq.hh" +#include "sim/sim_events.hh" using namespace MipsISA; }}; diff --git a/src/arch/mips/isa/operands.isa b/src/arch/mips/isa/operands.isa index 3843dc053..b89eb5249 100644 --- a/src/arch/mips/isa/operands.isa +++ b/src/arch/mips/isa/operands.isa @@ -48,16 +48,37 @@ def operands {{ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2), 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3), + #Immediate Value operand + 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), + #Operands used for Link or Syscall Insts 'R31': ('IntReg', 'uw','31','IsInteger', 4), 'R2': ('IntReg', 'uw','2', 'IsInteger', 5), #Special Integer Reg operands - 'HI': ('IntReg', 'uw','MipsISA::HI', 'IsInteger', 6), - 'LO': ('IntReg', 'uw','MipsISA::LO', 'IsInteger', 7), + 'LO0': ('IntReg', 'uw','MipsISA::LO', 'IsInteger', 6), + 'HI0': ('IntReg', 'uw','MipsISA::HI', 'IsInteger', 7), - #Immediate Value operand - 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), + #Bitfield-dependent HI/LO Register Access + 'LO_RD_SEL': ('IntReg','uw','MipsISA::DSPLo0 + ACDST*3', None, 6), + 'HI_RD_SEL': ('IntReg','uw','MipsISA::DSPHi0 + ACDST*3', None, 7), + 'LO_RS_SEL': ('IntReg','uw','MipsISA::DSPLo0 + ACSRC*3', None, 6), + 'HI_RS_SEL': ('IntReg','uw','MipsISA::DSPHi0 + ACSRC*3', None, 7), + + #DSP Special Purpose Integer Operands + 'DSPControl': ('IntReg', 'uw', 'MipsISA::DSPControl', None, 8), + 'DSPLo0': ('IntReg', 'uw', 'MipsISA::LO', None, 1), + 'DSPHi0': ('IntReg', 'uw', 'MipsISA::HI', None, 1), + 'DSPACX0': ('IntReg', 'uw', 'MipsISA::DSPACX0', None, 1), + 'DSPLo1': ('IntReg', 'uw', 'MipsISA::DSPLo1', None, 1), + 'DSPHi1': ('IntReg', 'uw', 'MipsISA::DSPHi1', None, 1), + 'DSPACX1': ('IntReg', 'uw', 'MipsISA::DSPACX1', None, 1), + 'DSPLo2': ('IntReg', 'uw', 'MipsISA::DSPLo2', None, 1), + 'DSPHi2': ('IntReg', 'uw', 'MipsISA::DSPHi2', None, 1), + 'DSPACX2': ('IntReg', 'uw', 'MipsISA::DSPACX2', None, 1), + 'DSPLo3': ('IntReg', 'uw', 'MipsISA::DSPLo3', None, 1), + 'DSPHi3': ('IntReg', 'uw', 'MipsISA::DSPHi3', None, 1), + 'DSPACX3': ('IntReg', 'uw', 'MipsISA::DSPACX3', None, 1), #Floating Point Reg Operands 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1), @@ -65,14 +86,14 @@ def operands {{ 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), 'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3), - #Special Floating Point Control Reg Operands + #Special Purpose Floating Point Control Reg Operands 'FIR': ('FloatReg', 'uw', 'MipsISA::FIR', 'IsFloating', 1), 'FCCR': ('FloatReg', 'uw', 'MipsISA::FCCR', 'IsFloating', 2), 'FEXR': ('FloatReg', 'uw', 'MipsISA::FEXR', 'IsFloating', 3), 'FENR': ('FloatReg', 'uw', 'MipsISA::FENR', 'IsFloating', 3), 'FCSR': ('FloatReg', 'uw', 'MipsISA::FCSR', 'IsFloating', 3), - #Operands For Paired Singles FP Operations + #Operands For Paired Singles FP Operations 'Fd1': ('FloatReg', 'sf', 'FD', 'IsFloating', 4), 'Fd2': ('FloatReg', 'sf', 'FD+1', 'IsFloating', 4), 'Fs1': ('FloatReg', 'sf', 'FS', 'IsFloating', 5), @@ -82,10 +103,44 @@ def operands {{ 'Fr1': ('FloatReg', 'sf', 'FR', 'IsFloating', 7), 'Fr2': ('FloatReg', 'sf', 'FR+1', 'IsFloating', 7), + #Status Control Reg + 'Status': ('ControlReg', 'uw', 'MipsISA::Status', None, 1), + + #Special cases for when a Control Register Access is dependent on + #a combination of bitfield indices (handles MTCO & MFCO) + 'CP0_RD_SEL': ('ControlReg', 'uw', 'RD << 3 | SEL', None, 1), + + #MT Control Regs + 'MVPConf0': ('ControlReg', 'uw', 'MipsISA::MVPConf0', None, 1), + 'MVPControl': ('ControlReg', 'uw', 'MipsISA::MVPControl', None, 1), + 'TCBind': ('ControlReg', 'uw', 'MipsISA::TCBind', None, 1), + 'TCStatus': ('ControlReg', 'uw', 'MipsISA::TCStatus', None, 1), + 'TCRestart': ('ControlReg', 'uw', 'MipsISA::TCRestart', None, 1), + 'VPEConf0': ('ControlReg', 'uw', 'MipsISA::VPEConf0', None, 1), + 'VPEControl': ('ControlReg', 'uw', 'MipsISA::VPEControl', None, 1), + 'YQMask': ('ControlReg', 'uw', 'MipsISA::YQMask', None, 1), + + # named bitfields of Control Regs + 'Status_IE': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'Status_ERL': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'Status_EXL': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'Status_CU3': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'Status_CU2': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'Status_CU1': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'Status_CU0': ('ControlBitfield', 'uw', 'MipsISA::Status', None, 1), + 'SRSCtl_HSS': ('ControlBitfield', 'uw', 'MipsISA::SRSCtl', None, 4), + 'SRSCtl_PSS': ('ControlBitfield', 'uw', 'MipsISA::SRSCtl', None, 4), + 'SRSCtl_CSS': ('ControlBitfield', 'uw', 'MipsISA::SRSCtl', None, 4), + 'Config_AR': ('ControlBitfield', 'uw', 'MipsISA::Config', None, 3), + + # named bitfields of Debug Regs + 'Debug_DM': ('ControlBitfield', 'uw', 'MipsISA::Debug', None, 1), + 'Debug_IEXI': ('ControlBitfield', 'uw', 'MipsISA::Debug', None, 1), + #Memory Operand 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), #Program Counter Operands - 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4), - 'NNPC':('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4) + 'NPC': ('NPC', 'uw', None, 'IsControl', 4), + 'NNPC':('NNPC', 'uw', None, 'IsControl', 4) }}; diff --git a/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc index 3a8cb46a5..0c84ce2b2 100644 --- a/src/arch/mips/isa_traits.cc +++ b/src/arch/mips/isa_traits.cc @@ -96,3 +96,5 @@ RegFile::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(nnpc); } + + diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh index f85fc5bea..5ab6957a3 100644 --- a/src/arch/mips/isa_traits.hh +++ b/src/arch/mips/isa_traits.hh @@ -60,24 +60,13 @@ namespace MipsISA // Constants Related to the number of registers const int NumIntArchRegs = 32; - const int NumIntSpecialRegs = 2; + const int NumIntSpecialRegs = 9; const int NumFloatArchRegs = 32; const int NumFloatSpecialRegs = 5; - const int NumControlRegs = 265; - const int NumInternalProcRegs = 0; - - const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs - const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// - const int NumMiscRegs = NumControlRegs; - - const int TotalNumRegs = NumIntRegs + NumFloatRegs + - NumMiscRegs + 0/*NumInternalProcRegs*/; - - const int TotalDataRegs = NumIntRegs + NumFloatRegs; // Static instruction parameters - const int MaxInstSrcRegs = 3; - const int MaxInstDestRegs = 2; + const int MaxInstSrcRegs = 5; + const int MaxInstDestRegs = 4; // semantically meaningful register indices const int ZeroReg = 0; @@ -97,7 +86,7 @@ namespace MipsISA const int ReturnAddressReg = 31; const int SyscallNumReg = ReturnValueReg1; - const int SyscallPseudoReturnReg = ReturnValueReg1; + const int SyscallPseudoReturnReg = ReturnValueReg2; const int SyscallSuccessReg = ArgumentReg3; const int LogVMPageSize = 13; // 8K bytes @@ -110,13 +99,176 @@ namespace MipsISA const int HalfwordBytes = 2; const int ByteBytes = 1; - // These help enumerate all the registers for dependence tracking. - const int FP_Base_DepTag = 34; - const int Ctrl_Base_DepTag = 257; - const int ANNOTE_NONE = 0; const uint32_t ITOUCH_ANNOTE = 0xffffffff; + // Enumerate names for 'Control' Registers in the CPU + // Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8 + // (Register Number-Register Select) Summary of Register + //------------------------------------------------------ + // The first set of names classify the CP0 names as Register Banks + // for easy indexing when using the 'RD + SEL' index combination + // in CP0 instructions. + enum MiscRegTags { + Index = 0, //Bank 0: 0 - 3 + MVPControl, + MVPConf0, + MVPConf1, + + Random = 8, //Bank 1: 8 - 15 + VPEControl, + VPEConf0, + VPEConf1, + YQMask, + VPESchedule, + VPEScheFBack, + VPEOpt, + + EntryLo0 = 16, //Bank 2: 16 - 23 + TCStatus, + TCBind, + TCRestart, + TCHalt, + TCContext, + TCSchedule, + TCScheFBack, + + EntryLo1 = 24, // Bank 3: 24 + + Context = 32, // Bank 4: 32 - 33 + ContextConfig, + + //PageMask = 40, //Bank 5: 40 - 41 + PageGrain = 41, + + Wired = 48, //Bank 6:48-55 + SRSConf0, + SRSConf1, + SRSConf2, + SRSConf3, + SRSConf4, + + HWRena = 56, //Bank 7: 56-63 + + BadVAddr = 64, //Bank 8: 64-71 + + Count = 72, //Bank 9: 72-79 + + EntryHi = 80, //Bank 10: 80-87 + + Compare = 88, //Bank 11: 88-95 + + Status = 96, //Bank 12: 96-103 + IntCtl, + SRSCtl, + SRSMap, + + Cause = 104, //Bank 13: 104-111 + + EPC = 112, //Bank 14: 112-119 + + PRId = 120, //Bank 15: 120-127, + EBase, + + Config = 128, //Bank 16: 128-135 + Config1, + Config2, + Config3, + Config4, + Config5, + Config6, + Config7, + + + LLAddr = 136, //Bank 17: 136-143 + + WatchLo0 = 144, //Bank 18: 144-151 + WatchLo1, + WatchLo2, + WatchLo3, + WatchLo4, + WatchLo5, + WatchLo6, + WatchLo7, + + WatchHi0 = 152, //Bank 19: 152-159 + WatchHi1, + WatchHi2, + WatchHi3, + WatchHi4, + WatchHi5, + WatchHi6, + WatchHi7, + + XCContext64 = 160, //Bank 20: 160-167 + + //Bank 21: 168-175 + + //Bank 22: 176-183 + + Debug = 184, //Bank 23: 184-191 + TraceControl1, + TraceControl2, + UserTraceData, + TraceBPC, + + DEPC = 192, //Bank 24: 192-199 + + PerfCnt0 = 200, //Bank 25: 200-207 + PerfCnt1, + PerfCnt2, + PerfCnt3, + PerfCnt4, + PerfCnt5, + PerfCnt6, + PerfCnt7, + + ErrCtl = 208, //Bank 26: 208-215 + + CacheErr0 = 216, //Bank 27: 216-223 + CacheErr1, + CacheErr2, + CacheErr3, + + TagLo0 = 224, //Bank 28: 224-231 + DataLo1, + TagLo2, + DataLo3, + TagLo4, + DataLo5, + TagLo6, + DataLo7, + + TagHi0 = 232, //Bank 29: 232-239 + DataHi1, + TagHi2, + DataHi3, + TagHi4, + DataHi5, + TagHi6, + DataHi7, + + + ErrorEPC = 240, //Bank 30: 240-247 + + DESAVE = 248, //Bank 31: 248-256 + + LLFlag = 257, + + NumControlRegs + }; + + const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs + const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// + const int NumMiscRegs = NumControlRegs; + + const int TotalNumRegs = NumIntRegs + NumFloatRegs + NumMiscRegs; + + const int TotalDataRegs = NumIntRegs + NumFloatRegs; + + // These help enumerate all the registers for dependence tracking. + const int FP_Base_DepTag = NumIntRegs; + const int Ctrl_Base_DepTag = FP_Base_DepTag + NumFloatRegs; }; using namespace MipsISA; diff --git a/src/arch/mips/linux/linux.cc b/src/arch/mips/linux/linux.cc index 90404af53..4499107d7 100644 --- a/src/arch/mips/linux/linux.cc +++ b/src/arch/mips/linux/linux.cc @@ -72,3 +72,4 @@ const int MipsLinux::NUM_OPEN_FLAGS = + diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh index a20221e9b..fcfaa18ea 100644 --- a/src/arch/mips/linux/linux.hh +++ b/src/arch/mips/linux/linux.hh @@ -32,6 +32,9 @@ #define __ARCH_MIPS_LINUX_LINUX_HH__ #include "kern/linux/linux.hh" +#include <string> + +using std::string; class MipsLinux : public Linux { @@ -91,21 +94,21 @@ class MipsLinux : public Linux //@{ /// ioctl() command codes. - static const unsigned TIOCGETP_ = 0x7408; - static const unsigned TIOCSETP_ = 0x7409; - static const unsigned TIOCSETN_ = 0x740a; - static const unsigned TIOCSETC_ = 0x7411; - static const unsigned TIOCGETC_ = 0x7412; - static const unsigned FIONREAD_ = 0x467f; - static const unsigned TIOCISATTY_ = 0x5480; - static const unsigned TIOCGETS_ = 0x7413; - static const unsigned TIOCGETA_ = 0x7417; + static const unsigned TIOCGETP = 0x7408; + static const unsigned TIOCSETP = 0x7409; + static const unsigned TIOCSETN = 0x740a; + static const unsigned TIOCSETC = 0x7411; + static const unsigned TIOCGETC = 0x7412; + static const unsigned FIONREAD = 0x467f; + static const unsigned TIOCISATTY = 0x5480; + static const unsigned TIOCGETS = 0x540d; + static const unsigned TIOCGETA = 0x7417; //@} /// For table(). static const int TBL_SYSINFO = 12; - /// Resource enumeration for getrlimit(). + /// Resource enumeration for getrlimit()/setrlimit(). enum rlimit_resources { TGT_RLIMIT_CPU = 0, TGT_RLIMIT_FSIZE = 1, @@ -118,9 +121,14 @@ class MipsLinux : public Linux TGT_RLIMIT_VMEM = 7, TGT_RLIMIT_NPROC = 8, TGT_RLIMIT_MEMLOCK = 9, - TGT_RLIMIT_LOCKS = 10 + TGT_RLIMIT_LOCKS = 10, + NUM_RLIMIT_RESOURCES }; + /// Offset used to make sure that processes don't + /// assign themselves to process IDs reserved for + /// the root users. + static const int NUM_ROOT_PROCS = 2; }; #endif diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index a847608d8..283088cb2 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -37,7 +37,9 @@ #include "kern/linux/linux.hh" #include "sim/process.hh" +#include "sim/system.hh" #include "sim/syscall_emul.hh" +#include "sim/eventq.hh" using namespace std; using namespace MipsISA; @@ -50,7 +52,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); strcpy(name->sysname, "Linux"); - strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->nodename,"m5.eecs.umich.edu"); strcpy(name->release, "2.4.20"); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "mips"); @@ -116,7 +118,6 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return 1; } - SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 0 */ SyscallDesc("syscall", unimplementedFunc), /* 1 */ SyscallDesc("exit", exitFunc), @@ -155,12 +156,12 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 34 */ SyscallDesc("nice", unimplementedFunc), /* 35 */ SyscallDesc("ftime", unimplementedFunc), /* 36 */ SyscallDesc("sync", unimplementedFunc), - /* 37 */ SyscallDesc("kill", ignoreFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), /* 38 */ SyscallDesc("rename", unimplementedFunc), /* 39 */ SyscallDesc("mkdir", unimplementedFunc), /* 40 */ SyscallDesc("rmdir", unimplementedFunc), /* 41 */ SyscallDesc("dup", unimplementedFunc), - /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), /* 43 */ SyscallDesc("times", unimplementedFunc), /* 44 */ SyscallDesc("prof", unimplementedFunc), /* 45 */ SyscallDesc("brk", obreakFunc), @@ -172,7 +173,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 51 */ SyscallDesc("acct", unimplementedFunc), /* 52 */ SyscallDesc("umount2", unimplementedFunc), /* 53 */ SyscallDesc("lock", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", ioctlFunc<MipsLinux>), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc/*ioctlFunc<MipsLinux>*/), /* 55 */ SyscallDesc("fcntl", fcntlFunc), /* 56 */ SyscallDesc("mpx", unimplementedFunc), /* 57 */ SyscallDesc("setpgid", unimplementedFunc), @@ -193,9 +194,9 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc), /* 73 */ SyscallDesc("sigpending", unimplementedFunc), /* 74 */ SyscallDesc("sethostname", ignoreFunc), - /* 75 */ SyscallDesc("setrlimit", unimplementedFunc), - /* 76 */ SyscallDesc("getrlimit", unimplementedFunc), - /* 77 */ SyscallDesc("getrusage", unimplementedFunc), + /* 75 */ SyscallDesc("setrlimit", unimplementedFunc/*setrlimitFunc<MipsLinux>*/), + /* 76 */ SyscallDesc("getrlimit", unimplementedFunc/*getrlimitFunc<MipsLinux>*/), + /* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>), /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc), /* 79 */ SyscallDesc("settimeofday", unimplementedFunc), /* 80 */ SyscallDesc("getgroups", unimplementedFunc), @@ -212,8 +213,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 91 */ SyscallDesc("munmap",munmapFunc), /* 92 */ SyscallDesc("truncate", truncateFunc), /* 93 */ SyscallDesc("ftruncate", ftruncateFunc), - /* 94 */ SyscallDesc("fchmod", unimplementedFunc), - /* 95 */ SyscallDesc("fchown", unimplementedFunc), + /* 94 */ SyscallDesc("fchmod", fchmodFunc<MipsLinux>), + /* 95 */ SyscallDesc("fchown", fchownFunc), /* 96 */ SyscallDesc("getpriority", unimplementedFunc), /* 97 */ SyscallDesc("setpriority", unimplementedFunc), /* 98 */ SyscallDesc("profil", unimplementedFunc), @@ -238,7 +239,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 117 */ SyscallDesc("ipc", unimplementedFunc), /* 118 */ SyscallDesc("fsync", unimplementedFunc), /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), - /* 120 */ SyscallDesc("clone", unimplementedFunc), + /* 120 */ SyscallDesc("clone", unimplementedFunc/*cloneFunc<MipsLinux>*/), /* 121 */ SyscallDesc("setdomainname", unimplementedFunc), /* 122 */ SyscallDesc("uname", unameFunc), /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), @@ -271,7 +272,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 150 */ SyscallDesc("unused#150", unimplementedFunc), /* 151 */ SyscallDesc("getsid", unimplementedFunc), /* 152 */ SyscallDesc("fdatasync", unimplementedFunc), - /* 153 */ SyscallDesc("sysctl", unimplementedFunc), + /* 153 */ SyscallDesc("sysctl", ignoreFunc), /* 154 */ SyscallDesc("mlock", unimplementedFunc), /* 155 */ SyscallDesc("munlock", unimplementedFunc), /* 156 */ SyscallDesc("mlockall", unimplementedFunc), @@ -312,12 +313,12 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 191 */ SyscallDesc("getresgid", unimplementedFunc), /* 192 */ SyscallDesc("prctl", unimplementedFunc), /* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 194 */ SyscallDesc("rt_sigaction", ignoreFunc), - /* 195 */ SyscallDesc("rt_sigprocmask", ignoreFunc), + /* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc/*rt_sigactionFunc<MipsLinux>*/), + /* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc/*rt_sigprocmaskFunc<MipsLinux>*/), /* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc), /* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), /* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc), - /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc/*rt_sigsuspendFunc<MipsLinux>*/), /* 200 */ SyscallDesc("pread64", unimplementedFunc), /* 201 */ SyscallDesc("pwrite64", unimplementedFunc), /* 202 */ SyscallDesc("chown", unimplementedFunc), @@ -400,9 +401,10 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 279 */ SyscallDesc("unknown #279", unimplementedFunc), /* 280 */ SyscallDesc("add_key", unimplementedFunc), /* 281 */ SyscallDesc("request_key", unimplementedFunc), - /* 282 */ SyscallDesc("keyctl", unimplementedFunc), + /* 282 */ SyscallDesc("keyctl", unimplementedFunc) }; + MipsLinuxProcess::MipsLinuxProcess(const std::string &name, ObjectFile *objFile, System *system, @@ -421,7 +423,13 @@ MipsLinuxProcess::MipsLinuxProcess(const std::string &name, : MipsLiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, _uid, _euid, _gid, _egid, _pid, _ppid), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) -{ } +{ } + +void +MipsLinuxProcess::startup() +{ + MipsLiveProcess::argsInit(MachineBytes, VMPageSize); +} SyscallDesc* MipsLinuxProcess::getDesc(int callnum) @@ -434,3 +442,8 @@ MipsLinuxProcess::getDesc(int callnum) return &syscallDescs[m5_sys_idx]; } + + + + + diff --git a/src/arch/mips/linux/process.hh b/src/arch/mips/linux/process.hh index 398e1cfc2..d18c96188 100644 --- a/src/arch/mips/linux/process.hh +++ b/src/arch/mips/linux/process.hh @@ -30,7 +30,8 @@ #define __MIPS_LINUX_PROCESS_HH__ #include "arch/mips/process.hh" - +#include "arch/mips/linux/linux.hh" +#include "sim/eventq.hh" /// A process with emulated Mips/Linux syscalls. class MipsLinuxProcess : public MipsLiveProcess @@ -48,16 +49,19 @@ class MipsLinuxProcess : public MipsLiveProcess uint64_t _gid, uint64_t _egid, uint64_t _pid, uint64_t _ppid); + void startup(); + virtual SyscallDesc* getDesc(int callnum); /// The target system's hostname. static const char *hostname; - /// Array of syscall descriptors, indexed by call number. - static SyscallDesc syscallDescs[]; + /// ID of the thread group leader for the process + uint64_t __tgid; + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; const int Num_Syscall_Descs; }; - #endif // __MIPS_LINUX_PROCESS_HH__ diff --git a/src/arch/mips/locked_mem.hh b/src/arch/mips/locked_mem.hh index 363cf1e90..9d7d02a03 100644 --- a/src/arch/mips/locked_mem.hh +++ b/src/arch/mips/locked_mem.hh @@ -37,6 +37,9 @@ * ISA-specific helper functions for locked memory accesses. */ +#include "arch/isa_traits.hh" +#include "base/misc.hh" +#include "base/trace.hh" #include "mem/request.hh" @@ -46,6 +49,11 @@ template <class XC> inline void handleLockedRead(XC *xc, Request *req) { + unsigned tid = req->getThreadNum(); + xc->setMiscReg(LLAddr, req->getPaddr() & ~0xf, tid); + xc->setMiscReg(LLFlag, true, tid); + DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link Address set to %x.\n", + tid, req->getPaddr() & ~0xf); } @@ -53,6 +61,52 @@ template <class XC> inline bool handleLockedWrite(XC *xc, Request *req) { + unsigned tid = req->getThreadNum(); + + if (req->isUncacheable()) { + // Funky Turbolaser mailbox access...don't update + // result register (see stq_c in decoder.isa) + req->setExtraData(2); + } else { + // standard store conditional + bool lock_flag = xc->readMiscReg(LLFlag, tid); + Addr lock_addr = xc->readMiscReg(LLAddr, tid); + + if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) { + // Lock flag not set or addr mismatch in CPU; + // don't even bother sending to memory system + req->setExtraData(0); + xc->setMiscReg(LLFlag, false, tid); + + // the rest of this code is not architectural; + // it's just a debugging aid to help detect + // livelock by warning on long sequences of failed + // store conditionals + int stCondFailures = xc->readStCondFailures(); + stCondFailures++; + xc->setStCondFailures(stCondFailures); + if (stCondFailures % 10 == 0) { + warn("%i: cpu %d: %d consecutive " + "store conditional failures\n", + curTick, xc->readCpuId(), stCondFailures); + } + + if (stCondFailures == 5000) { + panic("Max (5000) Store Conditional Fails Reached. Check Code For Deadlock.\n"); + } + + if (!lock_flag){ + DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n", + tid); + } else if ((req->getPaddr() & ~0xf) != lock_addr) { + DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n", + tid); + } + // store conditional failed already, so don't issue it to mem + return false; + } + } + return true; } diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh new file mode 100755 index 000000000..6d78dd020 --- /dev/null +++ b/src/arch/mips/mt.hh @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ARCH_MIPS_MT_HH__ +#define __ARCH_MIPS_MT_HH__ + +/** + * @file + * + * ISA-specific helper functions for multithreaded execution. + */ + +#include "arch/isa_traits.hh" +#include "arch/mips/faults.hh" +#include "arch/mips/mt_constants.hh" +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "base/misc.hh" + +#include <iostream> +using namespace std; + +namespace MipsISA +{ + + +template <class TC> +inline unsigned +getVirtProcNum(TC *tc) +{ + MiscReg tcbind = tc->readMiscRegNoEffect(TCBind); + return bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); +} + +template <class TC> +inline unsigned +getTargetThread(TC *tc) +{ + MiscReg vpec_ctrl = tc->readMiscRegNoEffect(VPEControl); + return bits(vpec_ctrl, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO); +} + +template <class TC> +inline void +haltThread(TC *tc) +{ + if (tc->status() == TC::Active) { + tc->halt(); + + // Save last known PC in TCRestart + // @TODO: Needs to check if this is a branch and if so, take previous instruction + tc->setMiscReg(TCRestart, tc->readNextPC()); + + warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), + tc->readPC(), tc->readNextPC()); + } +} + +template <class TC> +inline void +restoreThread(TC *tc) +{ + if (tc->status() != TC::Active) { + // Restore PC from TCRestart + IntReg pc = tc->readMiscRegNoEffect(TCRestart); + + // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY + // tc->setPCEvent(pc, pc + 4, pc + 8); + tc->setPC(pc); + tc->setNextPC(pc + 4); + tc->setNextNPC(pc + 8); + tc->activate(0); + + warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), + tc->readPC()); + } +} + +template <class TC> +void +forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) +{ + int num_threads = bits(tc->readMiscRegNoEffect(MVPConf0), MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; + + int success = 0; + for (int tid = 0; tid < num_threads && success == 0; tid++) { + unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, + tid); + unsigned tc_bind = tc->readMiscRegNoEffect(MipsISA::TCBind); + + if (bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) == + bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) { + + unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, + tid); + + unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, + tid); + + if (bits(tid_TCStatus, TCS_DA) == 1 && + bits(tid_TCHalt, TCH_H) == 0 && + bits(tid_TCStatus, TCS_A) == 0 && + success == 0) { + + tc->setRegOtherThread(MipsISA::TCRestart + Ctrl_Base_DepTag, Rs, tid); + + tc->setRegOtherThread(Rd_bits, Rt, tid); + + unsigned status_ksu = bits(tc->readMiscReg(MipsISA::Status), + S_KSU_HI, S_KSU_LO); + unsigned tc_status_asid = bits(tc->readMiscReg(MipsISA::TCStatus), + TCS_ASID_HI, TCS_ASID_LO); + + // Set Run-State to Running + replaceBits(tid_TCStatus, TCSTATUS_RNST_HI, TCSTATUS_RNST_LO, 0); + + // Set Delay-Slot to 0 + replaceBits(tid_TCStatus, TCSTATUS_TDS, 0); + + // Set Dirty TC to 1 + replaceBits(tid_TCStatus, TCSTATUS_DT, 1); + + // Set Activated to 1 + replaceBits(tid_TCStatus, TCSTATUS_A, 1); + + // Set status to previous thread's status + replaceBits(tid_TCStatus, TCSTATUS_TKSU_HI, TCSTATUS_TKSU_LO, status_ksu); + + // Set ASID to previous thread's state + replaceBits(tid_TCStatus, TCSTATUS_ASID_HI, TCSTATUS_ASID_LO, tc_status_asid); + + // Write Status Register + tc->setRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, + tid_TCStatus, tid); + + // Mark As Successful Fork + success = 1; + } + } else { + std::cerr << "Bad VPEs" << endl; + } + } + + if (success == 0) { + unsigned vpe_control = tc->readMiscRegNoEffect(MipsISA::VPEControl); + tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 1)); + fault = new ThreadFault(); + } +} + + +template <class TC> +int +yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) +{ + if (src_reg == 0) { + unsigned mvpconf0 = tc->readMiscRegNoEffect(MVPConf0); + int num_threads = bits(mvpconf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; + + int ok = 0; + + // Get Current VPE & TC numbers from calling thread + unsigned tcbind = tc->readMiscRegNoEffect(TCBind); + unsigned cur_vpe = bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); + unsigned cur_tc = bits(tcbind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); + + for (int tid = 0; tid < num_threads; tid++) { + unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, + tid); + unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, + tid); + unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, + tid); + + unsigned tid_vpe = bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); + unsigned tid_tc = bits(tid_TCBind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); + unsigned tid_tcstatus_da = bits(tid_TCStatus, TCS_DA); + unsigned tid_tcstatus_a = bits(tid_TCStatus, TCS_A); + unsigned tid_tchalt_h = bits(tid_TCHalt, TCH_H); + + if (tid_vpe == cur_vpe && + tid_tc == cur_tc && + tid_tcstatus_da == 1 && + tid_tchalt_h == 0 && + tid_tcstatus_a == 1) { + ok = 1; + } + } + + if (ok == 1) { + unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); + tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0)); + warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum()); + } + } else if (src_reg > 0) { + if (src_reg & !yield_mask != 0) { + unsigned vpe_control = tc->readMiscReg(VPEControl); + tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2)); + fault = new ThreadFault(); + } else { + //tc->setThreadRescheduleCondition(src_reg & yield_mask); + } + } else if (src_reg != -2) { + unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); + unsigned vpe_control = tc->readMiscRegNoEffect(VPEControl); + unsigned tcstatus_dt = bits(tcstatus, TCS_DT); + unsigned vpe_control_ysi = bits(vpe_control, VPEC_YSI); + + if (vpe_control_ysi == 1 && tcstatus_dt == 1 ) { + tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 4)); + fault = new ThreadFault(); + } else { + //tc->ScheduleOtherThreads(); + //std::cerr << "T" << tc->getThreadNum() << "YIELD: Schedule Other Threads.\n" << std::endl; + //tc->suspend(); + // Save last known PC in TCRestart + // @TODO: Needs to check if this is a branch and if so, take previous instruction + //tc->setMiscRegWithEffect(TCRestart, tc->readNextPC()); + } + } + + return src_reg & yield_mask; +} + + +// TC will usually be a object derived from ThreadContext +// (src/cpu/thread_context.hh) +template <class TC> +inline void +updateStatusView(TC *tc) +{ + // TCStatus' register view must be the same as + // Status register view for CU, MX, KSU bits + MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); + MiscReg status = tc->readMiscRegNoEffect(Status); + + unsigned cu_bits = bits(tc_status, TCS_TCU_HI, TCS_TCU_LO); + replaceBits(status, S_CU_HI, S_CU_LO, cu_bits); + + unsigned mx_bits = bits(tc_status, TCS_TMX); + replaceBits(status, S_MX, S_MX, mx_bits); + + unsigned ksu_bits = bits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO); + replaceBits(status, S_KSU_HI, S_KSU_LO, ksu_bits); + + tc->setMiscRegNoEffect(Status, status); +} + +// TC will usually be a object derived from ThreadContext +// (src/cpu/thread_context.hh) +template <class TC> +inline void +updateTCStatusView(TC *tc) +{ + // TCStatus' register view must be the same as + // Status register view for CU, MX, KSU bits + MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); + MiscReg status = tc->readMiscRegNoEffect(Status); + + unsigned cu_bits = bits(status, S_CU_HI, S_CU_LO); + replaceBits(tc_status, TCS_TCU_HI, TCS_TCU_LO, cu_bits); + + unsigned mx_bits = bits(status, S_MX, S_MX); + replaceBits(tc_status, TCS_TMX, mx_bits); + + unsigned ksu_bits = bits(status, S_KSU_HI, S_KSU_LO); + replaceBits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO, ksu_bits); + + tc->setMiscRegNoEffect(TCStatus, tc_status); +} + +} // namespace MipsISA + + +#endif diff --git a/src/arch/mips/mt_constants.hh b/src/arch/mips/mt_constants.hh new file mode 100755 index 000000000..0f6978433 --- /dev/null +++ b/src/arch/mips/mt_constants.hh @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __ARCH_MIPS_MT_CONSTANTS_HH__ +#define __ARCH_MIPS_MT_CONSTANTS_HH__ + +#include "arch/mips/types.hh" +//#include "config/full_system.hh" + +namespace MipsISA +{ +// MVPControl +const unsigned MVPC_EVP = 0; +const unsigned MVPC_CUR_VPE_HI = 3; +const unsigned MVPC_CUR_VPE_LO = 0; + +// MVPConf0 +const unsigned MVPC0_TCA = 15; +const unsigned MVPC0_PVPE_HI = 13; +const unsigned MVPC0_PVPE_LO = 10; +const unsigned MVPC0_PTC_HI = 7; +const unsigned MVPC0_PTC_LO = 0; + +//VPEControl +const unsigned VPEC_YSI = 21; +const unsigned VPEC_EXCPT_HI = 18; +const unsigned VPEC_EXCPT_LO = 16; +const unsigned VPEC_TE = 15; +const unsigned VPEC_TARG_TC_HI = 7; +const unsigned VPEC_TARG_TC_LO = 0; + +//VPEConf0 +const unsigned VPEC0_MVP = 1; + +//TCBind +const unsigned TCB_CUR_VPE_HI = 3; +const unsigned TCB_CUR_VPE_LO = 0; +const unsigned TCB_CUR_TC_HI = 28; +const unsigned TCB_CUR_TC_LO = 21; + + +//TCStatus +const unsigned TCS_TCU_HI = 31; +const unsigned TCS_TCU_LO = 28; +const unsigned TCS_TMX = 27; +const unsigned TCS_DT = 20; +const unsigned TCS_DA = 15; +const unsigned TCS_A = 13; +const unsigned TCS_TKSU_HI = 12; +const unsigned TCS_TKSU_LO = 11; +const unsigned TCS_IXMT = 7; +const unsigned TCS_ASID_HI = 7; +const unsigned TCS_ASID_LO = 7; + +const unsigned TCSTATUS_TCU_HI = 31; +const unsigned TCSTATUS_TCU_LO = 28; +const unsigned TCSTATUS_TMX = 27; +const unsigned TCSTATUS_RNST_HI = 24; +const unsigned TCSTATUS_RNST_LO = 23; +const unsigned TCSTATUS_TDS = 21; +const unsigned TCSTATUS_DT = 20; +const unsigned TCSTATUS_DA = 15; +const unsigned TCSTATUS_A = 13; +const unsigned TCSTATUS_TKSU_HI = 12; +const unsigned TCSTATUS_TKSU_LO = 11; +const unsigned TCSTATUS_IXMT = 7; +const unsigned TCSTATUS_ASID_HI = 7; +const unsigned TCSTATUS_ASID_LO = 7; + +//TCHalt +const unsigned TCH_H = 0; + +//Status +const unsigned S_CU_HI = 31; +const unsigned S_CU_LO = 28; +const unsigned S_MX = 24; +const unsigned S_KSU_HI = 4; +const unsigned S_KSU_LO = 3; + +// Config0 +const unsigned CFG_M = 31; + +// Config1 +const unsigned CFG1_M = 31; + +// Config2 +const unsigned CFG2_M = 31; + +// Config3 +const unsigned CFG3_M = 31; +const unsigned CFG3_MT = 2; + +} // namespace MipsISA + +#endif diff --git a/src/arch/mips/pra_constants.hh b/src/arch/mips/pra_constants.hh new file mode 100755 index 000000000..fb93e2de2 --- /dev/null +++ b/src/arch/mips/pra_constants.hh @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Jaidev Patwardhan + */ + +#ifndef __ARCH_MIPS_PRA_CONSTANTS_HH__ +#define __ARCH_MIPS_PRA_CONSTANTS_HH__ + +#include "arch/mips/types.hh" +//#include "config/full_system.hh" + +namespace MipsISA +{ + // See MIPS32(R) Architecture Reference Manual Volume - III + // This header file uses definitions from Revision 2.50 + + // Index Status Register - CP0 Reg 0, Sel 0 + + const unsigned Index_P_HI = 31; + const unsigned Index_P_LO = 31; + // Need to figure out how to put in the TLB specific bits here + // For now, we assume that the entire length is used by the index field + // In reality, Index_HI = N-1, where Ceiling(log2(TLB Entries))=N + const unsigned Index_HI = 30; + const unsigned Index_LO = 0; + + // CP0 Reg 0, Sel 1-3 are MT registers, see mt_constants.hh + + // Random Register - CP0 Reg 1, Sel 0 + // This has a problem similar to the Index_HI fields. We'll keep both consistent at 30 for now + const unsigned Random_HI = 30; + const unsigned Random_LO = 0; + + // EntryLo0 - CP0 Reg2, Sel 0 - Table 8-6, ARM Vol-3 + const unsigned EntryLo0_Fill_HI = 31; // See Table 8-8, ARM Vol III + const unsigned EntryLo0_Fill_LO = 30; + const unsigned EntryLo0_PFN_HI = 29; //PFN defines the Page Frame Number (see Table 8-7, ARM Vol III) + const unsigned EntryLo0_PFN_LO = 6; + const unsigned EntryLo0_C_HI = 5; // Coherency attribute of a Page (see Table 8-8, ARM Vol III) + const unsigned EntryLo0_C_LO = 3; + const unsigned EntryLo0_D = 2; // Dirty Bit, if D=1, page is writable. If D=0, a write causes a TLB Modified Exception + const unsigned EntryLo0_V = 1; // Valid Bit + const unsigned EntryLo0_G = 0; // Global Bit. From the ARM Vol-III, Table 8-5: + // On a TLB write, the logical AND of the G bits from EntryLo0 and EntryLo1 + // becomes the G bit in the TLB entry. If the TLB entry G bit is 1, ASID comparisons are + // ignored during TLB matches. On a read from a TLB entry, the G bits of both Lo0 and Lo1 + // reflect the state of the TLB G bit. + + // EntryLo1 - CP0 Reg3, Sel 0 + const unsigned EntryLo1_G = 0; + const unsigned EntryLo1_V = 1; // Valid Bit + const unsigned EntryLo1_D = 2; // Dirty Bit, if D=1, page is writable. If D=0, a write causes a TLB Modified Exception + const unsigned EntryLo1_C_HI = 5; // Coherency attribute of a Page (see Table 8-8, ARM Vol III) + const unsigned EntryLo1_C_LO = 3; + const unsigned EntryLo1_PFN_HI = 29; //PFN defines the Page Frame Number (see Table 8-7, ARM Vol III) + const unsigned EntryLo1_PFN_LO = 6; + const unsigned EntryLo1_Fill_LO = 30; + const unsigned EntryLo1_Fill_HI = 31; // See Table 8-8, ARM Vol III + + + // Context Register - CP0 Reg 4, Sel 0 + const unsigned Context_PTEBase_HI = 31; // Used by the OS to point into current PTE array + const unsigned Context_PTEBase_LO = 23; + const unsigned Context_BadVPN2_HI = 22; // This is written by hardware on a TLB exception. Contains bits 31-13 of the + const unsigned Context_BadVPN2_LO = 4; // virtual address + // Bits 3-0 are zeros + + // PageMask Register - CP0 Reg 5, Sel 0 + // Bits 31-29 are 0 + const unsigned PageMask_Mask_HI = 28; // (Table 8-10, ARM Vol-III) The Mask field is a bit mask in which a "1" indicates that + const unsigned PageMask_Mask_LO = 13; // the corresponding bit of the virtual address should not participate in the TLB match + const unsigned PageMask_MaskX_HI = 12; // See Table 8-10, ARM Vol-III + const unsigned PageMask_MaskX_LO = 11; + // Bits 10-0 are zero + + + // PageGrain Register - CP0 Reg 5, Sel 1 + const unsigned PageGrain_ASE_UP_HI = 31; // ASE specific bits (SmartMIPS) + const unsigned PageGrain_ASE_UP_LO = 30; // + const unsigned PageGrain_ELPA = 29; // Used to enable support for large physical addresses in MIPS64 processors, unused in MIPS32 + const unsigned PageGrain_ESP = 28; // Enables support for 1KB pages (1==enabled,0==disabled), See ARM Vol-III, Table 8-12 + const unsigned PageGrain_ASE_DN_HI = 12; + const unsigned PageGrain_ASE_DN_LO = 8; + // Bits 27-13, 7-0 are zeros + + // Wired Register - CPO Reg 6, Sel 0 + // See note on Index register (CP0, Sel0) above + const unsigned Wired_HI = 30; + const unsigned Wired_LO = 0; + + + // HWREna Register - CP0 Reg 7, Sel 0 + const unsigned HWREna_IMPL_HI = 31; // These bits enable access to implementation dependent hardware registers 31 + const unsigned HWREna_IMPL_LO = 30; // and 30 + const unsigned HWREna_Mask_HI = 3; // Each bit enables access to a particular hardware register. If bit 'n' is 1, HW Reg n is accessible + const unsigned HWREna_Mask_LO = 0; // See the RDHWR instruction for more details + + + // BadVAddr Register - CP0 Reg 8, Sel 0 + const unsigned BadVAddr_HI = 31; + const unsigned BadVAddr_LO = 0; + + // Count Register - CP0 Reg 9, Sel 0 + const unsigned Count_HI = 31; + const unsigned Count_LO = 0; + + // EntryHI Register - CP0 Reg 10, Sel 0 + const unsigned Entry_HI_VPN2_HI = 31; // This field is written by hardware on a TLB exception or on a TLB read + const unsigned Entry_HI_VPN2_LO = 13; // and is written by software before a TLB write + const unsigned Entry_HI_VPN2X_HI = 12; // Extension to support 1KB pages + const unsigned Entry_HI_VPN2X_LO = 11; + const unsigned Entry_HI_ASID_HI = 7; // Address space identifier + const unsigned Entry_HI_ASID_LO = 0; + + // Compare Register - CP0 Reg 11, Sel 0 + const unsigned Compare_HI = 31; // Used in conjunction with Count + const unsigned Compare_LO = 0; + + // Status Register - CP Reg 12, Sel 0 + const unsigned Status_IE_HI = 0; + const unsigned Status_IE_LO = 0; + + const unsigned Status_EXL_HI = 1; + const unsigned Status_EXL_LO = 1; + const unsigned Status_ERL_HI = 2; + const unsigned Status_ERL_LO = 2; + const unsigned Status_R0 = 3; + const unsigned Status_UM = 4; + const unsigned Status_KSU_HI = 4; // R0 and UM are also aliased as KSU + const unsigned Status_KSU_LO = 3; + const unsigned Status_UX = 5; + const unsigned Status_SX = 6; + const unsigned Status_KX = 7; + const unsigned Status_IM0 = 8; + const unsigned Status_IM1 = 9; + const unsigned Status_IM2 = 10; + const unsigned Status_IM3 = 11; + const unsigned Status_IM4 = 12; + const unsigned Status_IM5 = 13; + const unsigned Status_IM6 = 14; + const unsigned Status_IM7 = 15; + const unsigned Status_IPL_HI = 15; // IM7..IM2 are also aliased as IPL + const unsigned Status_IPL_LO = 10; + const unsigned Status_IMPL_HI = 17; + const unsigned Status_IMPL_LO = 16; + const unsigned Status_NMI = 19; + const unsigned Status_SR = 20; + const unsigned Status_TS = 21; + const unsigned Status_BEV = 22; + const unsigned Status_PX = 23; + const unsigned Status_MX = 24; + const unsigned Status_RE = 25; + const unsigned Status_FR = 26; + const unsigned Status_RP = 27; + const unsigned Status_CU3_HI = 31; + const unsigned Status_CU3_LO = 31; + const unsigned Status_CU2_HI = 30; + const unsigned Status_CU2_LO = 30; + const unsigned Status_CU1_HI = 29; + const unsigned Status_CU1_LO = 29; + const unsigned Status_CU0_HI = 28; + const unsigned Status_CU0_LO = 28; + + // IntCtl Register - CP0 Reg 12, Sel 1 + // Interrupt System status and control + const unsigned IntCtl_IPTI_HI = 31; + const unsigned IntCtl_IPTI_LO = 29; + const unsigned IntCtl_IPPCI_HI = 28; + const unsigned IntCtl_IPPCI_LO = 26; + const unsigned IntCtl_VS_HI = 9; + const unsigned IntCtl_VS_LO = 5; + // Bits 26-10, 4-0 are zeros + + // SRSCtl Register - CP0 Reg 12, Sel 2 + // Shadow Register Set Status and Control + const unsigned SRSCtl_HSS_HI=29; // Highest Shadow Set + const unsigned SRSCtl_HSS_LO=26; + const unsigned SRSCtl_EICSS_HI=21; //EIC interrupt mode shadow set + const unsigned SRSCtl_EICSS_LO=18; + const unsigned SRSCtl_ESS_HI=15; // Exception Shadow Set + const unsigned SRSCtl_ESS_LO=12; + const unsigned SRSCtl_PSS_HI=9; // Previous Shadow Set + const unsigned SRSCtl_PSS_LO=6; + const unsigned SRSCtl_CSS_HI=3; // Current Shadow Set + const unsigned SRSCtl_CSS_LO=0; + + // SRSMap Register - CP0 Reg 12, Sel 3 + // Shadow Set IPL mapping + const unsigned SRSMap_SSV7_HI = 31; // Shadow sets for particular vector numbers (7..0) + const unsigned SRSMap_SSV7_LO = 28; + const unsigned SRSMap_SSV6_HI = 27; + const unsigned SRSMap_SSV6_LO = 24; + const unsigned SRSMap_SSV5_HI = 23; + const unsigned SRSMap_SSV5_LO = 20; + const unsigned SRSMap_SSV4_HI = 19; + const unsigned SRSMap_SSV4_LO = 16; + const unsigned SRSMap_SSV3_HI = 15; + const unsigned SRSMap_SSV3_LO = 12; + const unsigned SRSMap_SSV2_HI = 11; + const unsigned SRSMap_SSV2_LO = 8; + const unsigned SRSMap_SSV1_HI = 7; + const unsigned SRSMap_SSV1_LO = 4; + const unsigned SRSMap_SSV0_HI = 3; + const unsigned SRSMap_SSV0_LO = 20; + + // Cause Register - CP0 Reg 13, Sel 0 + const unsigned Cause_BD = 31; + const unsigned Cause_TI = 30; + const unsigned Cause_CE_HI = 29; + const unsigned Cause_CE_LO = 28; + const unsigned Cause_DC = 27; + const unsigned Cause_PCI = 26; + const unsigned Cause_IV = 24; + const unsigned Cause_WP = 23; + const unsigned Cause_RIPL_HI = 15; // The individual bits of RIPL are also available as IP7..IP5 + const unsigned Cause_RIPL_LO = 10; + const unsigned Cause_IP7 = 15; + const unsigned Cause_IP6 = 14; + const unsigned Cause_IP5 = 13; + const unsigned Cause_IP4 = 12; + const unsigned Cause_IP3 = 11; + const unsigned Cause_IP2 = 10; + const unsigned Cause_IP1 = 9; + const unsigned Cause_IP0 = 8; + const unsigned Cause_EXCCODE_HI = 6; + const unsigned Cause_EXCCODE_LO = 2; + // All intermediate undefined bits must be ZERO + + + // EPC Register - CP0 Reg 14, Sel 0 + // Exception Program Counter + const unsigned EPC_HI = 31; + const unsigned EPC_LO = 0; + + // PRId Register - CP0 Reg 15, Sel 0 + // Processor Identification register + const unsigned PRIdCoOp_HI = 31; + const unsigned PRIdCoOp_LO = 24; + const unsigned PRIdCoID_HI = 23; + const unsigned PRIdCoID_LO = 16; + const unsigned PRIdProc_ID_HI = 15; + const unsigned PRIdProc_ID_LO = 8; + const unsigned PRIdRev_HI = 7; + const unsigned PRIdRev_LO = 0; + + + // EBase Register - CP0 Reg 15, Sel 1 + // Exception Base Register + const unsigned EBase_MSB = 31; // MUST BE = 1 + const unsigned EBase_EXCEPTION_Base_HI = 29; + const unsigned EBase_EXCEPTION_Base_LO = 12; + const unsigned EBase_CPUNum_HI = 9; + const unsigned EBase_CPUNum_LO = 0; + // Undefined bits must be zero + + // Config Register - CP0 Reg 16, Sel 0 + const unsigned Config_M = 31; + const unsigned Config_K23_HI = 30; + const unsigned Config_K23_LO = 28; + const unsigned Config_KU_HI = 27; + const unsigned Config_KU_LO = 25; + const unsigned Config_IMPL_HI = 24; + const unsigned Config_IMPL_LO = 16; + const unsigned Config_BE = 15; + const unsigned Config_AT_HI = 14; + const unsigned Config_AT_LO = 13; + const unsigned Config_AR_HI = 12; + const unsigned Config_AR_LO = 10; + const unsigned Config_MT_HI = 9; + const unsigned Config_MT_LO = 7; + const unsigned Config_VI = 3; + const unsigned Config_K0_HI = 2; + const unsigned Config_K0_LO = 0; + + // Config1 Register - CP0 Reg 16, Sel 1 + const unsigned Config1_M = 31; + const unsigned Config1_MMUSize_HI = 30; + const unsigned Config1_MMUSize_LO = 25; + const unsigned Config1_IS_HI = 24; + const unsigned Config1_IS_LO = 22; + const unsigned Config1_IL_HI = 21; + const unsigned Config1_IL_LO = 19; + const unsigned Config1_IA_HI = 18; + const unsigned Config1_IA_LO = 16; + const unsigned Config1_DS_HI = 15; + const unsigned Config1_DS_LO = 13; + const unsigned Config1_DL_HI = 12; + const unsigned Config1_DL_LO = 10; + const unsigned Config1_DA_HI = 9; + const unsigned Config1_DA_LO = 7; + const unsigned Config1_C2 = 6; + const unsigned Config1_MD = 5; + const unsigned Config1_PC = 4; + const unsigned Config1_WR = 3; + const unsigned Config1_CA = 2; + const unsigned Config1_EP = 1; + const unsigned Config1_FP = 0; + + + // Config2 Register - CP0 Reg 16, Sel 2 + const unsigned Config2_M = 31; + const unsigned Config2_TU_HI = 30; + const unsigned Config2_TU_LO = 28; + const unsigned Config2_TS_HI = 27; + const unsigned Config2_TS_LO = 24; + const unsigned Config2_TL_HI = 23; + const unsigned Config2_TL_LO = 20; + const unsigned Config2_TA_HI = 19; + const unsigned Config2_TA_LO = 16; + const unsigned Config2_SU_HI = 15; + const unsigned Config2_SU_LO = 12; + const unsigned Config2_SS_HI = 11; + const unsigned Config2_SS_LO = 8; + const unsigned Config2_SL_HI = 7; + const unsigned Config2_SL_LO = 4; + const unsigned Config2_SA_HI = 3; + const unsigned Config2_SA_LO = 0; + + // Config3 Register - CP0 Reg 16, Sel 3 + const unsigned Config3_M = 31; + const unsigned Config3_DSPP = 10; + const unsigned Config3_LPA=7; + const unsigned Config3_VEIC=6; + const unsigned Config3_VINT=5; + const unsigned Config3_SP=4; + const unsigned Config3_MT=2; + const unsigned Config3_SM=1; + const unsigned Config3_TL=0; + + + // LLAddr Register - CP0 Reg 17, Sel 0 + // Load Linked Address (Physical) + const unsigned LLAddr_PAddr_HI = 31; + const unsigned LLAddr_PAddr_LO = 0; + + + + // WatchLo Register - CP0 Reg 18, Sel 0-n + // See WatchHi to determine how many pairs of these registers are available + const unsigned WatchLo_VAddr_HI = 31; + const unsigned WatchLo_VAddr_LO = 3; + const unsigned WatchLo_I = 2; + const unsigned WatchLo_R = 1; + const unsigned WatchLo_W = 0; + + + // WatchHi Register - CP0 Reg 19, Sel 0-n + const unsigned WatchHi_M = 31; // If M = 1, another pair of WatchHi/Lo registers exist + const unsigned WatchHi_G = 30; + const unsigned WatchHi_ASID_HI = 23; + const unsigned WatchHi_ASID_LO = 16; + const unsigned WatchHi_Mask_HI = 11; + const unsigned WatchHi_Mask_LO = 3; + const unsigned WatchHi_I = 2; + const unsigned WatchHi_R = 1; + const unsigned WatchHi_W = 0; + + // Debug Register - CP0 Reg 23, Sel 0 + + // TraceControl Register - CP0 Reg 23, Sel 1 + // TraceControl2 Register - CP0 Reg 23, Sel 2 + // UserTraceData Register - CP0 Reg 23, Sel 3 + // TraceBPC Register - CP0 Reg 23, Sel 4 + // DEPC Register - CP0 Reg 24, Sel 0 + + + // PerfCnt Register - CP0 Reg 25, Sel 0-n + // Each Perf. counter that exists is mapped onto even-odd select pairs of Reg 25 + // Even values are control registers, odd values are the actual counter + // The format for the control reg is: + const unsigned PerfCntCtl_M = 31; // Is there another pair of perf counter registers? + const unsigned PerfCntCtl_W = 30; + const unsigned PerfCntCtl_Event_HI = 10; + const unsigned PerfCntCtl_Event_LO = 5; + const unsigned PerfCntCtl_IE = 4; + const unsigned PerfCntCtl_U = 3; + const unsigned PerfCntCtl_S = 2; + const unsigned PerfCntCtl_K = 1; + const unsigned PerfCntCtl_EXL = 0; + + // The format for the counter is a 32-bit value (or 64-bit for MIPS64) + const unsigned PerfCnt_Count_HI = 31; + const unsigned PerfCnt_Count_LO = 0; + + // ErrCtl Register - CP0 Reg 26, Sel 0 + // This is implementation dependent, not defined by the ISA + + // CacheErr Register - CP0 Reg 27, Sel 0 + // NOTE: Page 65 of the ARM, Volume-III indicates that there are four sel. values (0-3) + // used by the CacheErr registers. However, on page 134, only one sel value is shown + const unsigned Cache_Err_ER = 31; + const unsigned Cache_Err_EC = 30; + const unsigned Cache_Err_ED = 29; + const unsigned Cache_Err_ET = 28; + const unsigned Cache_Err_ES = 27; + const unsigned Cache_Err_EE = 26; + const unsigned Cache_Err_EB = 25; + const unsigned Cache_Err_IMPL_HI = 24; + const unsigned Cache_Err_IMPL_LO = 22; + const unsigned Cache_Err_Index_HI = 21; + const unsigned Cache_Err_Index_LO = 0; + + // TagLo Register - CP0 Reg 28 - Even Selects (0,2) + const unsigned TagLo_PTagLo_HI = 31; + const unsigned TagLo_PTagLo_LO = 8; + const unsigned TagLo_PState_HI = 7; + const unsigned TagLo_PState_LO = 6; + const unsigned TagLo_L = 5; + const unsigned TagLo_IMPL_HI = 4; + const unsigned TagLo_IMPL_LO = 3; + const unsigned TagLo_P = 0; + // undefined bits must be written 0 + + + // DataLo Register - CP0 Reg 28 - Odd Selects (1,3) + const unsigned DataLo_HI = 31; + const unsigned DataLo_LO = 0; + + // TagHi Register - CP0 Reg 29 - Even Selects (0,2) + // Not defined by the architecture + + // DataHi Register - CP0 Reg 29 - Odd Selects (1,3) + const unsigned DataHi_HI = 31; + const unsigned DataHi_LO = 0; + + + // ErrorEPC - CP0 Reg 30, Sel 0 + const unsigned ErrorPC_HI = 31; + const unsigned ErrorPC_LO = 0; + + // DESAVE - CP0 Reg 31, Sel 0 + + + + + +} // namespace MipsISA + +#endif diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index af85e8ee9..b6249f76d 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -48,12 +48,12 @@ class MipsLiveProcess : public LiveProcess System *_system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, std::vector<std::string> &envp, - const std::string &cwd, + const std::string &cwd, uint64_t _uid, uint64_t _euid, uint64_t _gid, uint64_t _egid, uint64_t _pid, uint64_t _ppid); - void startup(); + virtual void startup(); }; diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh index ce5f1fdde..21c16c238 100644 --- a/src/arch/mips/regfile/float_regfile.hh +++ b/src/arch/mips/regfile/float_regfile.hh @@ -88,12 +88,9 @@ namespace MipsISA public: - void clear() - { - bzero(regs, sizeof(regs)); - } + void clear() { bzero(®s, sizeof(regs)); } - double readReg(int floatReg, int width) + double readReg(int floatReg, int width, unsigned tid = 0) { switch(width) { @@ -115,7 +112,7 @@ namespace MipsISA } } - FloatRegBits readRegBits(int floatReg, int width) + FloatRegBits readRegBits(int floatReg, int width, unsigned tid = 0) { if (floatReg < NumFloatArchRegs - 1) { switch(width) @@ -137,8 +134,9 @@ namespace MipsISA } } - Fault setReg(int floatReg, const FloatRegVal &val, int width) + Fault setReg(int floatReg, const FloatRegVal &val, int width, unsigned tid = 0) { + using namespace std; switch(width) { case SingleWidth: @@ -165,8 +163,9 @@ namespace MipsISA return NoFault; } - Fault setRegBits(int floatReg, const FloatRegBits &val, int width) + Fault setRegBits(int floatReg, const FloatRegBits &val, int width, unsigned tid = 0) { + using namespace std; switch(width) { diff --git a/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh index a45a17a85..2a034ad8d 100644 --- a/src/arch/mips/regfile/int_regfile.hh +++ b/src/arch/mips/regfile/int_regfile.hh @@ -47,8 +47,21 @@ namespace MipsISA } enum MiscIntRegNums { - HI = NumIntArchRegs, - LO + LO = NumIntArchRegs, + HI, + DSPACX0, + DSPLo1, + DSPHi1, + DSPACX1, + DSPLo2, + DSPHi2, + DSPACX2, + DSPLo3, + DSPHi3, + DSPACX3, + DSPControl, + DSPLo0 = LO, + DSPHi0 = HI }; class IntRegFile @@ -57,6 +70,8 @@ namespace MipsISA IntReg regs[NumIntRegs]; public: + void clear() { bzero(®s, sizeof(regs)); } + IntReg readReg(int intReg) { return regs[intReg]; @@ -64,7 +79,10 @@ namespace MipsISA Fault setReg(int intReg, const IntReg &val) { - regs[intReg] = val; + if (intReg != ZeroReg) { + regs[intReg] = val; + } + return NoFault; } diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc new file mode 100755 index 000000000..c97d93cf9 --- /dev/null +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#include "base/bitfield.hh" + +#include "arch/mips/regfile/misc_regfile.hh" +#include "arch/mips/mt_constants.hh" +#include "arch/mips/faults.hh" + +#include "cpu/thread_context.hh" +#include "cpu/base.hh" +#include "cpu/exetrace.hh" +//#include "cpu/mixie/cpu.hh" + +using namespace std; + +std::string MiscRegFile::miscRegNames[NumMiscRegs] = +{"Index", "MVPControl", "MVPConf0", "MVPConf1", "", "", "", "", + "Random", "VPEControl", "VPEConf0", "VPEConf1", "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt", + "EntryLo0", "TCStatus", "TCBind", "TCRestart", "TCHalt", "TCContext", "TCSchedule", "TCScheFBack", + "EntryLo1", "", "", "", "", "", "", "", + "Context", "ContextConfig", "", "", "", "", "", "", + "PageMask", "PageGrain", "", "", "", "", "", "", + "Wired", "SRSConf0", "SRCConf1", "SRSConf2", "SRSConf3", "SRSConf4", "", "", + "HWREna", "", "", "", "", "", "", "", + "BadVAddr", "", "", "", "", "", "", "", + "Count", "", "", "", "", "", "", "", + "EntryHi", "", "", "", "", "", "", "", + "Compare", "", "", "", "", "", "", "", + "Status", "IntCtl", "SRSCtl", "SRSMap", "", "", "", "", + "Cause", "", "", "", "", "", "", "", + "EPC", "", "", "", "", "", "", "", + "PRId", "EBase", "", "", "", "", "", "", + "Config", "Config1", "Config2", "Config3", "", "", "", "", + "LLAddr", "", "", "", "", "", "", "", + "WatchLo0", "WatchLo1", "WatchLo2", "WatchLo3", "WatchLo4", "WatchLo5", "WatchLo6", "WatchLo7", + "WatchHi0", "WatchHi1", "WatchHi2", "WatchHi3", "WatchHi4", "WatchHi5", "WatchHi6", "WatchHi7", + "XCContext64", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "Debug", "TraceControl1", "TraceControl2", "UserTraceData", "TraceBPC", "", "", "", + "DEPC", "", "", "", "", "", "", "", + "PerfCnt0", "PerfCnt1", "PerfCnt2", "PerfCnt3", "PerfCnt4", "PerfCnt5", "PerfCnt6", "PerfCnt7", + "ErrCtl", "", "", "", "", "", "", "", + "CacheErr0", "CacheErr1", "CacheErr2", "CacheErr3", "", "", "", "", + "TagLo0", "DataLo1", "TagLo2", "DataLo3", "TagLo4", "DataLo5", "TagLo6", "DataLo7", + "TagHi0", "DataHi1", "TagHi2", "DataHi3", "TagHi4", "DataHi5", "TagHi6", "DataHi7", + "ErrorEPC", "", "", "", "", "", "", "", + "DESAVE", "", "", "", "", "", "", "", + "LLFlag" +}; + +MiscRegFile::MiscRegFile() +{ + init(); +} + +MiscRegFile::MiscRegFile(BaseCPU *_cpu) +{ + cpu = _cpu; + init(); +} + +void +MiscRegFile::init() +{ + miscRegFile.resize(NumMiscRegs); + bankType.resize(NumMiscRegs); + + for (int i=0; i < NumMiscRegs; i++) { + miscRegFile[i].resize(1); + bankType[i] = perProcessor; + } + + clear(0); +} + +void +MiscRegFile::clear(unsigned tid_or_vpn) +{ + for(int i = 0; i < NumMiscRegs; i++) { + miscRegFile[i][tid_or_vpn] = 0; + } +} + +void +MiscRegFile::expandForMultithreading(unsigned num_threads, unsigned num_vpes) +{ + // Initialize all Per-VPE regs + uint32_t per_vpe_regs[] = { VPEControl, VPEConf0, VPEConf1, YQMask, + VPESchedule, VPEScheFBack, VPEOpt, SRSConf0, + SRSConf1, SRSConf2, SRSConf3, SRSConf4, + EBase + }; + uint32_t num_vpe_regs = sizeof(per_vpe_regs) / 4; + for (int i = 0; i < num_vpe_regs; i++) { + if (num_vpes > 1) { + miscRegFile[per_vpe_regs[i]].resize(num_vpes); + } + bankType[per_vpe_regs[i]] = perVirtProcessor; + } + + // Initialize all Per-TC regs + uint32_t per_tc_regs[] = { Status, TCStatus, TCBind, TCRestart, TCHalt, + TCContext, TCSchedule, TCScheFBack, Debug, + LLAddr + }; + uint32_t num_tc_regs = sizeof(per_tc_regs) / 4; + + for (int i = 0; i < num_tc_regs; i++) { + miscRegFile[per_tc_regs[i]].resize(num_threads); + bankType[per_tc_regs[i]] = perThreadContext; + } + + + if (num_vpes > 1) { + for (int i=1; i < num_vpes; i++) { + clear(i); + } + } + +} + +//@TODO: Use MIPS STYLE CONSTANTS (e.g. TCHALT_H instead of TCH_H) +void +MiscRegFile::reset(std::string core_name, unsigned num_threads, + unsigned num_vpes) +{ + DPRINTF(MipsPRA, "Resetting CP0 State with %i TCs and %i VPEs\n", + num_threads, num_vpes); + + // Do Default CP0 initialization HERE + + // Do Initialization for MT cores here (eventually use + // core_name parameter to toggle this initialization) + // =================================================== + // Config + MiscReg cfg = readRegNoEffect(Config); + replaceBits(cfg, CFG_M, 1); + setRegNoEffect(Config, cfg); + + // Config1 + MiscReg cfg1 = readRegNoEffect(Config1); + replaceBits(cfg1, CFG1_M, 1); + setRegNoEffect(Config1, cfg1); + + // Config2 + MiscReg cfg2 = readRegNoEffect(Config2); + replaceBits(cfg2, CFG2_M, 1); + setRegNoEffect(Config2, cfg2); + + // Config3 + MiscReg cfg3 = readRegNoEffect(Config3); + replaceBits(cfg3, CFG3_MT, 1); + setRegNoEffect(Config3, cfg3); + + // MVPConf0 + MiscReg mvp_conf0 = readRegNoEffect(MVPConf0); + replaceBits(mvp_conf0, MVPC0_TCA, 1); + replaceBits(mvp_conf0, MVPC0_PVPE_HI, MVPC0_PVPE_LO, num_vpes - 1); + replaceBits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO, num_threads - 1); + setRegNoEffect(MVPConf0, mvp_conf0); + + // VPEConf0 + MiscReg vpe_conf0 = readRegNoEffect(VPEConf0); + replaceBits(vpe_conf0, VPEC0_MVP, 1); + setRegNoEffect(VPEConf0, vpe_conf0); + + // TCBind + for (int tid = 0; tid < num_threads; tid++) { + MiscReg tc_bind = readRegNoEffect(TCBind, tid); + replaceBits(tc_bind, TCB_CUR_TC_HI, TCB_CUR_TC_LO, tid); + setRegNoEffect(TCBind, tc_bind, tid); + } + + // TCHalt + MiscReg tc_halt = readRegNoEffect(TCHalt); + replaceBits(tc_halt, TCH_H, 0); + setRegNoEffect(TCHalt, tc_halt); + /*for (int tid = 1; tid < num_threads; tid++) { + // Set TCHalt Halt bit to 1 for all other threads + tc_halt = readRegNoEffect(TCHalt, tid); + replaceBits(tc_halt, TCH_H, 1); + setReg(TCHalt, tc_halt, tid); + }*/ + + // TCStatus + // Set TCStatus Activated to 1 for the initial thread that is running + MiscReg tc_status = readRegNoEffect(TCStatus); + replaceBits(tc_status, TCS_A, 1); + setRegNoEffect(TCStatus, tc_status); + + // Set Dynamically Allocatable bit to 1 for all other threads + for (int tid = 0; tid < num_threads; tid++) { + tc_status = readRegNoEffect(TCStatus, tid); + replaceBits(tc_status, TCSTATUS_DA, 1); + setRegNoEffect(TCStatus, tc_status, tid); + } +} + +inline std::string +MipsISA::getMiscRegName(unsigned reg_idx) +{ + return MiscRegFile::miscRegNames[reg_idx]; +} + +inline unsigned +MiscRegFile::getVPENum(unsigned tid) +{ + unsigned tc_bind = miscRegFile[TCBind][tid]; + return bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); +} + +MiscReg +MiscRegFile::readRegNoEffect(int misc_reg, unsigned tid) +{ + unsigned reg_sel = (bankType[misc_reg] == perThreadContext) + ? tid : getVPENum(tid); + + return miscRegFile[misc_reg][reg_sel]; +} + +//@TODO: MIPS MT's register view automatically connects +// Status to TCStatus depending on current thread +MiscReg +MiscRegFile::readReg(int misc_reg, + ThreadContext *tc, unsigned tid) +{ + DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) with effect.\n", + misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg)); + + unsigned reg_sel = (bankType[misc_reg] == perThreadContext) + ? tid : getVPENum(tid); + + switch (misc_reg) + { + default: + return miscRegFile[misc_reg][reg_sel]; + } +} + +void +MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid) +{ + unsigned reg_sel = (bankType[misc_reg] == perThreadContext) + ? tid : getVPENum(tid); + + miscRegFile[misc_reg][reg_sel] = val; +} + +// PROGRAMMER'S NOTES: +// (1) Some CP0 Registers have fields that cannot +// be overwritten. Make sure to handle those particular registers +// with care! +void +MiscRegFile::setReg(int misc_reg, const MiscReg &val, + ThreadContext *tc, unsigned tid) +{ + unsigned reg_sel = (bankType[misc_reg] == perThreadContext) + ? tid : getVPENum(tid); + + DPRINTF(MipsPRA, "[tid:%i]: Setting CP0 Register:%u Select:%u (%s) to %#x, with effect.\n", + tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); + + MiscReg cp0_val = filterCP0Write(misc_reg, val); + + miscRegFile[misc_reg][reg_sel] = cp0_val; + + scheduleCP0Update(); +} + +void +MiscRegFile::scheduleCP0Update(int delay) +{ + if (!cp0Updated) { + cp0Updated = true; + + //schedule UPDATE + CP0Event *cp0_event = new CP0Event(this, cpu, UpdateCP0); + cp0_event->schedule(curTick + cpu->cycles(delay)); + } +} + +void +MiscRegFile::updateCPU() +{ + /////////////////////////////////////////////////////////////////// + // + // EVALUATE CP0 STATE FOR MIPS MT + // + /////////////////////////////////////////////////////////////////// + unsigned mvp_conf0 = readRegNoEffect(MVPConf0); + unsigned num_threads = bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; + + for (int tid = 0; tid < num_threads; tid++) { + MiscReg tc_status = readRegNoEffect(TCStatus, tid); + MiscReg tc_halt = readRegNoEffect(TCHalt, tid); + + //@todo: add vpe/mt check here thru mvpcontrol & vpecontrol regs + if (bits(tc_halt, TCH_H) == 1 || bits(tc_status, TCS_A) == 0) { + haltThread(cpu->getContext(tid)); + } else if (bits(tc_halt, TCH_H) == 0 && bits(tc_status, TCS_A) == 1) { + restoreThread(cpu->getContext(tid)); + } + } + + num_threads = bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; + + // Toggle update flag after we finished updating + cp0Updated = false; +} + +MiscRegFile::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type) + : Event(&mainEventQueue, CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type) +{ } + +void +MiscRegFile::CP0Event::process() +{ + switch (cp0EventType) + { + case UpdateCP0: + cp0->updateCPU(); + break; + } + + //cp0EventRemoveList.push(this); +} + +const char * +MiscRegFile::CP0Event::description() +{ + return "Coprocessor-0 event"; +} + +void +MiscRegFile::CP0Event::scheduleEvent(int delay) +{ + if (squashed()) + reschedule(curTick + cpu->cycles(delay)); + else if (!scheduled()) + schedule(curTick + cpu->cycles(delay)); +} + +void +MiscRegFile::CP0Event::unscheduleEvent() +{ + if (scheduled()) + squash(); +} diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index 53ee09512..54b086a8b 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -31,213 +31,128 @@ #ifndef __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__ #define __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__ +#include "arch/mips/isa_traits.hh" #include "arch/mips/types.hh" +#include "arch/mips/mt.hh" +#include "arch/mips/mt_constants.hh" +#include "base/bitfield.hh" +#include "cpu/base.hh" #include "sim/faults.hh" +#include <queue> class ThreadContext; namespace MipsISA { - static inline std::string getMiscRegName(RegIndex) - { - return ""; - } - - //Coprocessor 0 Register Names - enum MiscRegTags { - //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8 - //(Register Number-Register Select) Summary of Register - //------------------------------------------------------ - Index = 0, //Bank 0: 0 - 3 - MVPControl, - MVPConf0, - MVPConf1, - - Random = 8, //Bank 1: 8 - 15 - VPEControl, - VPEConf0, - VPEConf1, - YQMask, - VPESchedule, - VPEScheFBack, - VPEOpt, - - EntryLo0 = 16, //Bank 2: 16 - 23 - TCStatus, - TCBind, - TCRestart, - TCHalt, - TCContext, - TCSchedule, - TCScheFBack, - - EntryLo1 = 24, // Bank 3: 24 - - Context = 32, // Bank 4: 32 - 33 - ContextConfig, - - //PageMask = 40, //Bank 5: 40 - 41 - PageGrain = 41, - - Wired = 48, //Bank 6: 48 - 55 - SRSConf0, - SRSConf1, - SRSConf2, - SRSConf3, - SRSConf4, - - HWRena = 56, //Bank 7: 56 - - BadVAddr = 63, //Bank 8: 63 - - Count = 64, //Bank 9: 64 - - EntryHi = 72, //Bank 10:72 - 79 - - Compare = 80, //Bank 10:80 - 87 - - Status = 88, //Bank 12:88 - 96 - IntCtl = 89, - SRSCtl = 90, - SRSMap = 91, - - Cause = 97, //97-104 - - EPC = 105, //105-112 - - PRId = 113, //113-120, - EBase = 114, - - Config = 121, //Bank 16: 121-128 - Config1 = 122, - Config2 = 123, - Config3 = 124, - Config6 = 127, - Config7 = 128, - - - LLAddr = 129, //Bank 17: 129-136 - - WatchLo0 = 137, //Bank 18: 137-144 - WatchLo1 = 138, - WatchLo2 = 139, - WatchLo3 = 140, - WatchLo4 = 141, - WatchLo5 = 142, - WatchLo6 = 143, - WatchLo7 = 144, - - WatchHi0 = 145,//Bank 19: 145-152 - WatchHi1 = 146, - WatchHi2 = 147, - WatchHi3 = 148, - WatchHi4 = 149, - WatchHi5 = 150, - WatchHi6 = 151, - WatchHi7 = 152, - - XCContext64 = 153, //Bank 20: 153-160 - - //Bank 21: 161-168 - - //Bank 22: 169-176 - - Debug = 177, //Bank 23: 177-184 - TraceControl1 = 178, - TraceControl2 = 179, - UserTraceData = 180, - TraceBPC = 181, - - DEPC = 185,//Bank 24: 185-192 - - PerfCnt0 = 193,//Bank 25: 193 - 200 - PerfCnt1 = 194, - PerfCnt2 = 195, - PerfCnt3 = 196, - PerfCnt4 = 197, - PerfCnt5 = 198, - PerfCnt6 = 199, - PerfCnt7 = 200, + class MiscRegFile { + public: + // Give RegFile object, private access + friend class RegFile; - ErrCtl = 201, //Bank 26: 201 - 208 + // The MIPS name for this file is CP0 or Coprocessor 0 + typedef MiscRegFile CP0; - CacheErr0 = 209, //Bank 27: 209 - 216 - CacheErr1 = 210, - CacheErr2 = 211, - CacheErr3 = 212, + protected: + enum BankType { + perProcessor, + perThreadContext, + perVirtProcessor + }; - TagLo0 = 217,//Bank 28: 217 - 224 - DataLo1 = 218, - TagLo2 = 219, - DataLo3 = 220, - TagLo4 = 221, - DataLo5 = 222, - TagLo6 = 223, - DataLo7 = 234, + std::vector<std::vector<MiscReg> > miscRegFile; + std::vector<BankType> bankType; - TagHi0 = 233,//Bank 29: 233 - 240 - DataHi1 = 234, - TagHi2 = 235, - DataHi3 = 236, - TagHi4 = 237, - DataHi5 = 238, - TagHi6 = 239, - DataHi7 = 240, + BaseCPU *cpu; + public: + MiscRegFile(); + MiscRegFile(BaseCPU *cpu); - ErrorEPC = 249,//Bank 30: 241 - 248 + void init(); - DESAVE = 257//Bank 31: 249-256 - }; + void clear(unsigned tid_or_vpn = 0); - class MiscRegFile { + void reset(std::string core_name, unsigned num_threads, unsigned num_vpes); - protected: - uint64_t fpcr; // floating point condition codes - // FPCR is not used in MIPS. Condition - // codes are kept as part of the FloatRegFile + void expandForMultithreading(unsigned num_threads, unsigned num_vpes); - bool lock_flag; // lock flag for LL/SC - // use LL reg. in the future + void copyMiscRegs(ThreadContext *tc); - Addr lock_addr; // lock address for LL/SC - // use LLAddr reg. in the future + inline unsigned getVPENum(unsigned tid); + + ////////////////////////////////////////////////////////// + // + // READ/WRITE CP0 STATE + // + // + ////////////////////////////////////////////////////////// + //@TODO: MIPS MT's register view automatically connects + // Status to TCStatus depending on current thread + void updateCP0ReadView(int misc_reg, unsigned tid) { } + MiscReg readRegNoEffect(int misc_reg, unsigned tid = 0); + MiscReg readReg(int misc_reg, + ThreadContext *tc, unsigned tid = 0); + + MiscReg filterCP0Write(int misc_reg, MiscReg val) { return val; } + void setRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0); + void setReg(int misc_reg, const MiscReg &val, + ThreadContext *tc, unsigned tid = 0); - MiscReg miscRegFile[NumMiscRegs]; + ////////////////////////////////////////////////////////// + // + // DECLARE INTERFACE THAT WILL ALLOW A MiscRegFile (Cop0) + // TO SCHEDULE EVENTS + // + ////////////////////////////////////////////////////////// - public: - void clear() - { - fpcr = 0; - lock_flag = 0; - lock_addr = 0; - } + // Flag that is set when CP0 state has been written to. + bool cp0Updated; - void copyMiscRegs(ThreadContext *tc); + // Enumerated List of CP0 Event Types + enum CP0EventType { + UpdateCP0 + }; - MiscReg readRegNoEffect(int misc_reg) + // Declare A CP0Event Class for scheduling + class CP0Event : public Event { - return miscRegFile[misc_reg]; - } + protected: + MiscRegFile::CP0 *cp0; + BaseCPU *cpu; + CP0EventType cp0EventType; + Fault fault; - MiscReg readReg(int misc_reg, ThreadContext *tc) - { - return miscRegFile[misc_reg]; - } + public: + /** Constructs a CP0 event. */ + CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type); - void setRegNoEffect(int misc_reg, const MiscReg &val) - { - miscRegFile[misc_reg] = val; - } + /** Process this event. */ + virtual void process(); - void setReg(int misc_reg, const MiscReg &val, - ThreadContext *tc) - { - miscRegFile[misc_reg] = val; - } + /** Returns the description of this event. */ + const char *description(); - friend class RegFile; + /** Schedule This Event */ + void scheduleEvent(int delay); + + /** Unschedule This Event */ + void unscheduleEvent(); + }; + + // Schedule a CP0 Update Event + void scheduleCP0Update(int delay = 0); + + // If any changes have been made, then check the state for changes + // and if necessary alert the CPU + void updateCPU(); + + // Keep a List of CPU Events that need to be deallocated + std::queue<CP0Event*> cp0EventRemoveList; + + static std::string miscRegNames[NumMiscRegs]; }; + + inline std::string getMiscRegName(unsigned reg_idx); } // namespace MipsISA #endif diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index 387fbd5c8..f13653132 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -32,6 +32,8 @@ #define __ARCH_MIPS_REGFILE_REGFILE_HH__ #include "arch/mips/types.hh" +#include "arch/mips/isa_traits.hh" +#include "arch/mips/mt.hh" #include "arch/mips/regfile/int_regfile.hh" #include "arch/mips/regfile/float_regfile.hh" #include "arch/mips/regfile/misc_regfile.hh" @@ -49,33 +51,50 @@ namespace MipsISA MiscRegFile miscRegFile; // control register file public: - void clear() { + intRegFile.clear(); + floatRegFile.clear(); + miscRegFile.clear(); + } + + void reset(std::string core_name, unsigned num_threads, unsigned num_vpes) + { bzero(&intRegFile, sizeof(intRegFile)); bzero(&floatRegFile, sizeof(floatRegFile)); - bzero(&miscRegFile, sizeof(miscRegFile)); + miscRegFile.reset(core_name, num_threads, num_vpes); + } + + IntReg readIntReg(int intReg) + { + return intRegFile.readReg(intReg); + } + + Fault setIntReg(int intReg, const IntReg &val) + { + return intRegFile.setReg(intReg, val); } - MiscReg readMiscRegNoEffect(int miscReg) + MiscReg readMiscRegNoEffect(int miscReg, unsigned tid = 0) { - return miscRegFile.readRegNoEffect(miscReg); + return miscRegFile.readRegNoEffect(miscReg, tid); } - MiscReg readMiscReg(int miscReg, ThreadContext *tc) + MiscReg readMiscReg(int miscReg, ThreadContext *tc, + unsigned tid = 0) { - return miscRegFile.readReg(miscReg, tc); + return miscRegFile.readReg(miscReg, tc, tid); } - void setMiscRegNoEffect(int miscReg, const MiscReg &val) + void setMiscRegNoEffect(int miscReg, const MiscReg &val, unsigned tid = 0) { - miscRegFile.setRegNoEffect(miscReg, val); + miscRegFile.setRegNoEffect(miscReg, val, tid); } void setMiscReg(int miscReg, const MiscReg &val, - ThreadContext * tc) + ThreadContext * tc, unsigned tid = 0) { - miscRegFile.setReg(miscReg, val, tc); + miscRegFile.setReg(miscReg, val, tc, tid); } FloatRegVal readFloatReg(int floatReg) @@ -98,35 +117,26 @@ namespace MipsISA return floatRegFile.readRegBits(floatReg,width); } - void setFloatReg(int floatReg, const FloatRegVal &val) - { - floatRegFile.setReg(floatReg, val, SingleWidth); - } - - void setFloatReg(int floatReg, const FloatRegVal &val, int width) + Fault setFloatReg(int floatReg, const FloatRegVal &val) { - floatRegFile.setReg(floatReg, val, width); + return floatRegFile.setReg(floatReg, val, SingleWidth); } - void setFloatRegBits(int floatReg, const FloatRegBits &val) + Fault setFloatReg(int floatReg, const FloatRegVal &val, int width) { - floatRegFile.setRegBits(floatReg, val, SingleWidth); + return floatRegFile.setReg(floatReg, val, width); } - void setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + Fault setFloatRegBits(int floatReg, const FloatRegBits &val) { - floatRegFile.setRegBits(floatReg, val, width); + return floatRegFile.setRegBits(floatReg, val, SingleWidth); } - IntReg readIntReg(int intReg) + Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) { - return intRegFile.readReg(intReg); + return floatRegFile.setRegBits(floatReg, val, width); } - void setIntReg(int intReg, const IntReg &val) - { - intRegFile.setReg(intReg, val); - } protected: Addr pc; // program counter @@ -134,6 +144,7 @@ namespace MipsISA Addr nnpc; // next-next-cycle program counter // used to implement branch delay slot // not real register + public: Addr readPC() { diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index 9ac4bb6d8..8f113fb82 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -28,12 +28,18 @@ * Authors: Korey Sewell */ -#include "arch/mips/regfile.hh" +#include "arch/mips/isa_traits.hh" #include "arch/mips/utility.hh" -#include "base/misc.hh" +#include "arch/mips/constants.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "cpu/static_inst.hh" +#include "sim/serialize.hh" #include "base/bitfield.hh" +#include "base/misc.hh" using namespace MipsISA; +using namespace std; uint64_t MipsISA::fpConvert(ConvertType cvt_type, double fp_val) @@ -197,3 +203,9 @@ MipsISA::isSnan(void *val_ptr, int size) panic("Type unsupported. Size mismatch\n"); } } + +void +MipsISA::startupCPU(ThreadContext *tc, int cpuId) +{ + tc->activate(0); +} diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index 12db1de57..e3fd9daa8 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -35,13 +35,15 @@ #define __ARCH_MIPS_UTILITY_HH__ #include "arch/mips/types.hh" +#include "arch/mips/isa_traits.hh" #include "base/misc.hh" #include "config/full_system.hh" -#include "cpu/thread_context.hh" //XXX This is needed for size_t. We should use something other than size_t //#include "kern/linux/linux.hh" #include "sim/host.hh" +#include "cpu/thread_context.hh" + class ThreadContext; namespace MipsISA { @@ -66,6 +68,8 @@ namespace MipsISA { template <class TC> void zeroRegisters(TC *tc); + void startupCPU(ThreadContext *tc, int cpuId); + void copyRegs(ThreadContext *src, ThreadContext *dest); // Instruction address compression hooks @@ -88,9 +92,17 @@ namespace MipsISA { return 0; } - inline void startupCPU(ThreadContext *tc, int cpuId) - { - tc->activate(0); + static inline ExtMachInst + makeExtMI(MachInst inst, ThreadContext * xc) { +#if FULL_SYSTEM + ExtMachInst ext_inst = inst; + if (xc->readPC() && 0x1) + return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32); + else + return ext_inst; +#else + return ExtMachInst(inst); +#endif } }; diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 518bad6b8..70a46386e 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -59,6 +59,17 @@ bits(T val, int first, int last) } /** + * Extract the bit from this position from 'val' and right justify it. + */ +template <class T> +inline +T +bits(T val, int bit) +{ + return bits(val, bit, bit); +} + +/** * Mask off the given bits in place like bits() but without shifting. * msb = 63, lsb = 0 */ @@ -102,6 +113,17 @@ insertBits(T val, int first, int last, B bit_val) } /** + * Overloaded for access to only one bit in value + */ +template <class T, class B> +inline +T +insertBits(T val, int bit, B bit_val) +{ + return insertBits(val, bit, bit, bit_val); +} + +/** * A convenience function to replace bits first to last of val with bit_val * in place. */ @@ -113,6 +135,14 @@ replaceBits(T& val, int first, int last, B bit_val) val = insertBits(val, first, last, bit_val); } +/** Overloaded function to allow to access only 1 bit*/ +template <class T, class B> +inline +void +replaceBits(T& val, int bit, B bit_val) +{ + val = insertBits(val, bit, bit, bit_val); +} /** * Returns the bit position of the MSB that is set in the input */ diff --git a/src/base/traceflags.py b/src/base/traceflags.py index f4cf7dfd7..70fadb210 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -129,6 +129,7 @@ baseFlags = [ 'MemDepUnit', 'MemoryAccess', 'MemTest', + 'MipsPRA', 'O3CPU', 'OzoneCPU', 'OzoneLSQ', diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index d221baca8..243167db0 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -215,6 +215,7 @@ class BaseSimpleCPU : public BaseCPU // need to do this... } + Fault copySrcTranslate(Addr src); Fault copy(Addr dest); @@ -353,6 +354,18 @@ class BaseSimpleCPU : public BaseCPU thread->setStCondFailures(sc_failures); } + MiscReg readRegOtherThread(int regIdx, int tid = -1) + { + panic("Simple CPU models do not support multithreaded " + "register access.\n"); + } + + void setRegOtherThread(int regIdx, const MiscReg &val, int tid = -1) + { + panic("Simple CPU models do not support multithreaded " + "register access.\n"); + } + #if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 95848ee2c..c20fe3d90 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -349,22 +349,22 @@ class SimpleThread : public ThreadState regs.setNextNPC(val); } - MiscReg readMiscRegNoEffect(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid = 0) { return regs.readMiscRegNoEffect(misc_reg); } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscReg(int misc_reg, unsigned tid = 0) { return regs.readMiscReg(misc_reg, tc); } - void setMiscRegNoEffect(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0) { return regs.setMiscRegNoEffect(misc_reg, val); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid = 0) { return regs.setMiscReg(misc_reg, val, tc); } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 05c409c95..3706d8543 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -234,6 +234,10 @@ class ThreadContext virtual void setMiscReg(int misc_reg, const MiscReg &val) = 0; + virtual uint64_t readRegOtherThread(int misc_reg, unsigned tid) { return 0; } + + virtual void setRegOtherThread(int misc_reg, const MiscReg &val, unsigned tid) { }; + // Also not necessarily the best location for these two. Hopefully will go // away once we decide upon where st cond failures goes. virtual unsigned readStCondFailures() = 0; |