branch.isa revision 2227
12929Sktlim@umich.edu// -*- mode:c++ -*- 22929Sktlim@umich.edu 32932Sktlim@umich.edu// Copyright (c) 2003-2005 The Regents of The University of Michigan 42929Sktlim@umich.edu// All rights reserved. 52929Sktlim@umich.edu// 62929Sktlim@umich.edu// Redistribution and use in source and binary forms, with or without 72929Sktlim@umich.edu// modification, are permitted provided that the following conditions are 82929Sktlim@umich.edu// met: redistributions of source code must retain the above copyright 92929Sktlim@umich.edu// notice, this list of conditions and the following disclaimer; 102929Sktlim@umich.edu// redistributions in binary form must reproduce the above copyright 112929Sktlim@umich.edu// notice, this list of conditions and the following disclaimer in the 122929Sktlim@umich.edu// documentation and/or other materials provided with the distribution; 132929Sktlim@umich.edu// neither the name of the copyright holders nor the names of its 142929Sktlim@umich.edu// contributors may be used to endorse or promote products derived from 152929Sktlim@umich.edu// this software without specific prior written permission. 162929Sktlim@umich.edu// 172929Sktlim@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182929Sktlim@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192929Sktlim@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202929Sktlim@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212929Sktlim@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222929Sktlim@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232929Sktlim@umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242929Sktlim@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252929Sktlim@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262929Sktlim@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272929Sktlim@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282932Sktlim@umich.edu 292932Sktlim@umich.eduoutput header {{ 302932Sktlim@umich.edu 312929Sktlim@umich.edu /** 326007Ssteve.reinhardt@amd.com * Base class for instructions whose disassembly is not purely a 337735SAli.Saidi@ARM.com * function of the machine instruction (i.e., it depends on the 342929Sktlim@umich.edu * PC). This class overrides the disassemble() method to check 352929Sktlim@umich.edu * the PC and symbol table values before re-using a cached 362929Sktlim@umich.edu * disassembly string. This is necessary for branches and jumps, 372929Sktlim@umich.edu * where the disassembly string includes the target address (which 382929Sktlim@umich.edu * may depend on the PC and/or symbol table). 392929Sktlim@umich.edu */ 402929Sktlim@umich.edu class PCDependentDisassembly : public AlphaStaticInst 418947Sandreas.hansson@arm.com { 428947Sandreas.hansson@arm.com protected: 438947Sandreas.hansson@arm.com /// Cached program counter from last disassembly 442929Sktlim@umich.edu mutable Addr cachedPC; 452929Sktlim@umich.edu /// Cached symbol table pointer from last disassembly 462929Sktlim@umich.edu mutable const SymbolTable *cachedSymtab; 472929Sktlim@umich.edu 482929Sktlim@umich.edu /// Constructor 492929Sktlim@umich.edu PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, 506007Ssteve.reinhardt@amd.com OpClass __opClass) 516007Ssteve.reinhardt@amd.com : AlphaStaticInst(mnem, _machInst, __opClass), 526007Ssteve.reinhardt@amd.com cachedPC(0), cachedSymtab(0) 536007Ssteve.reinhardt@amd.com { 546007Ssteve.reinhardt@amd.com } 556007Ssteve.reinhardt@amd.com 566007Ssteve.reinhardt@amd.com const std::string & 576007Ssteve.reinhardt@amd.com disassemble(Addr pc, const SymbolTable *symtab) const; 586007Ssteve.reinhardt@amd.com }; 596007Ssteve.reinhardt@amd.com 606007Ssteve.reinhardt@amd.com /** 616007Ssteve.reinhardt@amd.com * Base class for branches (PC-relative control transfers), 626007Ssteve.reinhardt@amd.com * conditional or unconditional. 636007Ssteve.reinhardt@amd.com */ 646007Ssteve.reinhardt@amd.com class Branch : public PCDependentDisassembly 656007Ssteve.reinhardt@amd.com { 669435SAndreas.Sandberg@ARM.com protected: 679435SAndreas.Sandberg@ARM.com /// Displacement to target address (signed). 689435SAndreas.Sandberg@ARM.com int32_t disp; 696007Ssteve.reinhardt@amd.com 706007Ssteve.reinhardt@amd.com /// Constructor. 716007Ssteve.reinhardt@amd.com Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 726007Ssteve.reinhardt@amd.com : PCDependentDisassembly(mnem, _machInst, __opClass), 736007Ssteve.reinhardt@amd.com disp(BRDISP << 2) 746007Ssteve.reinhardt@amd.com { 756007Ssteve.reinhardt@amd.com } 766007Ssteve.reinhardt@amd.com 776007Ssteve.reinhardt@amd.com Addr branchTarget(Addr branchPC) const; 786007Ssteve.reinhardt@amd.com 792929Sktlim@umich.edu std::string 802929Sktlim@umich.edu generateDisassembly(Addr pc, const SymbolTable *symtab) const; 812929Sktlim@umich.edu }; 826007Ssteve.reinhardt@amd.com 836007Ssteve.reinhardt@amd.com /** 846007Ssteve.reinhardt@amd.com * Base class for jumps (register-indirect control transfers). In 859781Sandreas.hansson@arm.com * the Alpha ISA, these are always unconditional. 866007Ssteve.reinhardt@amd.com */ 876007Ssteve.reinhardt@amd.com class Jump : public PCDependentDisassembly 882929Sktlim@umich.edu { 892929Sktlim@umich.edu protected: 902929Sktlim@umich.edu 912929Sktlim@umich.edu /// Displacement to target address (signed). 922929Sktlim@umich.edu int32_t disp; 936011Ssteve.reinhardt@amd.com 946007Ssteve.reinhardt@amd.com public: 956007Ssteve.reinhardt@amd.com /// Constructor 966007Ssteve.reinhardt@amd.com Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 976007Ssteve.reinhardt@amd.com : PCDependentDisassembly(mnem, _machInst, __opClass), 986007Ssteve.reinhardt@amd.com disp(BRDISP) 996007Ssteve.reinhardt@amd.com { 1006007Ssteve.reinhardt@amd.com } 1016007Ssteve.reinhardt@amd.com 1026007Ssteve.reinhardt@amd.com Addr branchTarget(ExecContext *xc) const; 1036007Ssteve.reinhardt@amd.com 1046007Ssteve.reinhardt@amd.com std::string 1056007Ssteve.reinhardt@amd.com generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1066007Ssteve.reinhardt@amd.com }; 10710384SCurtis.Dunham@arm.com}}; 10810384SCurtis.Dunham@arm.com 10910384SCurtis.Dunham@arm.comoutput decoder {{ 11010384SCurtis.Dunham@arm.com Addr 1116007Ssteve.reinhardt@amd.com Branch::branchTarget(Addr branchPC) const 1129781Sandreas.hansson@arm.com { 1139781Sandreas.hansson@arm.com return branchPC + 4 + disp; 1149781Sandreas.hansson@arm.com } 1159781Sandreas.hansson@arm.com 1167735SAli.Saidi@ARM.com Addr 1176011Ssteve.reinhardt@amd.com Jump::branchTarget(ExecContext *xc) const 1186007Ssteve.reinhardt@amd.com { 1199781Sandreas.hansson@arm.com Addr NPC = xc->readPC() + 4; 1206007Ssteve.reinhardt@amd.com uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); 1216007Ssteve.reinhardt@amd.com return (Rb & ~3) | (NPC & 1); 1227735SAli.Saidi@ARM.com } 1237735SAli.Saidi@ARM.com 1247735SAli.Saidi@ARM.com const std::string & 1257735SAli.Saidi@ARM.com PCDependentDisassembly::disassemble(Addr pc, 1267735SAli.Saidi@ARM.com const SymbolTable *symtab) const 1277735SAli.Saidi@ARM.com { 1287735SAli.Saidi@ARM.com if (!cachedDisassembly || 1297735SAli.Saidi@ARM.com pc != cachedPC || symtab != cachedSymtab) 1307735SAli.Saidi@ARM.com { 1317735SAli.Saidi@ARM.com if (cachedDisassembly) 1327735SAli.Saidi@ARM.com delete cachedDisassembly; 1337735SAli.Saidi@ARM.com 1347735SAli.Saidi@ARM.com cachedDisassembly = 1357735SAli.Saidi@ARM.com new std::string(generateDisassembly(pc, symtab)); 1366007Ssteve.reinhardt@amd.com cachedPC = pc; 1378599Ssteve.reinhardt@amd.com cachedSymtab = symtab; 1388599Ssteve.reinhardt@amd.com } 1398599Ssteve.reinhardt@amd.com 1406007Ssteve.reinhardt@amd.com return *cachedDisassembly; 1416011Ssteve.reinhardt@amd.com } 1426007Ssteve.reinhardt@amd.com 1436007Ssteve.reinhardt@amd.com std::string 1446007Ssteve.reinhardt@amd.com Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1456007Ssteve.reinhardt@amd.com { 1466007Ssteve.reinhardt@amd.com std::stringstream ss; 1476007Ssteve.reinhardt@amd.com 1489781Sandreas.hansson@arm.com ccprintf(ss, "%-10s ", mnemonic); 1499781Sandreas.hansson@arm.com 1509781Sandreas.hansson@arm.com // There's only one register arg (RA), but it could be 1519781Sandreas.hansson@arm.com // either a source (the condition for conditional 1526007Ssteve.reinhardt@amd.com // branches) or a destination (the link reg for 1536007Ssteve.reinhardt@amd.com // unconditional branches) 1546007Ssteve.reinhardt@amd.com if (_numSrcRegs > 0) { 1559781Sandreas.hansson@arm.com printReg(ss, _srcRegIdx[0]); 1569781Sandreas.hansson@arm.com ss << ","; 1579781Sandreas.hansson@arm.com } 1589781Sandreas.hansson@arm.com else if (_numDestRegs > 0) { 15910384SCurtis.Dunham@arm.com printReg(ss, _destRegIdx[0]); 16010384SCurtis.Dunham@arm.com ss << ","; 16110384SCurtis.Dunham@arm.com } 1629781Sandreas.hansson@arm.com 1636008Ssteve.reinhardt@amd.com#ifdef SS_COMPATIBLE_DISASSEMBLY 1646008Ssteve.reinhardt@amd.com if (_numSrcRegs == 0 && _numDestRegs == 0) { 1656008Ssteve.reinhardt@amd.com printReg(ss, 31); 1666008Ssteve.reinhardt@amd.com ss << ","; 1676008Ssteve.reinhardt@amd.com } 1689401SAndreas.Sandberg@ARM.com#endif 1699781Sandreas.hansson@arm.com 1709781Sandreas.hansson@arm.com Addr target = pc + 4 + disp; 1716008Ssteve.reinhardt@amd.com 1729781Sandreas.hansson@arm.com std::string str; 1736007Ssteve.reinhardt@amd.com if (symtab && symtab->findSymbol(target, str)) 1746007Ssteve.reinhardt@amd.com ss << str; 1756007Ssteve.reinhardt@amd.com else 1766007Ssteve.reinhardt@amd.com ccprintf(ss, "0x%x", target); 1779781Sandreas.hansson@arm.com 1786007Ssteve.reinhardt@amd.com return ss.str(); 1796007Ssteve.reinhardt@amd.com } 1802929Sktlim@umich.edu 1812929Sktlim@umich.edu std::string 1822929Sktlim@umich.edu Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1832929Sktlim@umich.edu { 1846007Ssteve.reinhardt@amd.com std::stringstream ss; 1856007Ssteve.reinhardt@amd.com 1862929Sktlim@umich.edu ccprintf(ss, "%-10s ", mnemonic); 1872929Sktlim@umich.edu 1886007Ssteve.reinhardt@amd.com#ifdef SS_COMPATIBLE_DISASSEMBLY 1892929Sktlim@umich.edu if (_numDestRegs == 0) { 1902929Sktlim@umich.edu printReg(ss, 31); 1918947Sandreas.hansson@arm.com ss << ","; 1928947Sandreas.hansson@arm.com } 1938947Sandreas.hansson@arm.com#endif 1948947Sandreas.hansson@arm.com 1958947Sandreas.hansson@arm.com if (_numDestRegs > 0) { 1968947Sandreas.hansson@arm.com printReg(ss, _destRegIdx[0]); 1978947Sandreas.hansson@arm.com ss << ","; 1988947Sandreas.hansson@arm.com } 1998947Sandreas.hansson@arm.com 2008947Sandreas.hansson@arm.com ccprintf(ss, "(r%d)", RB); 20110384SCurtis.Dunham@arm.com 2028947Sandreas.hansson@arm.com return ss.str(); 2039781Sandreas.hansson@arm.com } 2049781Sandreas.hansson@arm.com}}; 2058947Sandreas.hansson@arm.com 2068947Sandreas.hansson@arm.comdef template JumpOrBranchDecode {{ 2079401SAndreas.Sandberg@ARM.com return (RA == 31) 2089781Sandreas.hansson@arm.com ? (StaticInst *)new %(class_name)s(machInst) 2098947Sandreas.hansson@arm.com : (StaticInst *)new %(class_name)sAndLink(machInst); 2108947Sandreas.hansson@arm.com}}; 2118947Sandreas.hansson@arm.com 2128947Sandreas.hansson@arm.comdef format CondBranch(code) {{ 2138947Sandreas.hansson@arm.com code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; 2148947Sandreas.hansson@arm.com iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 2152929Sktlim@umich.edu ('IsDirectControl', 'IsCondControl')) 2162929Sktlim@umich.edu header_output = BasicDeclare.subst(iop) 2172929Sktlim@umich.edu decoder_output = BasicConstructor.subst(iop) 2182929Sktlim@umich.edu decode_block = BasicDecode.subst(iop) 2194937Sstever@gmail.com exec_output = BasicExecute.subst(iop) 2204937Sstever@gmail.com}}; 2214937Sstever@gmail.com 2224937Sstever@gmail.comlet {{ 2238120Sgblack@eecs.umich.edudef UncondCtrlBase(name, Name, base_class, npc_expr, flags): 2244937Sstever@gmail.com # Declare basic control transfer w/o link (i.e. link reg is R31) 2254937Sstever@gmail.com nolink_code = 'NPC = %s;\n' % npc_expr 2264937Sstever@gmail.com nolink_iop = InstObjParams(name, Name, base_class, 2274937Sstever@gmail.com CodeBlock(nolink_code), flags) 2285773Snate@binkert.org header_output = BasicDeclare.subst(nolink_iop) 2294937Sstever@gmail.com decoder_output = BasicConstructor.subst(nolink_iop) 2304937Sstever@gmail.com exec_output = BasicExecute.subst(nolink_iop) 2314937Sstever@gmail.com 2322929Sktlim@umich.edu # Generate declaration of '*AndLink' version, append to decls 2332929Sktlim@umich.edu link_code = 'Ra = NPC & ~3;\n' + nolink_code 2342929Sktlim@umich.edu link_iop = InstObjParams(name, Name + 'AndLink', base_class, 2355773Snate@binkert.org CodeBlock(link_code), flags) 2362929Sktlim@umich.edu header_output += BasicDeclare.subst(link_iop) 2372929Sktlim@umich.edu decoder_output += BasicConstructor.subst(link_iop) 2382929Sktlim@umich.edu exec_output += BasicExecute.subst(link_iop) 2392929Sktlim@umich.edu 2402929Sktlim@umich.edu # need to use link_iop for the decode template since it is expecting 2412929Sktlim@umich.edu # the shorter version of class_name (w/o "AndLink") 2424937Sstever@gmail.com 2434937Sstever@gmail.com return (header_output, decoder_output, 2444937Sstever@gmail.com JumpOrBranchDecode.subst(nolink_iop), exec_output) 2454937Sstever@gmail.com}}; 2464937Sstever@gmail.com 2474937Sstever@gmail.comdef format UncondBranch(*flags) {{ 2484937Sstever@gmail.com flags += ('IsUncondControl', 'IsDirectControl') 2494937Sstever@gmail.com (header_output, decoder_output, decode_block, exec_output) = \ 2504937Sstever@gmail.com UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) 2514937Sstever@gmail.com}}; 2524937Sstever@gmail.com 2534937Sstever@gmail.comdef format Jump(*flags) {{ 2544937Sstever@gmail.com flags += ('IsUncondControl', 'IsIndirectControl') 2554937Sstever@gmail.com (header_output, decoder_output, decode_block, exec_output) = \ 2564937Sstever@gmail.com UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) 2572929Sktlim@umich.edu}}; 2582929Sktlim@umich.edu 2592929Sktlim@umich.edu 2602929Sktlim@umich.edu