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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 );
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
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;
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
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;
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:
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:
FaultStat & countStat() {return _count;}
};
-class PalFault : public MipsFault
+class IntegerOverflowFault : public MipsFault
{
- protected:
- bool skipFaultingInstruction() {return true;}
private:
static FaultName _name;
static FaultVect _vect;
FaultStat & countStat() {return _count;}
};
-class IntegerOverflowFault : public MipsFault
+class DspStateDisabledFault : public MipsFault
{
private:
static FaultName _name;
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
+ void invoke(ThreadContext * tc);
};
} // MipsISA namespace
//
// Authors: Korey Sewell
+//@TODO: Make sure the naming convention is consistent here.
////////////////////////////////////////////////////////////////////
//
// Bitfield definitions.
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>;
// CP0 Register Select
def bitfield SEL < 2: 0>;
-// Interrupts
+// INTERRUPTS
def bitfield SC < 5: 5>;
// Branch format
// 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>;
// 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
//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();
}
}
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);
}
}
}
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;
+ }
+ }});
}
}
}
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();
}
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;}});
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();
}
+
}
}
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;
+ }});
}
}
}
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 ); }});
+ }
+ }
}
}
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; }});
}
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 ); }});
+ }
+ }
+ }
+ }
}
}
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 {
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 {
output header {{
#include <iostream>
+ using namespace std;
/**
* Base class for instructions whose disassembly is not purely a
}
}};
-def format Branch(code,*opt_flags) {{
+def format Branch(code, *opt_flags) {{
not_taken_code = ' NNPC = NNPC;\n'
not_taken_code += '} \n'
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', )
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
////////////////////////////////////////////////////////////////////
//
-// 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)
{
}
}};
-//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();
}
}};
-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)
}};
--- /dev/null
+// -*- 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)
+
+}};
+
+
+
//Include the integer formats
##include "int.isa"
+//Include the DSP integer format
+##include "dsp.isa"
+
//Include the floatOp format
##include "fp.isa"
}};
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>
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;
//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
//
output header {{
#include <iostream>
+ using namespace std;
/**
* Base class for integer operations.
*/
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)
{
}
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
{
}};
-// 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
{
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;
}
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;
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)
+}};
const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
const StaticInstPtr &memAccInst() const { return memAccPtr; }
+
+ unsigned memAccFlags() { return memAccessFlags; }
};
/**
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 {{
{
public:
/// Constructor
- EAComp(MachInst machInst);
+ EAComp(ExtMachInst machInst);
%(BasicExecDeclare)s
};
{
public:
/// Constructor
- MemAcc(MachInst machInst);
+ MemAcc(ExtMachInst machInst);
%(BasicExecDeclare)s
};
public:
/// Constructor.
- %(class_name)s(MachInst machInst);
+ %(class_name)s(ExtMachInst machInst);
%(BasicExecDeclare)s
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
+
+ %(MemAccSizeDeclare)s
};
}};
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;
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;
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))
{
%(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);
}
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;
}
}
}};
-
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
{
%(fp_enable_check)s;
%(op_decl)s;
+ %(op_rd)s;
Mem = pkt->get<typeof(Mem)>();
}};
+
+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,
{
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) {
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;
}
}};
-
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;
if (fault == NoFault) {
fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, NULL);
+ memAccessFlags, &write_result);
if (traceData) { traceData->setData(Mem); }
}
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
{
if (fault == NoFault) {
%(op_wb)s;
+
+ if (traceData) { traceData->setData(getStoreData(pkt)); }
}
return fault;
}};
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
{
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
{
}
}};
+
+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) = \
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) = \
/**
* 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)
}};
// 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)
+ completeAccTemplate.subst(iop))
}};
-
output header {{
std::string inst2string(MachInst machInst);
}};
std::string inst2string(MachInst machInst)
{
- std::string str = "";
+ string str = "";
uint32_t mask = 0x80000000;
for(int i=0; i < 32; i++) {
}
}};
-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
-
-
-
-}};
-
-
}};
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;
}};
#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;
}};
'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),
'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),
'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)
}};
UNSERIALIZE_SCALAR(nnpc);
}
+
+
// 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;
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
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;
#define __ARCH_MIPS_LINUX_LINUX_HH__
#include "kern/linux/linux.hh"
+#include <string>
+
+using std::string;
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,
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
#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;
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");
return 1;
}
-
SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 0 */ SyscallDesc("syscall", unimplementedFunc),
/* 1 */ SyscallDesc("exit", exitFunc),
/* 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),
/* 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),
/* 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),
/* 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),
/* 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),
/* 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),
/* 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),
/* 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,
: 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)
return &syscallDescs[m5_sys_idx];
}
+
+
+
+
+
#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
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__
* 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"
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);
}
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;
}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
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();
};
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)
{
}
}
- FloatRegBits readRegBits(int floatReg, int width)
+ FloatRegBits readRegBits(int floatReg, int width, unsigned tid = 0)
{
if (floatReg < NumFloatArchRegs - 1) {
switch(width)
}
}
- 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:
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)
{
}
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
IntReg regs[NumIntRegs];
public:
+ void clear() { bzero(®s, sizeof(regs)); }
+
IntReg readReg(int intReg)
{
return regs[intReg];
Fault setReg(int intReg, const IntReg &val)
{
- regs[intReg] = val;
+ if (intReg != ZeroReg) {
+ regs[intReg] = val;
+ }
+
return NoFault;
}
--- /dev/null
+/*
+ * 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();
+}
#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
#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"
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)
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
Addr nnpc; // next-next-cycle program counter
// used to implement branch delay slot
// not real register
+
public:
Addr readPC()
{
* 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)
panic("Type unsupported. Size mismatch\n");
}
}
+
+void
+MipsISA::startupCPU(ThreadContext *tc, int cpuId)
+{
+ tc->activate(0);
+}
#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 {
template <class TC>
void zeroRegisters(TC *tc);
+ void startupCPU(ThreadContext *tc, int cpuId);
+
void copyRegs(ThreadContext *src, ThreadContext *dest);
// Instruction address compression hooks
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
}
};
return (val >> last) & mask(nbits);
}
+/**
+ * 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
return ((t_bit_val << last) & bmask) | (val & ~bmask);
}
+/**
+ * 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.
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
*/
'Mbox',
'MemDepUnit',
'MemoryAccess',
+ 'MipsPRA',
'O3CPU',
'OzoneCPU',
'OzoneLSQ',
// need to do this...
}
+
Fault copySrcTranslate(Addr src);
Fault copy(Addr dest);
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); }
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);
}
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;