branch.isa revision 7741
15389Sgblack@eecs.umich.edu// Copyright (c) 2006-2007 The Regents of The University of Michigan 25446Sgblack@eecs.umich.edu// All rights reserved. 35389Sgblack@eecs.umich.edu// 45389Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without 55389Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are 65389Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright 75389Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer; 85389Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright 95389Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the 105389Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution; 115389Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its 125389Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from 135389Sgblack@eecs.umich.edu// this software without specific prior written permission. 145389Sgblack@eecs.umich.edu// 155389Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 165389Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 175389Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 185389Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 195389Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205389Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 215389Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 225389Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 235389Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245389Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 255389Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265389Sgblack@eecs.umich.edu// 275389Sgblack@eecs.umich.edu// Authors: Gabe Black 285389Sgblack@eecs.umich.edu// Steve Reinhardt 295389Sgblack@eecs.umich.edu 305389Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////// 315389Sgblack@eecs.umich.edu// 325389Sgblack@eecs.umich.edu// Branch instructions 335389Sgblack@eecs.umich.edu// 345389Sgblack@eecs.umich.edu 355389Sgblack@eecs.umich.eduoutput header {{ 365389Sgblack@eecs.umich.edu /** 375389Sgblack@eecs.umich.edu * Base class for branch operations. 385389Sgblack@eecs.umich.edu */ 395389Sgblack@eecs.umich.edu class Branch : public SparcStaticInst 405389Sgblack@eecs.umich.edu { 415478Snate@binkert.org protected: 425643Sgblack@eecs.umich.edu // Constructor 435636Sgblack@eecs.umich.edu Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 445389Sgblack@eecs.umich.edu SparcStaticInst(mnem, _machInst, __opClass) 455637Sgblack@eecs.umich.edu { 465389Sgblack@eecs.umich.edu } 475389Sgblack@eecs.umich.edu 485389Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, 495389Sgblack@eecs.umich.edu const SymbolTable *symtab) const; 505389Sgblack@eecs.umich.edu }; 515638Sgblack@eecs.umich.edu 525389Sgblack@eecs.umich.edu /** 535389Sgblack@eecs.umich.edu * Base class for branch operations with an immediate displacement. 545446Sgblack@eecs.umich.edu */ 555389Sgblack@eecs.umich.edu class BranchDisp : public Branch 565389Sgblack@eecs.umich.edu { 575389Sgblack@eecs.umich.edu protected: 585389Sgblack@eecs.umich.edu // Constructor 595446Sgblack@eecs.umich.edu BranchDisp(const char *mnem, ExtMachInst _machInst, 605638Sgblack@eecs.umich.edu OpClass __opClass) : 615446Sgblack@eecs.umich.edu Branch(mnem, _machInst, __opClass) 625446Sgblack@eecs.umich.edu { 635643Sgblack@eecs.umich.edu } 645643Sgblack@eecs.umich.edu 655643Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, 665643Sgblack@eecs.umich.edu const SymbolTable *symtab) const; 675636Sgblack@eecs.umich.edu 685446Sgblack@eecs.umich.edu int32_t disp; 695446Sgblack@eecs.umich.edu }; 705446Sgblack@eecs.umich.edu 715446Sgblack@eecs.umich.edu /** 725446Sgblack@eecs.umich.edu * Base class for branches with n bit displacements. 735635Sgblack@eecs.umich.edu */ 745635Sgblack@eecs.umich.edu template<int bits> 755643Sgblack@eecs.umich.edu class BranchNBits : public BranchDisp 765643Sgblack@eecs.umich.edu { 775643Sgblack@eecs.umich.edu protected: 785643Sgblack@eecs.umich.edu // Constructor 795643Sgblack@eecs.umich.edu BranchNBits(const char *mnem, ExtMachInst _machInst, 805643Sgblack@eecs.umich.edu OpClass __opClass) : 815643Sgblack@eecs.umich.edu BranchDisp(mnem, _machInst, __opClass) 825643Sgblack@eecs.umich.edu { 835643Sgblack@eecs.umich.edu disp = sext<bits + 2>((_machInst & mask(bits)) << 2); 845643Sgblack@eecs.umich.edu } 855446Sgblack@eecs.umich.edu }; 865446Sgblack@eecs.umich.edu 875389Sgblack@eecs.umich.edu /** 885638Sgblack@eecs.umich.edu * Base class for 16bit split displacements. 895389Sgblack@eecs.umich.edu */ 905389Sgblack@eecs.umich.edu class BranchSplit : public BranchDisp 915389Sgblack@eecs.umich.edu { 925389Sgblack@eecs.umich.edu protected: 935389Sgblack@eecs.umich.edu // Constructor 945389Sgblack@eecs.umich.edu BranchSplit(const char *mnem, ExtMachInst _machInst, 955638Sgblack@eecs.umich.edu OpClass __opClass) : 965389Sgblack@eecs.umich.edu BranchDisp(mnem, _machInst, __opClass) 975389Sgblack@eecs.umich.edu { 985389Sgblack@eecs.umich.edu disp = sext<18>((D16HI << 16) | (D16LO << 2)); 995389Sgblack@eecs.umich.edu } 1005389Sgblack@eecs.umich.edu }; 1015389Sgblack@eecs.umich.edu 1025638Sgblack@eecs.umich.edu /** 1035389Sgblack@eecs.umich.edu * Base class for branches that use an immediate and a register to 1045389Sgblack@eecs.umich.edu * compute their displacements. 1055389Sgblack@eecs.umich.edu */ 1065389Sgblack@eecs.umich.edu class BranchImm13 : public Branch 1075389Sgblack@eecs.umich.edu { 1085389Sgblack@eecs.umich.edu protected: 1095638Sgblack@eecs.umich.edu // Constructor 1105389Sgblack@eecs.umich.edu BranchImm13(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 1115389Sgblack@eecs.umich.edu Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) 1125389Sgblack@eecs.umich.edu { 1135389Sgblack@eecs.umich.edu } 1145389Sgblack@eecs.umich.edu 1155638Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, 1165389Sgblack@eecs.umich.edu const SymbolTable *symtab) const; 1175389Sgblack@eecs.umich.edu 1185389Sgblack@eecs.umich.edu int32_t imm; 1195389Sgblack@eecs.umich.edu }; 1205389Sgblack@eecs.umich.edu}}; 1215638Sgblack@eecs.umich.edu 1225389Sgblack@eecs.umich.eduoutput decoder {{ 1235389Sgblack@eecs.umich.edu 1245389Sgblack@eecs.umich.edu template class BranchNBits<19>; 1255389Sgblack@eecs.umich.edu 1265389Sgblack@eecs.umich.edu template class BranchNBits<22>; 1275389Sgblack@eecs.umich.edu 1285389Sgblack@eecs.umich.edu template class BranchNBits<30>; 1295638Sgblack@eecs.umich.edu 1305389Sgblack@eecs.umich.edu std::string 1315389Sgblack@eecs.umich.edu Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1325389Sgblack@eecs.umich.edu { 1335389Sgblack@eecs.umich.edu std::stringstream response; 1345389Sgblack@eecs.umich.edu 1355389Sgblack@eecs.umich.edu printMnemonic(response, mnemonic); 1365389Sgblack@eecs.umich.edu printRegArray(response, _srcRegIdx, _numSrcRegs); 1375638Sgblack@eecs.umich.edu if (_numDestRegs && _numSrcRegs) 1385638Sgblack@eecs.umich.edu response << ", "; 1395389Sgblack@eecs.umich.edu printDestReg(response, 0); 1405638Sgblack@eecs.umich.edu 1415389Sgblack@eecs.umich.edu 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(%(CPU_exec_context)s *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 PCS = PCS; 199 %(code)s; 200 201 if (fault == NoFault) { 202 // Write the resulting state to the execution context 203 %(op_wb)s; 204 } 205 206 return fault; 207 } 208}}; 209 210def template BranchExecute {{ 211 Fault 212 %(class_name)s::execute(%(CPU_exec_context)s *xc, 213 Trace::InstRecord *traceData) const 214 { 215 // Attempt to execute the instruction 216 Fault fault = NoFault; 217 218 %(op_decl)s; 219 %(op_rd)s; 220 221 if (%(cond)s) { 222 %(code)s; 223 } else { 224 %(fail)s; 225 } 226 227 if (fault == NoFault) { 228 // Write the resulting state to the execution context 229 %(op_wb)s; 230 } 231 232 return fault; 233 } 234}}; 235 236def template BranchDecode {{ 237 if (A) 238 return new %(class_name)sAnnul("%(mnemonic)s,a", machInst); 239 else 240 return new %(class_name)s("%(mnemonic)s", machInst); 241}}; 242 243// Primary format for branch instructions: 244def format Branch(code, *opt_flags) {{ 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 iop = InstObjParams(name, Name, base, 266 {"code": code, 267 "fail": fail, 268 "cond": cond 269 }, 270 opt_flags) 271 header_output = BasicDeclareWithMnemonic.subst(iop) 272 decoder_output = BasicConstructorWithMnemonic.subst(iop) 273 exec_output = BranchExecute.subst(iop) 274 if annul_code == "None": 275 decode_block = BasicDecodeWithMnemonic.subst(iop) 276 else: 277 decode_block = BranchDecode.subst(iop) 278 279 if annul_code != "None": 280 iop = InstObjParams(name + ',a', Name + 'Annul', base, 281 {"code": annul_code, 282 "fail": annul_fail, 283 "cond": cond 284 }, 285 opt_flags) 286 header_output += BasicDeclareWithMnemonic.subst(iop) 287 decoder_output += BasicConstructorWithMnemonic.subst(iop) 288 exec_output += BranchExecute.subst(iop) 289 return (header_output, decoder_output, exec_output, decode_block) 290 291 def doCondBranch(name, Name, base, cond, code, opt_flags): 292 return doBranch(name, Name, base, cond, code, code, 293 'PCS = PCS;', 294 ''' 295 SparcISA::PCState pc = PCS; 296 pc.nnpc(pc.npc() + 8); 297 pc.npc(pc.npc() + 4); 298 PCS = pc; 299 ''', 300 opt_flags) 301 302 def doUncondBranch(name, Name, base, code, annul_code, opt_flags): 303 return doBranch(name, Name, base, "true", code, annul_code, 304 ";", ";", opt_flags) 305 306 default_branch_code = ''' 307 SparcISA::PCState pc = PCS; 308 pc.nnpc(pc.pc() + disp); 309 PCS = pc; 310 ''' 311}}; 312 313// Format for branch instructions with n bit displacements: 314def format BranchN(bits, code=default_branch_code, 315 test=None, annul_code=None, *opt_flags) {{ 316 if code == "default_branch_code": 317 code = default_branch_code 318 if test != "None": 319 (header_output, 320 decoder_output, 321 exec_output, 322 decode_block) = doCondBranch(name, Name, 323 "BranchNBits<%d>" % bits, test, code, opt_flags) 324 else: 325 (header_output, 326 decoder_output, 327 exec_output, 328 decode_block) = doUncondBranch(name, Name, 329 "BranchNBits<%d>" % bits, code, annul_code, opt_flags) 330}}; 331 332// Format for branch instructions with split displacements: 333def format BranchSplit(code=default_branch_code, 334 test=None, annul_code=None, *opt_flags) {{ 335 if code == "default_branch_code": 336 code = default_branch_code 337 if test != "None": 338 (header_output, 339 decoder_output, 340 exec_output, 341 decode_block) = doCondBranch(name, Name, 342 "BranchSplit", test, code, opt_flags) 343 else: 344 (header_output, 345 decoder_output, 346 exec_output, 347 decode_block) = doUncondBranch(name, Name, 348 "BranchSplit", code, annul_code, opt_flags) 349}}; 350 351