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

////////////////////////////////////////////////////////////////////
//
// Coprocessor instructions
//

//Outputs to decoder.hh
output header {{
    class CP0Control : public MipsStaticInst
    {
      protected:
        using MipsStaticInst::MipsStaticInst;

        std::string generateDisassembly(
                Addr pc, const loader::SymbolTable *symtab) const override;
    };
    class CP0TLB : public MipsStaticInst
    {
      protected:
        using MipsStaticInst::MipsStaticInst;

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


    class CP1Control : public MipsStaticInst
    {
      protected:
        using MipsStaticInst::MipsStaticInst;

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

// Basic instruction class execute method template.
def template CP0Execute {{
    Fault %(class_name)s::execute(
        ExecContext *xc, trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;
        %(op_decl)s;
        %(op_rd)s;

        if (isCoprocessorEnabled(xc, 0)) {
            %(code)s;

            if(fault == NoFault)
            {
                %(op_wb)s;
            }
        } else {
            fault = std::make_shared<CoprocessorUnusableFault>(0);
        }
        return fault;
    }
}};

def template CP1Execute {{
    Fault %(class_name)s::execute(
        ExecContext *xc, trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;
        %(op_decl)s;
        %(op_rd)s;

        if (isCoprocessorEnabled(xc, 1)) {
            %(code)s;
        } else {
            fault = std::make_shared<CoprocessorUnusableFault>(1);
        }

        if(fault == NoFault)
        {
            %(op_wb)s;
        }
        return fault;
    }
}};
// Basic instruction class execute method template.
def template ControlTLBExecute {{
    Fault %(class_name)s::execute(
        ExecContext *xc, trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;
        %(op_decl)s;
        %(op_rd)s;

        if (FullSystem) {
            if (isCoprocessor0Enabled(xc)) {
                if(isMMUTLB(xc)){
                    %(code)s;
                } else {
                    fault = std::make_shared<ReservedInstructionFault>();
                }
            } else {
                fault = std::make_shared<CoprocessorUnusableFault>(0);
            }
        } else { // Syscall Emulation Mode - No TLB Instructions
            fault = std::make_shared<ReservedInstructionFault>();
        }

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

//Outputs to decoder.cc
output decoder {{
    std::string
    CP0Control::generateDisassembly(
            Addr pc, const loader::SymbolTable *symtab) const
    {
        std::stringstream ss;
        ccprintf(ss, "%-10s r%d, %d, %d", mnemonic, RT, RD, SEL);
        return ss.str();
    }
    std::string
    CP0TLB::generateDisassembly(
            Addr pc, const loader::SymbolTable *symtab) const
    {
        std::stringstream ss;
        ccprintf(ss, "%-10s r%d, %d, %d", mnemonic, RT, RD, SEL);
        return ss.str();
    }
    std::string
    CP1Control::generateDisassembly(
            Addr pc, const loader::SymbolTable *symtab) const
    {
        std::stringstream ss;
        ccprintf(ss, "%-10s r%d, f%d", mnemonic, RT, FS);
        return ss.str();
    }
}};

output header {{
        bool isCoprocessorEnabled(ExecContext *xc, unsigned cop_num);

        bool isMMUTLB(ExecContext *xc);

}};

output exec {{
        bool
        isCoprocessorEnabled(ExecContext *xc, unsigned cop_num)
        {
            if (!FullSystem)
                return true;

            RegVal Stat = xc->readMiscReg(misc_reg::Status);
            if (cop_num == 0) {
                RegVal Dbg = xc->readMiscReg(misc_reg::Debug);
                // In Stat, EXL, ERL or CU0 set, CP0 accessible
                // In Dbg, DM bit set, CP0 accessible
                // In Stat, KSU = 0, kernel mode is base mode
                return (Stat & 0x10000006) ||
                       (Dbg & 0x40000000) ||
                       !(Stat & 0x00000018);
            } else if (cop_num < 4) {
                return Stat & (0x10000000 << cop_num); // CU is reset
            } else {
                panic("Invalid Coprocessor Number Specified");
            }
        }

        bool inline
        isCoprocessor0Enabled(ExecContext *xc)
        {
            if (FullSystem) {
                RegVal Stat = xc->readMiscReg(misc_reg::Status);
                RegVal Dbg = xc->readMiscReg(misc_reg::Debug);
                // In Stat, EXL, ERL or CU0 set, CP0 accessible
                // In Dbg, DM bit set, CP0 accessible
                // In Stat KSU = 0, kernel mode is base mode
                return (Stat & 0x10000006) || (Dbg & 0x40000000) ||
                    !(Stat & 0x00000018);
            } else {
                return true;
            }
        }

        bool
        isMMUTLB(ExecContext *xc)
        {
            RegVal Config = xc->readMiscReg(misc_reg::Config);
            return FullSystem && (Config & 0x380) == 0x80;
        }
}};

def format CP0Control(code, *flags) {{
    flags += ('IsNonSpeculative', )
    iop = InstObjParams(name, Name, 'CP0Control', code, flags)
    header_output = BasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    decode_block = BasicDecode.subst(iop)
    exec_output = CP0Execute.subst(iop)
}};
def format CP0TLB(code, *flags) {{
    flags += ('IsNonSpeculative', )
    iop = InstObjParams(name, Name, 'CP0Control', code, flags)
    header_output = BasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    decode_block = BasicDecode.subst(iop)
    exec_output = ControlTLBExecute.subst(iop)
}};
def format CP1Control(code, *flags) {{
    flags += ('IsNonSpeculative', )
    iop = InstObjParams(name, Name, 'CP1Control', code, flags)
    header_output = BasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    decode_block = BasicDecode.subst(iop)
    exec_output = CP1Execute.subst(iop)
}};
