// -*- 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;
            [[maybe_unused]] 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)
}};
