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

////////////////////////////////////////////////////////////////////
//
// 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
    code, immCode, 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 immCode is not None:
        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)
}};

