branch.isa revision 8342
13985Sgblack@eecs.umich.edu// Copyright (c) 2006-2007 The Regents of The University of Michigan 22632Sstever@eecs.umich.edu// All rights reserved. 32632Sstever@eecs.umich.edu// 42632Sstever@eecs.umich.edu// Redistribution and use in source and binary forms, with or without 52632Sstever@eecs.umich.edu// modification, are permitted provided that the following conditions are 62632Sstever@eecs.umich.edu// met: redistributions of source code must retain the above copyright 72632Sstever@eecs.umich.edu// notice, this list of conditions and the following disclaimer; 82632Sstever@eecs.umich.edu// redistributions in binary form must reproduce the above copyright 92632Sstever@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the 102632Sstever@eecs.umich.edu// documentation and/or other materials provided with the distribution; 112632Sstever@eecs.umich.edu// neither the name of the copyright holders nor the names of its 122632Sstever@eecs.umich.edu// contributors may be used to endorse or promote products derived from 132632Sstever@eecs.umich.edu// this software without specific prior written permission. 142632Sstever@eecs.umich.edu// 152632Sstever@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 162632Sstever@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 172632Sstever@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 182632Sstever@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 192632Sstever@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 202632Sstever@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 212632Sstever@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 222632Sstever@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 232632Sstever@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242632Sstever@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 252632Sstever@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262632Sstever@eecs.umich.edu// 272632Sstever@eecs.umich.edu// Authors: Gabe Black 282632Sstever@eecs.umich.edu// Steve Reinhardt 292632Sstever@eecs.umich.edu 302022SN/A//////////////////////////////////////////////////////////////////// 312022SN/A// 322022SN/A// Branch instructions 332022SN/A// 342022SN/A 352022SN/Aoutput header {{ 362022SN/A /** 372516SN/A * Base class for branch operations. 382022SN/A */ 392022SN/A class Branch : public SparcStaticInst 402022SN/A { 412224SN/A protected: 422224SN/A // Constructor 434253Sgblack@eecs.umich.edu Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 442224SN/A SparcStaticInst(mnem, _machInst, __opClass) 452224SN/A { 462224SN/A } 472022SN/A 482224SN/A std::string generateDisassembly(Addr pc, 492224SN/A const SymbolTable *symtab) const; 502022SN/A }; 512516SN/A 522516SN/A /** 532516SN/A * Base class for branch operations with an immediate displacement. 542516SN/A */ 552516SN/A class BranchDisp : public Branch 562516SN/A { 572516SN/A protected: 582516SN/A // Constructor 594253Sgblack@eecs.umich.edu BranchDisp(const char *mnem, ExtMachInst _machInst, 602516SN/A OpClass __opClass) : 612516SN/A Branch(mnem, _machInst, __opClass) 622516SN/A { 632516SN/A } 642516SN/A 652516SN/A std::string generateDisassembly(Addr pc, 662516SN/A const SymbolTable *symtab) const; 672516SN/A 682516SN/A int32_t disp; 692516SN/A }; 702516SN/A 712516SN/A /** 722944Sgblack@eecs.umich.edu * Base class for branches with n bit displacements. 732516SN/A */ 742944Sgblack@eecs.umich.edu template<int bits> 752944Sgblack@eecs.umich.edu class BranchNBits : public BranchDisp 762516SN/A { 772516SN/A protected: 782516SN/A // Constructor 794253Sgblack@eecs.umich.edu BranchNBits(const char *mnem, ExtMachInst _machInst, 802516SN/A OpClass __opClass) : 812516SN/A BranchDisp(mnem, _machInst, __opClass) 822516SN/A { 833273Sgblack@eecs.umich.edu disp = sext<bits + 2>((_machInst & mask(bits)) << 2); 842516SN/A } 852516SN/A }; 862516SN/A 872516SN/A /** 882516SN/A * Base class for 16bit split displacements. 892516SN/A */ 902516SN/A class BranchSplit : public BranchDisp 912516SN/A { 922516SN/A protected: 932516SN/A // Constructor 944253Sgblack@eecs.umich.edu BranchSplit(const char *mnem, ExtMachInst _machInst, 952516SN/A OpClass __opClass) : 962516SN/A BranchDisp(mnem, _machInst, __opClass) 972516SN/A { 983273Sgblack@eecs.umich.edu disp = sext<18>((D16HI << 16) | (D16LO << 2)); 992516SN/A } 1002516SN/A }; 1012516SN/A 1022516SN/A /** 1032516SN/A * Base class for branches that use an immediate and a register to 1042516SN/A * compute their displacements. 1052516SN/A */ 1062516SN/A class BranchImm13 : public Branch 1072516SN/A { 1082516SN/A protected: 1092516SN/A // Constructor 1104253Sgblack@eecs.umich.edu BranchImm13(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 1113273Sgblack@eecs.umich.edu Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) 1122516SN/A { 1132516SN/A } 1142516SN/A 1152516SN/A std::string generateDisassembly(Addr pc, 1162516SN/A const SymbolTable *symtab) const; 1172516SN/A 1182516SN/A int32_t imm; 1192516SN/A }; 1202022SN/A}}; 1212022SN/A 1222022SN/Aoutput decoder {{ 1232944Sgblack@eecs.umich.edu 1242944Sgblack@eecs.umich.edu template class BranchNBits<19>; 1252944Sgblack@eecs.umich.edu 1262944Sgblack@eecs.umich.edu template class BranchNBits<22>; 1272944Sgblack@eecs.umich.edu 1282944Sgblack@eecs.umich.edu template class BranchNBits<30>; 1292944Sgblack@eecs.umich.edu 1307741Sgblack@eecs.umich.edu std::string 1317741Sgblack@eecs.umich.edu Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1327741Sgblack@eecs.umich.edu { 1337741Sgblack@eecs.umich.edu std::stringstream response; 1347741Sgblack@eecs.umich.edu 1357741Sgblack@eecs.umich.edu printMnemonic(response, mnemonic); 1367741Sgblack@eecs.umich.edu printRegArray(response, _srcRegIdx, _numSrcRegs); 1377741Sgblack@eecs.umich.edu if (_numDestRegs && _numSrcRegs) 1387741Sgblack@eecs.umich.edu response << ", "; 1397741Sgblack@eecs.umich.edu printDestReg(response, 0); 1407741Sgblack@eecs.umich.edu 1417741Sgblack@eecs.umich.edu return response.str(); 1427741Sgblack@eecs.umich.edu } 1437741Sgblack@eecs.umich.edu 1447741Sgblack@eecs.umich.edu std::string 1457741Sgblack@eecs.umich.edu BranchImm13::generateDisassembly(Addr pc, 1462516SN/A const SymbolTable *symtab) const 1472022SN/A { 1482516SN/A std::stringstream response; 1492516SN/A 1502516SN/A printMnemonic(response, mnemonic); 1512944Sgblack@eecs.umich.edu printRegArray(response, _srcRegIdx, _numSrcRegs); 1527741Sgblack@eecs.umich.edu if (_numSrcRegs > 0) 1532516SN/A response << ", "; 1542516SN/A ccprintf(response, "0x%x", imm); 1552516SN/A if (_numDestRegs > 0) 1562516SN/A response << ", "; 1572944Sgblack@eecs.umich.edu printDestReg(response, 0); 1582516SN/A 1592516SN/A return response.str(); 1602516SN/A } 1612516SN/A 1627741Sgblack@eecs.umich.edu std::string 1637741Sgblack@eecs.umich.edu BranchDisp::generateDisassembly(Addr pc, 1642516SN/A const SymbolTable *symtab) const 1652516SN/A { 1662516SN/A std::stringstream response; 1672516SN/A std::string symbol; 1682516SN/A Addr symbolAddr; 1692516SN/A 1702516SN/A Addr target = disp + pc; 1712516SN/A 1722516SN/A printMnemonic(response, mnemonic); 1732516SN/A ccprintf(response, "0x%x", target); 1742516SN/A 1757741Sgblack@eecs.umich.edu if (symtab && 1767741Sgblack@eecs.umich.edu symtab->findNearestSymbol(target, symbol, symbolAddr)) { 1772516SN/A ccprintf(response, " <%s", symbol); 1787741Sgblack@eecs.umich.edu if (symbolAddr != target) 1792580SN/A ccprintf(response, "+%d>", target - symbolAddr); 1802516SN/A else 1812516SN/A ccprintf(response, ">"); 1822516SN/A } 1832516SN/A 1842516SN/A return response.str(); 1852022SN/A } 1862022SN/A}}; 1872022SN/A 1885091Sgblack@eecs.umich.edudef template JumpExecute {{ 1892224SN/A Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 1902224SN/A Trace::InstRecord *traceData) const 1912022SN/A { 1927741Sgblack@eecs.umich.edu // Attempt to execute the instruction 1932224SN/A Fault fault = NoFault; 1942022SN/A 1952224SN/A %(op_decl)s; 1962224SN/A %(op_rd)s; 1972516SN/A 1982224SN/A %(code)s; 1992022SN/A 2007741Sgblack@eecs.umich.edu if (fault == NoFault) { 2017741Sgblack@eecs.umich.edu // Write the resulting state to the execution context 2022022SN/A %(op_wb)s; 2032224SN/A } 2042022SN/A 2052224SN/A return fault; 2062022SN/A } 2072022SN/A}}; 2082022SN/A 2095091Sgblack@eecs.umich.edudef template BranchExecute {{ 2107741Sgblack@eecs.umich.edu Fault 2117741Sgblack@eecs.umich.edu %(class_name)s::execute(%(CPU_exec_context)s *xc, 2125091Sgblack@eecs.umich.edu Trace::InstRecord *traceData) const 2132580SN/A { 2147741Sgblack@eecs.umich.edu // Attempt to execute the instruction 2155091Sgblack@eecs.umich.edu Fault fault = NoFault; 2165091Sgblack@eecs.umich.edu 2175091Sgblack@eecs.umich.edu %(op_decl)s; 2185091Sgblack@eecs.umich.edu %(op_rd)s; 2195091Sgblack@eecs.umich.edu 2205091Sgblack@eecs.umich.edu if (%(cond)s) { 2215091Sgblack@eecs.umich.edu %(code)s; 2225091Sgblack@eecs.umich.edu } else { 2235091Sgblack@eecs.umich.edu %(fail)s; 2245091Sgblack@eecs.umich.edu } 2255091Sgblack@eecs.umich.edu 2267741Sgblack@eecs.umich.edu if (fault == NoFault) { 2277741Sgblack@eecs.umich.edu // Write the resulting state to the execution context 2285091Sgblack@eecs.umich.edu %(op_wb)s; 2295091Sgblack@eecs.umich.edu } 2305091Sgblack@eecs.umich.edu 2315091Sgblack@eecs.umich.edu return fault; 2322580SN/A } 2335091Sgblack@eecs.umich.edu}}; 2345091Sgblack@eecs.umich.edu 2355091Sgblack@eecs.umich.edudef template BranchDecode {{ 2365091Sgblack@eecs.umich.edu if (A) 2375091Sgblack@eecs.umich.edu return new %(class_name)sAnnul("%(mnemonic)s,a", machInst); 2385091Sgblack@eecs.umich.edu else 2395091Sgblack@eecs.umich.edu return new %(class_name)s("%(mnemonic)s", machInst); 2402580SN/A}}; 2412580SN/A 2422516SN/A// Primary format for branch instructions: 2432022SN/Adef format Branch(code, *opt_flags) {{ 2447790Sgblack@eecs.umich.edu code = 'NNPC = NNPC;\n' + code 2455091Sgblack@eecs.umich.edu (usesImm, code, immCode, 2465091Sgblack@eecs.umich.edu rString, iString) = splitOutImm(code) 2475091Sgblack@eecs.umich.edu iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 2485091Sgblack@eecs.umich.edu header_output = BasicDeclare.subst(iop) 2495091Sgblack@eecs.umich.edu decoder_output = BasicConstructor.subst(iop) 2505091Sgblack@eecs.umich.edu exec_output = JumpExecute.subst(iop) 2515091Sgblack@eecs.umich.edu if usesImm: 2525091Sgblack@eecs.umich.edu imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 2535091Sgblack@eecs.umich.edu immCode, opt_flags) 2545091Sgblack@eecs.umich.edu header_output += BasicDeclare.subst(imm_iop) 2555091Sgblack@eecs.umich.edu decoder_output += BasicConstructor.subst(imm_iop) 2565091Sgblack@eecs.umich.edu exec_output += JumpExecute.subst(imm_iop) 2575091Sgblack@eecs.umich.edu decode_block = ROrImmDecode.subst(iop) 2585091Sgblack@eecs.umich.edu else: 2592516SN/A decode_block = BasicDecode.subst(iop) 2602516SN/A}}; 2612516SN/A 2625091Sgblack@eecs.umich.edulet {{ 2635091Sgblack@eecs.umich.edu def doBranch(name, Name, base, cond, 2645091Sgblack@eecs.umich.edu code, annul_code, fail, annul_fail, opt_flags): 2658342Sksewell@umich.edu if "IsIndirectControl" not in opt_flags: 2668342Sksewell@umich.edu opt_flags += ('IsDirectControl', ) 2678342Sksewell@umich.edu 2685091Sgblack@eecs.umich.edu iop = InstObjParams(name, Name, base, 2695091Sgblack@eecs.umich.edu {"code": code, 2705091Sgblack@eecs.umich.edu "fail": fail, 2715091Sgblack@eecs.umich.edu "cond": cond 2725091Sgblack@eecs.umich.edu }, 2735091Sgblack@eecs.umich.edu opt_flags) 2745091Sgblack@eecs.umich.edu header_output = BasicDeclareWithMnemonic.subst(iop) 2755091Sgblack@eecs.umich.edu decoder_output = BasicConstructorWithMnemonic.subst(iop) 2762516SN/A exec_output = BranchExecute.subst(iop) 2775091Sgblack@eecs.umich.edu if annul_code == "None": 2785091Sgblack@eecs.umich.edu decode_block = BasicDecodeWithMnemonic.subst(iop) 2795091Sgblack@eecs.umich.edu else: 2805091Sgblack@eecs.umich.edu decode_block = BranchDecode.subst(iop) 2815091Sgblack@eecs.umich.edu 2825091Sgblack@eecs.umich.edu if annul_code != "None": 2835091Sgblack@eecs.umich.edu iop = InstObjParams(name + ',a', Name + 'Annul', base, 2845091Sgblack@eecs.umich.edu {"code": annul_code, 2855091Sgblack@eecs.umich.edu "fail": annul_fail, 2865091Sgblack@eecs.umich.edu "cond": cond 2875091Sgblack@eecs.umich.edu }, 2885091Sgblack@eecs.umich.edu opt_flags) 2895091Sgblack@eecs.umich.edu header_output += BasicDeclareWithMnemonic.subst(iop) 2905091Sgblack@eecs.umich.edu decoder_output += BasicConstructorWithMnemonic.subst(iop) 2915091Sgblack@eecs.umich.edu exec_output += BranchExecute.subst(iop) 2925091Sgblack@eecs.umich.edu return (header_output, decoder_output, exec_output, decode_block) 2935091Sgblack@eecs.umich.edu 2945091Sgblack@eecs.umich.edu def doCondBranch(name, Name, base, cond, code, opt_flags): 2958342Sksewell@umich.edu opt_flags += ('IsCondControl', ) 2965091Sgblack@eecs.umich.edu return doBranch(name, Name, base, cond, code, code, 2977790Sgblack@eecs.umich.edu 'NNPC = NNPC; NPC = NPC;\n', 2987790Sgblack@eecs.umich.edu 'NNPC = NPC + 8; NPC = NPC + 4;\n', 2995091Sgblack@eecs.umich.edu opt_flags) 3005091Sgblack@eecs.umich.edu 3015091Sgblack@eecs.umich.edu def doUncondBranch(name, Name, base, code, annul_code, opt_flags): 3028342Sksewell@umich.edu opt_flags += ('IsUncondControl', ) 3035091Sgblack@eecs.umich.edu return doBranch(name, Name, base, "true", code, annul_code, 3045091Sgblack@eecs.umich.edu ";", ";", opt_flags) 3055091Sgblack@eecs.umich.edu 3067790Sgblack@eecs.umich.edu default_branch_code = 'NNPC = PC + disp;\n' 3072516SN/A}}; 3082516SN/A 3095091Sgblack@eecs.umich.edu// Format for branch instructions with n bit displacements: 3105091Sgblack@eecs.umich.edudef format BranchN(bits, code=default_branch_code, 3115091Sgblack@eecs.umich.edu test=None, annul_code=None, *opt_flags) {{ 3125091Sgblack@eecs.umich.edu if code == "default_branch_code": 3135091Sgblack@eecs.umich.edu code = default_branch_code 3145091Sgblack@eecs.umich.edu if test != "None": 3155091Sgblack@eecs.umich.edu (header_output, 3165091Sgblack@eecs.umich.edu decoder_output, 3175091Sgblack@eecs.umich.edu exec_output, 3185091Sgblack@eecs.umich.edu decode_block) = doCondBranch(name, Name, 3195091Sgblack@eecs.umich.edu "BranchNBits<%d>" % bits, test, code, opt_flags) 3205091Sgblack@eecs.umich.edu else: 3215091Sgblack@eecs.umich.edu (header_output, 3225091Sgblack@eecs.umich.edu decoder_output, 3235091Sgblack@eecs.umich.edu exec_output, 3245091Sgblack@eecs.umich.edu decode_block) = doUncondBranch(name, Name, 3255091Sgblack@eecs.umich.edu "BranchNBits<%d>" % bits, code, annul_code, opt_flags) 3265091Sgblack@eecs.umich.edu}}; 3275091Sgblack@eecs.umich.edu 3285091Sgblack@eecs.umich.edu// Format for branch instructions with split displacements: 3295091Sgblack@eecs.umich.edudef format BranchSplit(code=default_branch_code, 3305091Sgblack@eecs.umich.edu test=None, annul_code=None, *opt_flags) {{ 3315091Sgblack@eecs.umich.edu if code == "default_branch_code": 3325091Sgblack@eecs.umich.edu code = default_branch_code 3335091Sgblack@eecs.umich.edu if test != "None": 3345091Sgblack@eecs.umich.edu (header_output, 3355091Sgblack@eecs.umich.edu decoder_output, 3365091Sgblack@eecs.umich.edu exec_output, 3375091Sgblack@eecs.umich.edu decode_block) = doCondBranch(name, Name, 3385091Sgblack@eecs.umich.edu "BranchSplit", test, code, opt_flags) 3395091Sgblack@eecs.umich.edu else: 3405091Sgblack@eecs.umich.edu (header_output, 3415091Sgblack@eecs.umich.edu decoder_output, 3425091Sgblack@eecs.umich.edu exec_output, 3435091Sgblack@eecs.umich.edu decode_block) = doUncondBranch(name, Name, 3445091Sgblack@eecs.umich.edu "BranchSplit", code, annul_code, opt_flags) 3455091Sgblack@eecs.umich.edu}}; 3465091Sgblack@eecs.umich.edu 347