// Copyright (c) 2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder.  You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// 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.

def template BrDeclare {{
    class %(class_name)s : public %(base_class)s
    {
      private:
        %(reg_idx_arr_decl)s;

      public:
        %(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
                uint64_t set_flags, uint16_t _target, uint8_t _cc) :
            %(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
                    %(op_class)s, { _target }, _cc)
        {
            %(set_reg_idx_arr)s;
            %(constructor)s;
        }

        Fault execute(ExecContext *, Trace::InstRecord *) const override;

        std::unique_ptr<PCStateBase>
        branchTarget(const PCStateBase &branch_pc) const override
        {
            PCStateBase *pcs = branch_pc.clone();
            DPRINTF(X86, "Br branchTarget PC info: %s, Target: %d\n",
                    *pcs, (int16_t)target);
            auto &xpc = pcs->as<PCState>();
            xpc.nupc(target);
            xpc.uAdvance();
            return std::unique_ptr<PCStateBase>{pcs};
        }

        /// Explicitly import the otherwise hidden branchTarget
        using StaticInst::branchTarget;
    };
}};

def template EretDeclare {{
    class %(class_name)s : public %(base_class)s
    {
      private:
        %(reg_idx_arr_decl)s;

      public:
        %(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
                uint64_t set_flags, uint8_t _cc) :
            %(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
                    %(op_class)s, {}, _cc)
        {
            %(set_reg_idx_arr)s;
            %(constructor)s;
        }

        Fault execute(ExecContext *, Trace::InstRecord *) const override;
    };
}};

def template SeqOpExecute {{
    Fault
    %(class_name)s::execute(ExecContext *xc,
            Trace::InstRecord *traceData) const
    {
        %(op_decl)s;
        %(op_rd)s;
        if (%(cond_test)s) {
            %(code)s;
        } else {
            %(else_code)s;
        }
        %(op_wb)s;
        return NoFault;
    }
}};

let {{
    class Br(X86Microop):
        def __init__(self, target, flags=None):
            self.className = "Br"
            self.target = target
            if flags:
                if not isinstance(flags, (list, tuple)):
                    raise Exception("flags must be a list or tuple of flags")
                self.cond = " | ".join(flags)
                self.className += "Flags"
            else:
                self.cond = "0"

        def getAllocator(self, microFlags):
            if "IsLastMicroop" in microFlags:
                microFlags.remove("IsLastMicroop")
            if not "IsDelayedCommit" in microFlags:
                microFlags.append("IsDelayedCommit")

            return '''new %(class_name)s(machInst, macrocodeBlock,
                    %(flags)s, %(target)s, %(cc)s)''' % {
                "class_name" : self.className,
                "flags" : self.microFlagsText(microFlags),
                "target" : self.target,
                "cc" : self.cond}
    microopClasses["br"] = Br

    class Eret(X86Microop):
        def __init__(self, flags=None):
            self.className = "Eret"
            if flags:
                if not isinstance(flags, (list, tuple)):
                    raise Exception("flags must be a list or tuple of flags")
                self.cond = " | ".join(flags)
                self.className += "Flags"
            else:
                self.cond = "X86ISA::condition_tests::True"

        def getAllocator(self, microFlags):
            if not "IsLastMicroop" in microFlags:
                microFlags.append("IsLastMicroop")
            if "IsDelayedCommit" in microFlags:
                microFlags.remove("IsDelayedCommit")

            return '''new %(class_name)s(machInst, macrocodeBlock,
                    %(flags)s, %(cc)s)''' % {
                "class_name" : self.className,
                "flags" : self.microFlagsText(microFlags),
                "cc" : self.cond}
    microopClasses["eret"] = Eret

    cond_code = "checkCondition(ccFlagBits | cfofBits | dfBit |" \
                 "ecfBit | ezfBit, cc)"
    for suffix, cond, flags in \
            ("Flags", cond_code, ["IsDirectControl", "IsCondControl"]), \
            ("", "true", []):
        iop = InstObjParams("br", "Br" + suffix,
                "X86ISA::InstOperands<X86ISA::MicroCondBase, X86ISA::UpcOp>",
                {"code": "nuIP = target;", "else_code": "nuIP = nuIP;",
                 "cond_test": cond},
                 flags)
        exec_output += SeqOpExecute.subst(iop)
        header_output += BrDeclare.subst(iop)

        iop = InstObjParams("eret", "Eret" + suffix,
                "X86ISA::InstOperands<X86ISA::MicroCondBase>",
                {"code": "", "else_code": "", "cond_test": cond}, flags)
        exec_output += SeqOpExecute.subst(iop)
        header_output += EretDeclare.subst(iop)
}};
