branch.isa (12234:78ece221f9f5) | branch.isa (12288:f13eec2f5a17) |
---|---|
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 | 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 |
35output header {{ 36 /** 37 * Base class for branch operations. 38 */ 39 class Branch : public SparcStaticInst 40 { 41 protected: 42 // Constructor 43 Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 44 SparcStaticInst(mnem, _machInst, __opClass) 45 { 46 } 47 48 std::string generateDisassembly(Addr pc, 49 const SymbolTable *symtab) const; 50 }; 51 52 /** 53 * Base class for branch operations with an immediate displacement. 54 */ 55 class BranchDisp : public Branch 56 { 57 protected: 58 // Constructor 59 BranchDisp(const char *mnem, ExtMachInst _machInst, 60 OpClass __opClass) : 61 Branch(mnem, _machInst, __opClass) 62 { 63 } 64 65 std::string generateDisassembly(Addr pc, 66 const SymbolTable *symtab) const; 67 68 int32_t disp; 69 }; 70 71 /** 72 * Base class for branches with n bit displacements. 73 */ 74 template<int bits> 75 class BranchNBits : public BranchDisp 76 { 77 protected: 78 // Constructor 79 BranchNBits(const char *mnem, ExtMachInst _machInst, 80 OpClass __opClass) : 81 BranchDisp(mnem, _machInst, __opClass) 82 { 83 disp = sext<bits + 2>((_machInst & mask(bits)) << 2); 84 } 85 }; 86 87 /** 88 * Base class for 16bit split displacements. 89 */ 90 class BranchSplit : public BranchDisp 91 { 92 protected: 93 // Constructor 94 BranchSplit(const char *mnem, ExtMachInst _machInst, 95 OpClass __opClass) : 96 BranchDisp(mnem, _machInst, __opClass) 97 { 98 disp = sext<18>((D16HI << 16) | (D16LO << 2)); 99 } 100 }; 101 102 /** 103 * Base class for branches that use an immediate and a register to 104 * compute their displacements. 105 */ 106 class BranchImm13 : public Branch 107 { 108 protected: 109 // Constructor 110 BranchImm13(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 111 Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) 112 { 113 } 114 115 std::string generateDisassembly(Addr pc, 116 const SymbolTable *symtab) const; 117 118 int32_t imm; 119 }; 120}}; 121 122output decoder {{ 123 124 template class BranchNBits<19>; 125 126 template class BranchNBits<22>; 127 128 template class BranchNBits<30>; 129 130 std::string 131 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 132 { 133 std::stringstream response; 134 135 printMnemonic(response, mnemonic); 136 printRegArray(response, _srcRegIdx, _numSrcRegs); 137 if (_numDestRegs && _numSrcRegs) 138 response << ", "; 139 printDestReg(response, 0); 140 141 return response.str(); 142 } 143 144 std::string 145 BranchImm13::generateDisassembly(Addr pc, 146 const SymbolTable *symtab) const 147 { 148 std::stringstream response; 149 150 printMnemonic(response, mnemonic); 151 printRegArray(response, _srcRegIdx, _numSrcRegs); 152 if (_numSrcRegs > 0) 153 response << ", "; 154 ccprintf(response, "0x%x", imm); 155 if (_numDestRegs > 0) 156 response << ", "; 157 printDestReg(response, 0); 158 159 return response.str(); 160 } 161 162 std::string 163 BranchDisp::generateDisassembly(Addr pc, 164 const SymbolTable *symtab) const 165 { 166 std::stringstream response; 167 std::string symbol; 168 Addr symbolAddr; 169 170 Addr target = disp + pc; 171 172 printMnemonic(response, mnemonic); 173 ccprintf(response, "0x%x", target); 174 175 if (symtab && 176 symtab->findNearestSymbol(target, symbol, symbolAddr)) { 177 ccprintf(response, " <%s", symbol); 178 if (symbolAddr != target) 179 ccprintf(response, "+%d>", target - symbolAddr); 180 else 181 ccprintf(response, ">"); 182 } 183 184 return response.str(); 185 } 186}}; 187 | |
188def template JumpExecute {{ 189 Fault %(class_name)s::execute(ExecContext *xc, 190 Trace::InstRecord *traceData) const 191 { 192 // Attempt to execute the instruction 193 Fault fault = NoFault; 194 195 %(op_decl)s; 196 %(op_rd)s; 197 198 %(code)s; 199 200 if (fault == NoFault) { 201 // Write the resulting state to the execution context 202 %(op_wb)s; 203 } 204 205 return fault; 206 } 207}}; 208 209def template BranchExecute {{ 210 Fault 211 %(class_name)s::execute(ExecContext *xc, 212 Trace::InstRecord *traceData) const 213 { 214 // Attempt to execute the instruction 215 Fault fault = NoFault; 216 217 %(op_decl)s; 218 %(op_rd)s; 219 220 if (%(cond)s) { 221 %(code)s; 222 } else { 223 %(fail)s; 224 } 225 226 if (fault == NoFault) { 227 // Write the resulting state to the execution context 228 %(op_wb)s; 229 } 230 231 return fault; 232 } 233}}; 234 235def template BranchDecode {{ 236 if (A) 237 return new %(class_name)sAnnul("%(mnemonic)s,a", machInst); 238 else 239 return new %(class_name)s("%(mnemonic)s", machInst); 240}}; 241 242// Primary format for branch instructions: 243def format Branch(code, *opt_flags) {{ 244 code = 'NNPC = NNPC;\n' + code 245 (usesImm, code, immCode, 246 rString, iString) = splitOutImm(code) 247 iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 248 header_output = BasicDeclare.subst(iop) 249 decoder_output = BasicConstructor.subst(iop) 250 exec_output = JumpExecute.subst(iop) 251 if usesImm: 252 imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 253 immCode, opt_flags) 254 header_output += BasicDeclare.subst(imm_iop) 255 decoder_output += BasicConstructor.subst(imm_iop) 256 exec_output += JumpExecute.subst(imm_iop) 257 decode_block = ROrImmDecode.subst(iop) 258 else: 259 decode_block = BasicDecode.subst(iop) 260}}; 261 262let {{ 263 def doBranch(name, Name, base, cond, 264 code, annul_code, fail, annul_fail, opt_flags): 265 #@todo: add flags and branchTarget() for DirectCntrl branches 266 # the o3 model can take advantage of this annotation if 267 # done correctly 268 269 iop = InstObjParams(name, Name, base, 270 {"code": code, 271 "fail": fail, 272 "cond": cond 273 }, 274 opt_flags) 275 header_output = BasicDeclareWithMnemonic.subst(iop) 276 decoder_output = BasicConstructorWithMnemonic.subst(iop) 277 exec_output = BranchExecute.subst(iop) 278 if annul_code == "None": 279 decode_block = BasicDecodeWithMnemonic.subst(iop) 280 else: 281 decode_block = BranchDecode.subst(iop) 282 283 if annul_code != "None": 284 iop = InstObjParams(name + ',a', Name + 'Annul', base, 285 {"code": annul_code, 286 "fail": annul_fail, 287 "cond": cond 288 }, 289 opt_flags) 290 header_output += BasicDeclareWithMnemonic.subst(iop) 291 decoder_output += BasicConstructorWithMnemonic.subst(iop) 292 exec_output += BranchExecute.subst(iop) 293 return (header_output, decoder_output, exec_output, decode_block) 294 295 def doCondBranch(name, Name, base, cond, code, opt_flags): 296 opt_flags += ('IsCondControl', ) 297 return doBranch(name, Name, base, cond, code, code, 298 'NNPC = NNPC; NPC = NPC;\n', 299 'NNPC = NPC + 8; NPC = NPC + 4;\n', 300 opt_flags) 301 302 def doUncondBranch(name, Name, base, code, annul_code, opt_flags): 303 opt_flags += ('IsUncondControl', ) 304 return doBranch(name, Name, base, "true", code, annul_code, 305 ";", ";", opt_flags) 306 307 default_branch_code = 'NNPC = PC + disp;\n' 308}}; 309 310// Format for branch instructions with n bit displacements: 311def format BranchN(bits, code=default_branch_code, 312 test=None, annul_code=None, *opt_flags) {{ 313 if code == "default_branch_code": 314 code = default_branch_code 315 if test != "None": 316 (header_output, 317 decoder_output, 318 exec_output, 319 decode_block) = doCondBranch(name, Name, 320 "BranchNBits<%d>" % bits, test, code, opt_flags) 321 else: 322 (header_output, 323 decoder_output, 324 exec_output, 325 decode_block) = doUncondBranch(name, Name, 326 "BranchNBits<%d>" % bits, code, annul_code, opt_flags) 327}}; 328 329// Format for branch instructions with split displacements: 330def format BranchSplit(code=default_branch_code, 331 test=None, annul_code=None, *opt_flags) {{ 332 if code == "default_branch_code": 333 code = default_branch_code 334 if test != "None": 335 (header_output, 336 decoder_output, 337 exec_output, 338 decode_block) = doCondBranch(name, Name, 339 "BranchSplit", test, code, opt_flags) 340 else: 341 (header_output, 342 decoder_output, 343 exec_output, 344 decode_block) = doUncondBranch(name, Name, 345 "BranchSplit", code, annul_code, opt_flags) 346}}; 347 | 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 |