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

def template ThreadRegisterExecute {{
        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
        {
            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(0);
            }

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

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