branch.isa revision 7720:65d338a8dba4
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 Branch::generateDisassembly(Addr pc, 131 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 BranchImm13::generateDisassembly(Addr pc, 145 const SymbolTable *symtab) const 146 { 147 std::stringstream response; 148 149 printMnemonic(response, mnemonic); 150 printRegArray(response, _srcRegIdx, _numSrcRegs); 151 if(_numSrcRegs > 0) 152 response << ", "; 153 ccprintf(response, "0x%x", imm); 154 if (_numDestRegs > 0) 155 response << ", "; 156 printDestReg(response, 0); 157 158 return response.str(); 159 } 160 161 std::string BranchDisp::generateDisassembly(Addr pc, 162 const SymbolTable *symtab) const 163 { 164 std::stringstream response; 165 std::string symbol; 166 Addr symbolAddr; 167 168 Addr target = disp + pc; 169 170 printMnemonic(response, mnemonic); 171 ccprintf(response, "0x%x", target); 172 173 if(symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) 174 { 175 ccprintf(response, " <%s", symbol); 176 if(symbolAddr != target) 177 ccprintf(response, "+%d>", target - symbolAddr); 178 else 179 ccprintf(response, ">"); 180 } 181 182 return response.str(); 183 } 184}}; 185 186def template JumpExecute {{ 187 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 188 Trace::InstRecord *traceData) const 189 { 190 //Attempt to execute the instruction 191 Fault fault = NoFault; 192 193 %(op_decl)s; 194 %(op_rd)s; 195 196 PCS = PCS; 197 %(code)s; 198 199 if(fault == NoFault) 200 { 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 %(class_name)s::execute(%(CPU_exec_context)s *xc, 211 Trace::InstRecord *traceData) const 212 { 213 //Attempt to execute the instruction 214 Fault fault = NoFault; 215 216 %(op_decl)s; 217 %(op_rd)s; 218 219 if (%(cond)s) { 220 %(code)s; 221 } else { 222 %(fail)s; 223 } 224 225 if(fault == NoFault) 226 { 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 (usesImm, code, immCode, 245 rString, iString) = splitOutImm(code) 246 iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 247 header_output = BasicDeclare.subst(iop) 248 decoder_output = BasicConstructor.subst(iop) 249 exec_output = JumpExecute.subst(iop) 250 if usesImm: 251 imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 252 immCode, opt_flags) 253 header_output += BasicDeclare.subst(imm_iop) 254 decoder_output += BasicConstructor.subst(imm_iop) 255 exec_output += JumpExecute.subst(imm_iop) 256 decode_block = ROrImmDecode.subst(iop) 257 else: 258 decode_block = BasicDecode.subst(iop) 259}}; 260 261let {{ 262 def doBranch(name, Name, base, cond, 263 code, annul_code, fail, annul_fail, opt_flags): 264 iop = InstObjParams(name, Name, base, 265 {"code": code, 266 "fail": fail, 267 "cond": cond 268 }, 269 opt_flags) 270 header_output = BasicDeclareWithMnemonic.subst(iop) 271 decoder_output = BasicConstructorWithMnemonic.subst(iop) 272 exec_output = BranchExecute.subst(iop) 273 if annul_code == "None": 274 decode_block = BasicDecodeWithMnemonic.subst(iop) 275 else: 276 decode_block = BranchDecode.subst(iop) 277 278 if annul_code != "None": 279 iop = InstObjParams(name + ',a', Name + 'Annul', base, 280 {"code": annul_code, 281 "fail": annul_fail, 282 "cond": cond 283 }, 284 opt_flags) 285 header_output += BasicDeclareWithMnemonic.subst(iop) 286 decoder_output += BasicConstructorWithMnemonic.subst(iop) 287 exec_output += BranchExecute.subst(iop) 288 return (header_output, decoder_output, exec_output, decode_block) 289 290 def doCondBranch(name, Name, base, cond, code, opt_flags): 291 return doBranch(name, Name, base, cond, code, code, 292 'PCS = PCS;', 293 ''' 294 SparcISA::PCState pc = PCS; 295 pc.nnpc(pc.npc() + 8); 296 pc.npc(pc.npc() + 4); 297 PCS = pc; 298 ''', 299 opt_flags) 300 301 def doUncondBranch(name, Name, base, code, annul_code, opt_flags): 302 return doBranch(name, Name, base, "true", code, annul_code, 303 ";", ";", opt_flags) 304 305 default_branch_code = ''' 306 SparcISA::PCState pc = PCS; 307 pc.nnpc(pc.pc() + disp); 308 PCS = pc; 309 ''' 310}}; 311 312// Format for branch instructions with n bit displacements: 313def format BranchN(bits, code=default_branch_code, 314 test=None, annul_code=None, *opt_flags) {{ 315 if code == "default_branch_code": 316 code = default_branch_code 317 if test != "None": 318 (header_output, 319 decoder_output, 320 exec_output, 321 decode_block) = doCondBranch(name, Name, 322 "BranchNBits<%d>" % bits, test, code, opt_flags) 323 else: 324 (header_output, 325 decoder_output, 326 exec_output, 327 decode_block) = doUncondBranch(name, Name, 328 "BranchNBits<%d>" % bits, code, annul_code, opt_flags) 329}}; 330 331// Format for branch instructions with split displacements: 332def format BranchSplit(code=default_branch_code, 333 test=None, annul_code=None, *opt_flags) {{ 334 if code == "default_branch_code": 335 code = default_branch_code 336 if test != "None": 337 (header_output, 338 decoder_output, 339 exec_output, 340 decode_block) = doCondBranch(name, Name, 341 "BranchSplit", test, code, opt_flags) 342 else: 343 (header_output, 344 decoder_output, 345 exec_output, 346 decode_block) = doUncondBranch(name, Name, 347 "BranchSplit", code, annul_code, opt_flags) 348}}; 349 350