branch.isa revision 7741
12391SN/A// Copyright (c) 2006-2007 The Regents of The University of Michigan 28931Sandreas.hansson@arm.com// All rights reserved. 37733SN/A// 47733SN/A// Redistribution and use in source and binary forms, with or without 57733SN/A// modification, are permitted provided that the following conditions are 67733SN/A// met: redistributions of source code must retain the above copyright 77733SN/A// notice, this list of conditions and the following disclaimer; 87733SN/A// redistributions in binary form must reproduce the above copyright 97733SN/A// notice, this list of conditions and the following disclaimer in the 107733SN/A// documentation and/or other materials provided with the distribution; 117733SN/A// neither the name of the copyright holders nor the names of its 127733SN/A// contributors may be used to endorse or promote products derived from 137733SN/A// this software without specific prior written permission. 142391SN/A// 152391SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 162391SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 172391SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 182391SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 192391SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 202391SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 212391SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 222391SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 232391SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242391SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 252391SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262391SN/A// 272391SN/A// Authors: Gabe Black 282391SN/A// Steve Reinhardt 292391SN/A 302391SN/A//////////////////////////////////////////////////////////////////// 312391SN/A// 322391SN/A// Branch instructions 332391SN/A// 342391SN/A 352391SN/Aoutput header {{ 362391SN/A /** 372391SN/A * Base class for branch operations. 382391SN/A */ 392665SN/A class Branch : public SparcStaticInst 402665SN/A { 412914SN/A protected: 428931Sandreas.hansson@arm.com // Constructor 432391SN/A Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 442391SN/A SparcStaticInst(mnem, _machInst, __opClass) 4510466Sandreas.hansson@arm.com { 4610466Sandreas.hansson@arm.com } 4710102Sali.saidi@arm.com 4810102Sali.saidi@arm.com std::string generateDisassembly(Addr pc, 498232SN/A const SymbolTable *symtab) const; 508232SN/A }; 518931Sandreas.hansson@arm.com 523879SN/A /** 539053Sdam.sunwoo@arm.com * Base class for branch operations with an immediate displacement. 542394SN/A */ 552391SN/A class BranchDisp : public Branch 562391SN/A { 578931Sandreas.hansson@arm.com protected: 588931Sandreas.hansson@arm.com // Constructor 599053Sdam.sunwoo@arm.com BranchDisp(const char *mnem, ExtMachInst _machInst, 609053Sdam.sunwoo@arm.com OpClass __opClass) : 612391SN/A Branch(mnem, _machInst, __opClass) 6210466Sandreas.hansson@arm.com { 6310466Sandreas.hansson@arm.com } 6410466Sandreas.hansson@arm.com 6510466Sandreas.hansson@arm.com std::string generateDisassembly(Addr pc, 6610466Sandreas.hansson@arm.com const SymbolTable *symtab) const; 6710466Sandreas.hansson@arm.com 6810466Sandreas.hansson@arm.com int32_t disp; 6910466Sandreas.hansson@arm.com }; 702391SN/A 712391SN/A /** 722391SN/A * Base class for branches with n bit displacements. 739293Sandreas.hansson@arm.com */ 749293Sandreas.hansson@arm.com template<int bits> 752391SN/A class BranchNBits : public BranchDisp 769293Sandreas.hansson@arm.com { 772391SN/A protected: 782391SN/A // Constructor 798719SN/A BranchNBits(const char *mnem, ExtMachInst _machInst, 808931Sandreas.hansson@arm.com OpClass __opClass) : 818719SN/A BranchDisp(mnem, _machInst, __opClass) 828719SN/A { 838719SN/A disp = sext<bits + 2>((_machInst & mask(bits)) << 2); 849053Sdam.sunwoo@arm.com } 859053Sdam.sunwoo@arm.com }; 868719SN/A 879053Sdam.sunwoo@arm.com /** 888719SN/A * Base class for 16bit split displacements. 898719SN/A */ 909053Sdam.sunwoo@arm.com class BranchSplit : public BranchDisp 918719SN/A { 929053Sdam.sunwoo@arm.com protected: 939053Sdam.sunwoo@arm.com // Constructor 949053Sdam.sunwoo@arm.com BranchSplit(const char *mnem, ExtMachInst _machInst, 958719SN/A OpClass __opClass) : 969053Sdam.sunwoo@arm.com BranchDisp(mnem, _machInst, __opClass) 978719SN/A { 988719SN/A disp = sext<18>((D16HI << 16) | (D16LO << 2)); 999053Sdam.sunwoo@arm.com } 1008719SN/A }; 1019053Sdam.sunwoo@arm.com 1029053Sdam.sunwoo@arm.com /** 1039053Sdam.sunwoo@arm.com * Base class for branches that use an immediate and a register to 1048719SN/A * compute their displacements. 1059053Sdam.sunwoo@arm.com */ 1068719SN/A class BranchImm13 : public Branch 1078719SN/A { 1089053Sdam.sunwoo@arm.com protected: 1098719SN/A // Constructor 1109053Sdam.sunwoo@arm.com BranchImm13(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 1119053Sdam.sunwoo@arm.com Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) 1129053Sdam.sunwoo@arm.com { 1138719SN/A } 1149053Sdam.sunwoo@arm.com 1158719SN/A std::string generateDisassembly(Addr pc, 1168719SN/A const SymbolTable *symtab) const; 1179053Sdam.sunwoo@arm.com 1188719SN/A int32_t imm; 1199053Sdam.sunwoo@arm.com }; 1209053Sdam.sunwoo@arm.com}}; 1219053Sdam.sunwoo@arm.com 1228719SN/Aoutput decoder {{ 1239053Sdam.sunwoo@arm.com 1248719SN/A template class BranchNBits<19>; 1258719SN/A 1269053Sdam.sunwoo@arm.com template class BranchNBits<22>; 1278719SN/A 1289053Sdam.sunwoo@arm.com template class BranchNBits<30>; 1299053Sdam.sunwoo@arm.com 1309053Sdam.sunwoo@arm.com std::string 1318719SN/A Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1329053Sdam.sunwoo@arm.com { 1338719SN/A std::stringstream response; 1348719SN/A 1359053Sdam.sunwoo@arm.com printMnemonic(response, mnemonic); 1368719SN/A printRegArray(response, _srcRegIdx, _numSrcRegs); 1379053Sdam.sunwoo@arm.com if (_numDestRegs && _numSrcRegs) 1389053Sdam.sunwoo@arm.com response << ", "; 1399053Sdam.sunwoo@arm.com printDestReg(response, 0); 1408719SN/A 1418719SN/A return response.str(); 1428719SN/A } 1438719SN/A 1448719SN/A std::string 1459053Sdam.sunwoo@arm.com BranchImm13::generateDisassembly(Addr pc, 1468719SN/A const SymbolTable *symtab) const 1479053Sdam.sunwoo@arm.com { 1489053Sdam.sunwoo@arm.com std::stringstream response; 1499053Sdam.sunwoo@arm.com 1509053Sdam.sunwoo@arm.com printMnemonic(response, mnemonic); 1518719SN/A printRegArray(response, _srcRegIdx, _numSrcRegs); 1528719SN/A if (_numSrcRegs > 0) 1538719SN/A response << ", "; 1548719SN/A ccprintf(response, "0x%x", imm); 1558719SN/A if (_numDestRegs > 0) 1569053Sdam.sunwoo@arm.com response << ", "; 1578719SN/A printDestReg(response, 0); 1589053Sdam.sunwoo@arm.com 1599053Sdam.sunwoo@arm.com return response.str(); 1609053Sdam.sunwoo@arm.com } 1618719SN/A 1628719SN/A std::string 1638719SN/A BranchDisp::generateDisassembly(Addr pc, 1648719SN/A const SymbolTable *symtab) const 1658719SN/A { 1669053Sdam.sunwoo@arm.com std::stringstream response; 1678719SN/A std::string symbol; 1689053Sdam.sunwoo@arm.com Addr symbolAddr; 1699053Sdam.sunwoo@arm.com 1709053Sdam.sunwoo@arm.com Addr target = disp + pc; 1718719SN/A 1728719SN/A printMnemonic(response, mnemonic); 1738719SN/A ccprintf(response, "0x%x", target); 1748719SN/A 1758719SN/A if (symtab && 1769053Sdam.sunwoo@arm.com symtab->findNearestSymbol(target, symbol, symbolAddr)) { 1778719SN/A ccprintf(response, " <%s", symbol); 1789053Sdam.sunwoo@arm.com if (symbolAddr != target) 1799053Sdam.sunwoo@arm.com ccprintf(response, "+%d>", target - symbolAddr); 1809053Sdam.sunwoo@arm.com else 1818719SN/A ccprintf(response, ">"); 1828719SN/A } 1838719SN/A 1848719SN/A return response.str(); 1858719SN/A } 1868719SN/A}}; 1879235Sandreas.hansson@arm.com 1889098Sandreas.hansson@arm.comdef template JumpExecute {{ 1892408SN/A Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 1908931Sandreas.hansson@arm.com Trace::InstRecord *traceData) const 1912408SN/A { 1922408SN/A // Attempt to execute the instruction 1933170SN/A Fault fault = NoFault; 1946076SN/A 1953170SN/A %(op_decl)s; 1968931Sandreas.hansson@arm.com %(op_rd)s; 1973170SN/A 1984626SN/A PCS = PCS; 1993170SN/A %(code)s; 2003170SN/A 2013170SN/A if (fault == NoFault) { 2023170SN/A // Write the resulting state to the execution context 2033170SN/A %(op_wb)s; 2043170SN/A } 2053170SN/A 2063170SN/A return fault; 2073170SN/A } 2085714SN/A}}; 2095714SN/A 2103170SN/Adef template BranchExecute {{ 2113170SN/A Fault 2123170SN/A %(class_name)s::execute(%(CPU_exec_context)s *xc, 2133170SN/A Trace::InstRecord *traceData) const 2143170SN/A { 2153170SN/A // Attempt to execute the instruction 2165714SN/A Fault fault = NoFault; 2175714SN/A 2183170SN/A %(op_decl)s; 2193170SN/A %(op_rd)s; 2203170SN/A 2213170SN/A if (%(cond)s) { 2223170SN/A %(code)s; 2233170SN/A } else { 2243170SN/A %(fail)s; 2253170SN/A } 2263170SN/A 2278931Sandreas.hansson@arm.com if (fault == NoFault) { 2283170SN/A // Write the resulting state to the execution context 2294626SN/A %(op_wb)s; 2303170SN/A } 2316102SN/A 2323170SN/A return fault; 2333170SN/A } 2343170SN/A}}; 2353170SN/A 2369080Smatt.evans@arm.comdef template BranchDecode {{ 2373170SN/A if (A) 2389080Smatt.evans@arm.com return new %(class_name)sAnnul("%(mnemonic)s,a", machInst); 2399080Smatt.evans@arm.com else 2409080Smatt.evans@arm.com return new %(class_name)s("%(mnemonic)s", machInst); 2419080Smatt.evans@arm.com}}; 2429080Smatt.evans@arm.com 2433170SN/A// Primary format for branch instructions: 2443170SN/Adef format Branch(code, *opt_flags) {{ 2459080Smatt.evans@arm.com (usesImm, code, immCode, 2469080Smatt.evans@arm.com rString, iString) = splitOutImm(code) 2479080Smatt.evans@arm.com iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 2489080Smatt.evans@arm.com header_output = BasicDeclare.subst(iop) 2499080Smatt.evans@arm.com decoder_output = BasicConstructor.subst(iop) 2505714SN/A exec_output = JumpExecute.subst(iop) 2515714SN/A if usesImm: 2529080Smatt.evans@arm.com imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 2539080Smatt.evans@arm.com immCode, opt_flags) 2543170SN/A header_output += BasicDeclare.subst(imm_iop) 2559080Smatt.evans@arm.com decoder_output += BasicConstructor.subst(imm_iop) 2569080Smatt.evans@arm.com exec_output += JumpExecute.subst(imm_iop) 2579080Smatt.evans@arm.com decode_block = ROrImmDecode.subst(iop) 2589080Smatt.evans@arm.com else: 2593170SN/A decode_block = BasicDecode.subst(iop) 2609080Smatt.evans@arm.com}}; 2619080Smatt.evans@arm.com 2629080Smatt.evans@arm.comlet {{ 2639080Smatt.evans@arm.com def doBranch(name, Name, base, cond, 2649080Smatt.evans@arm.com code, annul_code, fail, annul_fail, opt_flags): 2659080Smatt.evans@arm.com iop = InstObjParams(name, Name, base, 2669080Smatt.evans@arm.com {"code": code, 2679080Smatt.evans@arm.com "fail": fail, 2689080Smatt.evans@arm.com "cond": cond 2699080Smatt.evans@arm.com }, 2709080Smatt.evans@arm.com opt_flags) 2719080Smatt.evans@arm.com header_output = BasicDeclareWithMnemonic.subst(iop) 27210102Sali.saidi@arm.com decoder_output = BasicConstructorWithMnemonic.subst(iop) 27310102Sali.saidi@arm.com exec_output = BranchExecute.subst(iop) 27410102Sali.saidi@arm.com if annul_code == "None": 27510102Sali.saidi@arm.com decode_block = BasicDecodeWithMnemonic.subst(iop) 27610102Sali.saidi@arm.com else: 27710102Sali.saidi@arm.com decode_block = BranchDecode.subst(iop) 2789080Smatt.evans@arm.com 2799080Smatt.evans@arm.com if annul_code != "None": 2809080Smatt.evans@arm.com iop = InstObjParams(name + ',a', Name + 'Annul', base, 2819080Smatt.evans@arm.com {"code": annul_code, 2823170SN/A "fail": annul_fail, 2833170SN/A "cond": cond 2843170SN/A }, 2859080Smatt.evans@arm.com opt_flags) 2863170SN/A header_output += BasicDeclareWithMnemonic.subst(iop) 2873170SN/A decoder_output += BasicConstructorWithMnemonic.subst(iop) 2884626SN/A exec_output += BranchExecute.subst(iop) 2894626SN/A return (header_output, decoder_output, exec_output, decode_block) 2904626SN/A 2919931SAli.Saidi@ARM.com def doCondBranch(name, Name, base, cond, code, opt_flags): 2929931SAli.Saidi@ARM.com return doBranch(name, Name, base, cond, code, code, 2939931SAli.Saidi@ARM.com 'PCS = PCS;', 2949931SAli.Saidi@ARM.com ''' 2959931SAli.Saidi@ARM.com SparcISA::PCState pc = PCS; 2969931SAli.Saidi@ARM.com pc.nnpc(pc.npc() + 8); 2974626SN/A pc.npc(pc.npc() + 4); 2984626SN/A PCS = pc; 2994626SN/A ''', 3004626SN/A opt_flags) 3014626SN/A 3024626SN/A def doUncondBranch(name, Name, base, code, annul_code, opt_flags): 3034626SN/A return doBranch(name, Name, base, "true", code, annul_code, 3044626SN/A ";", ";", opt_flags) 3054626SN/A 3064626SN/A default_branch_code = ''' 3074626SN/A SparcISA::PCState pc = PCS; 3089931SAli.Saidi@ARM.com pc.nnpc(pc.pc() + disp); 3099931SAli.Saidi@ARM.com PCS = pc; 3109931SAli.Saidi@ARM.com ''' 3119931SAli.Saidi@ARM.com}}; 31210563Sandreas.hansson@arm.com 3139931SAli.Saidi@ARM.com// Format for branch instructions with n bit displacements: 3144626SN/Adef format BranchN(bits, code=default_branch_code, 3154626SN/A test=None, annul_code=None, *opt_flags) {{ 3164626SN/A if code == "default_branch_code": 3174626SN/A code = default_branch_code 3184626SN/A if test != "None": 3194626SN/A (header_output, 3204626SN/A decoder_output, 3214626SN/A exec_output, 3228931Sandreas.hansson@arm.com decode_block) = doCondBranch(name, Name, 3238931Sandreas.hansson@arm.com "BranchNBits<%d>" % bits, test, code, opt_flags) 3242413SN/A else: 3259405Sandreas.hansson@arm.com (header_output, 3269405Sandreas.hansson@arm.com decoder_output, 3272414SN/A exec_output, 3284626SN/A decode_block) = doUncondBranch(name, Name, 3294626SN/A "BranchNBits<%d>" % bits, code, annul_code, opt_flags) 3304626SN/A}}; 3318931Sandreas.hansson@arm.com 3323175SN/A// Format for branch instructions with split displacements: 3334626SN/Adef format BranchSplit(code=default_branch_code, 3349405Sandreas.hansson@arm.com test=None, annul_code=None, *opt_flags) {{ 3354626SN/A if code == "default_branch_code": 3364626SN/A code = default_branch_code 33710466Sandreas.hansson@arm.com if test != "None": 3384040SN/A (header_output, 3394040SN/A decoder_output, 3404040SN/A exec_output, 3415477SN/A decode_block) = doCondBranch(name, Name, 3425477SN/A "BranchSplit", test, code, opt_flags) 3434040SN/A else: 34410466Sandreas.hansson@arm.com (header_output, 3454040SN/A decoder_output, 3464040SN/A exec_output, 34710563Sandreas.hansson@arm.com decode_block) = doUncondBranch(name, Name, 34810563Sandreas.hansson@arm.com "BranchSplit", code, annul_code, opt_flags) 3494626SN/A}}; 3504040SN/A 3514040SN/A