// -*- mode:c++ -*-

// Copyright (c) 2007 MIPS Technologies, Inc.
// 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

////////////////////////////////////////////////////////////////////
//
// MT instructions
//

output header {{
        /**
         * Base class for MIPS MT ASE operations.
         */
        class MTOp : public MipsStaticInst
        {
                protected:

                /// Constructor
                MTOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
                    MipsStaticInst(mnem, _machInst, __opClass), user_mode(false)
                {
                }

               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 {{
    std::string MTOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
    {
        std::stringstream ss;

        if (strcmp(mnemonic,"mttc0") == 0 || strcmp(mnemonic,"mftc0") == 0) {
            ccprintf(ss, "%-10s r%d, r%d, %d", mnemonic, RT, RD, SEL);
        } else if (strcmp(mnemonic,"mftgpr") == 0) {
            ccprintf(ss, "%-10s r%d, r%d", mnemonic, RD, RT);
        } else {
            ccprintf(ss, "%-10s r%d, r%d", mnemonic, RT, RD);
        }

        return ss.str();
    }
}};

output header {{
   void getThrRegExValues(%(CPU_exec_context)s *xc,
                          MipsISA::VPEConf0Reg &vpe_conf0,
                          MipsISA::TCBindReg &tc_bind_mt,
                          MipsISA::TCBindReg &tc_bind,
                          MipsISA::VPEControlReg &vpe_control,
                          MipsISA::MVPConf0Reg &mvp_conf0);

   void getMTExValues(%(CPU_exec_context)s *xc, MipsISA::Config3Reg &config3);
}};

output exec {{
    void getThrRegExValues(CPU_EXEC_CONTEXT *xc,
            VPEConf0Reg &vpe_conf0, TCBindReg &tc_bind_mt,
            TCBindReg &tc_bind, VPEControlReg &vpe_control,
            MVPConf0Reg &mvp_conf0)
    {
        vpe_conf0 = xc->readMiscReg(MISCREG_VPE_CONF0);
        tc_bind_mt = xc->readRegOtherThread(MISCREG_TC_BIND + Misc_Reg_Base);
        tc_bind = xc->readMiscReg(MISCREG_TC_BIND);
        vpe_control = xc->readMiscReg(MISCREG_VPE_CONTROL);
        mvp_conf0 = xc->readMiscReg(MISCREG_MVP_CONF0);
    }

    void getMTExValues(CPU_EXEC_CONTEXT *xc, Config3Reg &config3)
    {
        config3 = xc->readMiscReg(MISCREG_CONFIG3);
    }
}};

def template ThreadRegisterExecute {{
        Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
        {
            Fault fault = NoFault;
            int64_t data M5_VAR_USED;
            %(op_decl)s;
            %(op_rd)s;

            VPEConf0Reg vpeConf0;
            TCBindReg tcBindMT;
            TCBindReg tcBind;
            VPEControlReg vpeControl;
            MVPConf0Reg mvpConf0;

            getThrRegExValues(xc, vpeConf0, tcBindMT,
                                  tcBind, vpeControl, mvpConf0);

            if (isCoprocessorEnabled(xc, 0)) {
                if (vpeConf0.mvp == 0 && tcBindMT.curVPE != tcBind.curVPE) {
                    data = -1;
                } else if (vpeControl.targTC > mvpConf0.ptc) {
                    data = -1;
                } else {
                    %(code)s;
                }
            } else {
                fault = new CoprocessorUnusableFault(0);
            }

            if(fault == NoFault)
            {
                %(op_wb)s;
            }

            return fault;
        }
}};

def template MTExecute{{
        Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
        {
                Fault fault = NoFault;
                %(op_decl)s;
                %(op_rd)s;

                Config3Reg config3;

                getMTExValues(xc, config3);

                if (isCoprocessorEnabled(xc, 0)) {
                    if (config3.mt == 1) {
                        %(code)s;
                    } else {
                        fault = new ReservedInstructionFault();
                    }
                } else {
                    fault = new CoprocessorUnusableFault(0);
                }

                if(fault == NoFault)
                {
                    %(op_wb)s;
                }
                return fault;
        }
}};

// Primary format for integer operate instructions:
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()->threadId() << \": Executing MT INST: ' + name + '\" << endl;\n' + code

        code += '''
            if (MT_H)
                data = bits(data, 63, 32);
            Rd = data;
        '''

        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()->threadId() << \": 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 = ThreadRegisterExecute.subst(iop)
}};
