// -*- 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.

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

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

        std::string generateDisassembly(
                Addr pc, const Loader::SymbolTable *symtab) const override;

        bool user_mode = false;
    };

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

output decoder {{
    std::string
    MTOp::generateDisassembly(Addr pc, const Loader::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 = readRegOtherThread(xc, 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;
            M5_VAR_USED int64_t data;
            %(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)
}};
