// -*- 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 override;

                bool user_mode;
        };

        class MTUserModeOp : public MTOp
        {
                protected:

                /// Constructor
                MTUserModeOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
                    MTOp(mnem, _machInst, __opClass)
                {
                    user_mode = true;
                }
        };
}};

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(ExecContext *xc,
                          MipsISA::VPEConf0Reg &vpe_conf0,
                          MipsISA::TCBindReg &tc_bind_mt,
                          MipsISA::TCBindReg &tc_bind,
                          MipsISA::VPEControlReg &vpe_control,
                          MipsISA::MVPConf0Reg &mvp_conf0);

   void getMTExValues(ExecContext *xc, MipsISA::Config3Reg &config3);
}};

output exec {{
    void getThrRegExValues(ExecContext *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(RegId(MiscRegClass,
                                                  MISCREG_TC_BIND));
        tc_bind = xc->readMiscReg(MISCREG_TC_BIND);
        vpe_control = xc->readMiscReg(MISCREG_VPE_CONTROL);
        mvp_conf0 = xc->readMiscReg(MISCREG_MVP_CONF0);
    }

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

def template ThreadRegisterExecute {{
        Fault %(class_name)s::execute(
            ExecContext *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 = std::make_shared<CoprocessorUnusableFault>(0);
            }

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

            return fault;
        }
}};

def template MTExecute{{
        Fault %(class_name)s::execute(
            ExecContext *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 = std::make_shared<ReservedInstructionFault>();
                    }
                } else {
                    fault = std::make_shared<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)
}};
