1// Copyright (c) 2006-2007 The Regents of The University of Michigan 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer; 8// redistributions in binary form must reproduce the above copyright 9// notice, this list of conditions and the following disclaimer in the 10// documentation and/or other materials provided with the distribution; 11// neither the name of the copyright holders nor the names of its 12// contributors may be used to endorse or promote products derived from 13// this software without specific prior written permission. 14// 15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26// 27// Authors: Gabe Black 28// Steve Reinhardt 29 30//////////////////////////////////////////////////////////////////// 31// 32// Branch instructions 33// 34 35def template JumpExecute {{ 36 Fault %(class_name)s::execute(ExecContext *xc, 37 Trace::InstRecord *traceData) const 38 { 39 // Attempt to execute the instruction 40 Fault fault = NoFault; 41 42 %(op_decl)s; 43 %(op_rd)s; 44 45 %(code)s; 46 47 if (fault == NoFault) { 48 // Write the resulting state to the execution context 49 %(op_wb)s; 50 } 51 52 return fault; 53 } 54}}; 55 56def template BranchExecute {{ 57 Fault 58 %(class_name)s::execute(ExecContext *xc, 59 Trace::InstRecord *traceData) const 60 { 61 // Attempt to execute the instruction 62 Fault fault = NoFault; 63 64 %(op_decl)s; 65 %(op_rd)s; 66 67 if (%(cond)s) { 68 %(code)s; 69 } else { 70 %(fail)s; 71 } 72 73 if (fault == NoFault) { 74 // Write the resulting state to the execution context 75 %(op_wb)s; 76 } 77 78 return fault; 79 } 80}}; 81 82def template BranchDecode {{ 83 if (A) 84 return new %(class_name)sAnnul("%(mnemonic)s,a", machInst); 85 else 86 return new %(class_name)s("%(mnemonic)s", machInst); 87}}; 88 89// Primary format for branch instructions: 90def format Branch(code, *opt_flags) {{ 91 code = 'NNPC = NNPC;\n' + code 92 (usesImm, code, immCode, 93 rString, iString) = splitOutImm(code) 94 iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 95 header_output = BasicDeclare.subst(iop) 96 decoder_output = BasicConstructor.subst(iop) 97 exec_output = JumpExecute.subst(iop) 98 if usesImm: 99 imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 100 immCode, opt_flags) 101 header_output += BasicDeclare.subst(imm_iop) 102 decoder_output += BasicConstructor.subst(imm_iop) 103 exec_output += JumpExecute.subst(imm_iop) 104 decode_block = ROrImmDecode.subst(iop) 105 else: 106 decode_block = BasicDecode.subst(iop) 107}}; 108 109let {{ 110 def doBranch(name, Name, base, cond, 111 code, annul_code, fail, annul_fail, opt_flags): 112 #@todo: add flags and branchTarget() for DirectCntrl branches 113 # the o3 model can take advantage of this annotation if 114 # done correctly 115 116 iop = InstObjParams(name, Name, base, 117 {"code": code, 118 "fail": fail, 119 "cond": cond 120 }, 121 opt_flags) 122 header_output = BasicDeclareWithMnemonic.subst(iop) 123 decoder_output = BasicConstructorWithMnemonic.subst(iop) 124 exec_output = BranchExecute.subst(iop) 125 if annul_code == "None": 126 decode_block = BasicDecodeWithMnemonic.subst(iop) 127 else: 128 decode_block = BranchDecode.subst(iop) 129 130 if annul_code != "None": 131 iop = InstObjParams(name + ',a', Name + 'Annul', base, 132 {"code": annul_code, 133 "fail": annul_fail, 134 "cond": cond 135 }, 136 opt_flags) 137 header_output += BasicDeclareWithMnemonic.subst(iop) 138 decoder_output += BasicConstructorWithMnemonic.subst(iop) 139 exec_output += BranchExecute.subst(iop) 140 return (header_output, decoder_output, exec_output, decode_block) 141 142 def doCondBranch(name, Name, base, cond, code, opt_flags): 143 opt_flags += ('IsCondControl', ) 144 return doBranch(name, Name, base, cond, code, code, 145 'NNPC = NNPC; NPC = NPC;\n', 146 'NNPC = NPC + 8; NPC = NPC + 4;\n', 147 opt_flags) 148 149 def doUncondBranch(name, Name, base, code, annul_code, opt_flags): 150 opt_flags += ('IsUncondControl', ) 151 return doBranch(name, Name, base, "true", code, annul_code, 152 ";", ";", opt_flags) 153 154 default_branch_code = 'NNPC = PC + disp;\n' 155}}; 156 157// Format for branch instructions with n bit displacements: 158def format BranchN(bits, code=default_branch_code, 159 test=None, annul_code=None, *opt_flags) {{ 160 if code == "default_branch_code": 161 code = default_branch_code 162 if test != "None": 163 (header_output, 164 decoder_output, 165 exec_output, 166 decode_block) = doCondBranch(name, Name, 167 "BranchNBits<%d>" % bits, test, code, opt_flags) 168 else: 169 (header_output, 170 decoder_output, 171 exec_output, 172 decode_block) = doUncondBranch(name, Name, 173 "BranchNBits<%d>" % bits, code, annul_code, opt_flags) 174}}; 175 176// Format for branch instructions with split displacements: 177def format BranchSplit(code=default_branch_code, 178 test=None, annul_code=None, *opt_flags) {{ 179 if code == "default_branch_code": 180 code = default_branch_code 181 if test != "None": 182 (header_output, 183 decoder_output, 184 exec_output, 185 decode_block) = doCondBranch(name, Name, 186 "BranchSplit", test, code, opt_flags) 187 else: 188 (header_output, 189 decoder_output, 190 exec_output, 191 decode_block) = doUncondBranch(name, Name, 192 "BranchSplit", code, annul_code, opt_flags) 193}}; 194 195