// Copyright (c) 2006-2007 The Regents of The University of Michigan
// 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: Gabe Black
//          Steve Reinhardt

////////////////////////////////////////////////////////////////////
//
// Branch instructions
//

def template JumpExecute {{
        Fault %(class_name)s::execute(ExecContext *xc,
                Trace::InstRecord *traceData) const
        {
            // Attempt to execute the instruction
            Fault fault = NoFault;

            %(op_decl)s;
            %(op_rd)s;

            %(code)s;

            if (fault == NoFault) {
                // Write the resulting state to the execution context
                %(op_wb)s;
            }

            return fault;
        }
}};

def template BranchExecute {{
        Fault
        %(class_name)s::execute(ExecContext *xc,
                Trace::InstRecord *traceData) const
        {
            // Attempt to execute the instruction
            Fault fault = NoFault;

            %(op_decl)s;
            %(op_rd)s;

            if (%(cond)s) {
                %(code)s;
            } else {
                %(fail)s;
            }

            if (fault == NoFault) {
                // Write the resulting state to the execution context
                %(op_wb)s;
            }

            return fault;
        }
}};

def template BranchDecode {{
    if (A)
        return new %(class_name)sAnnul("%(mnemonic)s,a", machInst);
    else
        return new %(class_name)s("%(mnemonic)s", machInst);
}};

// Primary format for branch instructions:
def format Branch(code, *opt_flags) {{
    code = 'NNPC = NNPC;\n' + code
    (usesImm, code, immCode,
     rString, iString) = splitOutImm(code)
    iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
    header_output = BasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    exec_output = JumpExecute.subst(iop)
    if usesImm:
        imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
                immCode, opt_flags)
        header_output += BasicDeclare.subst(imm_iop)
        decoder_output += BasicConstructor.subst(imm_iop)
        exec_output += JumpExecute.subst(imm_iop)
        decode_block = ROrImmDecode.subst(iop)
    else:
        decode_block = BasicDecode.subst(iop)
}};

let {{
    def doBranch(name, Name, base, cond,
            code, annul_code, fail, annul_fail, opt_flags):
        #@todo: add flags and branchTarget() for DirectCntrl branches
        #       the o3 model can take advantage of this annotation if
        #       done correctly

        iop = InstObjParams(name, Name, base,
                {"code": code,
                 "fail": fail,
                 "cond": cond
                },
                opt_flags)
        header_output = BasicDeclareWithMnemonic.subst(iop)
        decoder_output = BasicConstructorWithMnemonic.subst(iop)
        exec_output = BranchExecute.subst(iop)
        if annul_code == "None":
            decode_block = BasicDecodeWithMnemonic.subst(iop)
        else:
            decode_block = BranchDecode.subst(iop)

        if annul_code != "None":
            iop = InstObjParams(name + ',a', Name + 'Annul', base,
                    {"code": annul_code,
                     "fail": annul_fail,
                     "cond": cond
                    },
                    opt_flags)
            header_output += BasicDeclareWithMnemonic.subst(iop)
            decoder_output += BasicConstructorWithMnemonic.subst(iop)
            exec_output += BranchExecute.subst(iop)
        return (header_output, decoder_output, exec_output, decode_block)

    def doCondBranch(name, Name, base, cond, code, opt_flags):
        opt_flags += ('IsCondControl', )
        return doBranch(name, Name, base, cond, code, code,
                'NNPC = NNPC; NPC = NPC;\n',
                'NNPC = NPC + 8; NPC = NPC + 4;\n',
                opt_flags)

    def doUncondBranch(name, Name, base, code, annul_code, opt_flags):
        opt_flags += ('IsUncondControl', )
        return doBranch(name, Name, base, "true", code, annul_code,
                ";", ";", opt_flags)

    default_branch_code = 'NNPC = PC + disp;\n'
}};

// Format for branch instructions with n bit displacements:
def format BranchN(bits, code=default_branch_code,
        test=None, annul_code=None, *opt_flags) {{
    if code == "default_branch_code":
        code = default_branch_code
    if test != "None":
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doCondBranch(name, Name,
             "BranchNBits<%d>" % bits, test, code, opt_flags)
    else:
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doUncondBranch(name, Name,
             "BranchNBits<%d>" % bits, code, annul_code, opt_flags)
}};

// Format for branch instructions with split displacements:
def format BranchSplit(code=default_branch_code,
        test=None, annul_code=None, *opt_flags) {{
    if code == "default_branch_code":
        code = default_branch_code
    if test != "None":
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doCondBranch(name, Name,
             "BranchSplit", test, code, opt_flags)
    else:
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doUncondBranch(name, Name,
             "BranchSplit", code, annul_code, opt_flags)
}};

