branch.isa revision 9552
12068SN/A// -*- mode:c++ -*- 22068SN/A 32068SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan 42068SN/A// All rights reserved. 52068SN/A// 62068SN/A// Redistribution and use in source and binary forms, with or without 72068SN/A// modification, are permitted provided that the following conditions are 82068SN/A// met: redistributions of source code must retain the above copyright 92068SN/A// notice, this list of conditions and the following disclaimer; 102068SN/A// redistributions in binary form must reproduce the above copyright 112068SN/A// notice, this list of conditions and the following disclaimer in the 122068SN/A// documentation and/or other materials provided with the distribution; 132068SN/A// neither the name of the copyright holders nor the names of its 142068SN/A// contributors may be used to endorse or promote products derived from 152068SN/A// this software without specific prior written permission. 162068SN/A// 172068SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182068SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192068SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202068SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212068SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222068SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232068SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242068SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252068SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262068SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272068SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu// 292665Ssaidi@eecs.umich.edu// Authors: Steve Reinhardt 302068SN/A 312649Ssaidi@eecs.umich.edu//////////////////////////////////////////////////////////////////// 322649Ssaidi@eecs.umich.edu// 332649Ssaidi@eecs.umich.edu// Control transfer instructions 342649Ssaidi@eecs.umich.edu// 352649Ssaidi@eecs.umich.edu 362068SN/Aoutput header {{ 372068SN/A 382068SN/A /** 392068SN/A * Base class for instructions whose disassembly is not purely a 402068SN/A * function of the machine instruction (i.e., it depends on the 412068SN/A * PC). This class overrides the disassemble() method to check 422068SN/A * the PC and symbol table values before re-using a cached 432068SN/A * disassembly string. This is necessary for branches and jumps, 442068SN/A * where the disassembly string includes the target address (which 452068SN/A * may depend on the PC and/or symbol table). 462068SN/A */ 472068SN/A class PCDependentDisassembly : public AlphaStaticInst 482068SN/A { 492068SN/A protected: 502068SN/A /// Cached program counter from last disassembly 512068SN/A mutable Addr cachedPC; 522068SN/A /// Cached symbol table pointer from last disassembly 532068SN/A mutable const SymbolTable *cachedSymtab; 542068SN/A 552068SN/A /// Constructor 562227SN/A PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, 572068SN/A OpClass __opClass) 582068SN/A : AlphaStaticInst(mnem, _machInst, __opClass), 592068SN/A cachedPC(0), cachedSymtab(0) 602068SN/A { 612068SN/A } 622068SN/A 632068SN/A const std::string & 642068SN/A disassemble(Addr pc, const SymbolTable *symtab) const; 652068SN/A }; 662068SN/A 672068SN/A /** 682068SN/A * Base class for branches (PC-relative control transfers), 692068SN/A * conditional or unconditional. 702068SN/A */ 712068SN/A class Branch : public PCDependentDisassembly 722068SN/A { 732068SN/A protected: 742068SN/A /// Displacement to target address (signed). 752068SN/A int32_t disp; 762068SN/A 772068SN/A /// Constructor. 782227SN/A Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 792068SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 802068SN/A disp(BRDISP << 2) 812068SN/A { 822068SN/A } 832068SN/A 847720Sgblack@eecs.umich.edu AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const; 852068SN/A 869552Sandreas.hansson@arm.com /// Explicitly import the otherwise hidden branchTarget 879552Sandreas.hansson@arm.com using StaticInst::branchTarget; 889552Sandreas.hansson@arm.com 892068SN/A std::string 902068SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 912068SN/A }; 922068SN/A 932068SN/A /** 942068SN/A * Base class for jumps (register-indirect control transfers). In 952068SN/A * the Alpha ISA, these are always unconditional. 962068SN/A */ 972068SN/A class Jump : public PCDependentDisassembly 982068SN/A { 992068SN/A protected: 1002068SN/A 1012068SN/A /// Displacement to target address (signed). 1022068SN/A int32_t disp; 1032068SN/A 1042068SN/A public: 1052068SN/A /// Constructor 1062227SN/A Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 1072068SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 1082068SN/A disp(BRDISP) 1092068SN/A { 1102068SN/A } 1112068SN/A 1127720Sgblack@eecs.umich.edu AlphaISA::PCState branchTarget(ThreadContext *tc) const; 1132068SN/A 1149552Sandreas.hansson@arm.com /// Explicitly import the otherwise hidden branchTarget 1159552Sandreas.hansson@arm.com using StaticInst::branchTarget; 1169552Sandreas.hansson@arm.com 1172068SN/A std::string 1182068SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1192068SN/A }; 1202068SN/A}}; 1212068SN/A 1222068SN/Aoutput decoder {{ 1237720Sgblack@eecs.umich.edu AlphaISA::PCState 1247720Sgblack@eecs.umich.edu Branch::branchTarget(const AlphaISA::PCState &branchPC) const 1252068SN/A { 1267720Sgblack@eecs.umich.edu return branchPC.pc() + 4 + disp; 1272068SN/A } 1282068SN/A 1297720Sgblack@eecs.umich.edu AlphaISA::PCState 1302680Sktlim@umich.edu Jump::branchTarget(ThreadContext *tc) const 1312068SN/A { 1327720Sgblack@eecs.umich.edu PCState pc = tc->pcState(); 1332680Sktlim@umich.edu uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); 1347720Sgblack@eecs.umich.edu pc.set((Rb & ~3) | (pc.pc() & 1)); 1357720Sgblack@eecs.umich.edu return pc; 1362068SN/A } 1372068SN/A 1382068SN/A const std::string & 1392068SN/A PCDependentDisassembly::disassemble(Addr pc, 1402068SN/A const SymbolTable *symtab) const 1412068SN/A { 1422068SN/A if (!cachedDisassembly || 1432068SN/A pc != cachedPC || symtab != cachedSymtab) 1442068SN/A { 1452068SN/A if (cachedDisassembly) 1462068SN/A delete cachedDisassembly; 1472068SN/A 1482068SN/A cachedDisassembly = 1492068SN/A new std::string(generateDisassembly(pc, symtab)); 1502068SN/A cachedPC = pc; 1512068SN/A cachedSymtab = symtab; 1522068SN/A } 1532068SN/A 1542068SN/A return *cachedDisassembly; 1552068SN/A } 1562068SN/A 1572068SN/A std::string 1582068SN/A Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1592068SN/A { 1602068SN/A std::stringstream ss; 1612068SN/A 1622068SN/A ccprintf(ss, "%-10s ", mnemonic); 1632068SN/A 1642068SN/A // There's only one register arg (RA), but it could be 1652068SN/A // either a source (the condition for conditional 1662068SN/A // branches) or a destination (the link reg for 1672068SN/A // unconditional branches) 1682068SN/A if (_numSrcRegs > 0) { 1692068SN/A printReg(ss, _srcRegIdx[0]); 1702068SN/A ss << ","; 1712068SN/A } 1722068SN/A else if (_numDestRegs > 0) { 1732068SN/A printReg(ss, _destRegIdx[0]); 1742068SN/A ss << ","; 1752068SN/A } 1762068SN/A 1772068SN/A#ifdef SS_COMPATIBLE_DISASSEMBLY 1782068SN/A if (_numSrcRegs == 0 && _numDestRegs == 0) { 1792068SN/A printReg(ss, 31); 1802068SN/A ss << ","; 1812068SN/A } 1822068SN/A#endif 1832068SN/A 1842068SN/A Addr target = pc + 4 + disp; 1852068SN/A 1862068SN/A std::string str; 1872068SN/A if (symtab && symtab->findSymbol(target, str)) 1882068SN/A ss << str; 1892068SN/A else 1902068SN/A ccprintf(ss, "0x%x", target); 1912068SN/A 1922068SN/A return ss.str(); 1932068SN/A } 1942068SN/A 1952068SN/A std::string 1962068SN/A Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1972068SN/A { 1982068SN/A std::stringstream ss; 1992068SN/A 2002068SN/A ccprintf(ss, "%-10s ", mnemonic); 2012068SN/A 2022068SN/A#ifdef SS_COMPATIBLE_DISASSEMBLY 2032068SN/A if (_numDestRegs == 0) { 2042068SN/A printReg(ss, 31); 2052068SN/A ss << ","; 2062068SN/A } 2072068SN/A#endif 2082068SN/A 2092068SN/A if (_numDestRegs > 0) { 2102068SN/A printReg(ss, _destRegIdx[0]); 2112068SN/A ss << ","; 2122068SN/A } 2132068SN/A 2142068SN/A ccprintf(ss, "(r%d)", RB); 2152068SN/A 2162068SN/A return ss.str(); 2172068SN/A } 2182068SN/A}}; 2192068SN/A 2202068SN/Adef template JumpOrBranchDecode {{ 2212068SN/A return (RA == 31) 2222107SN/A ? (StaticInst *)new %(class_name)s(machInst) 2232107SN/A : (StaticInst *)new %(class_name)sAndLink(machInst); 2242068SN/A}}; 2252068SN/A 2262068SN/Adef format CondBranch(code) {{ 2277720Sgblack@eecs.umich.edu code = ''' 2287720Sgblack@eecs.umich.edu bool cond; 2297720Sgblack@eecs.umich.edu %(code)s; 2307720Sgblack@eecs.umich.edu if (cond) 2317794Sgblack@eecs.umich.edu NPC = NPC + disp; 2327794Sgblack@eecs.umich.edu else 2337794Sgblack@eecs.umich.edu NPC = NPC; 2347720Sgblack@eecs.umich.edu ''' % { "code" : code } 2353953Sstever@eecs.umich.edu iop = InstObjParams(name, Name, 'Branch', code, 2362068SN/A ('IsDirectControl', 'IsCondControl')) 2372068SN/A header_output = BasicDeclare.subst(iop) 2382068SN/A decoder_output = BasicConstructor.subst(iop) 2392068SN/A decode_block = BasicDecode.subst(iop) 2402068SN/A exec_output = BasicExecute.subst(iop) 2412068SN/A}}; 2422068SN/A 2432068SN/Alet {{ 2442068SN/Adef UncondCtrlBase(name, Name, base_class, npc_expr, flags): 2452068SN/A # Declare basic control transfer w/o link (i.e. link reg is R31) 2467794Sgblack@eecs.umich.edu nolink_code = 'NPC = %s;\n' % npc_expr 2477720Sgblack@eecs.umich.edu nolink_iop = InstObjParams(name, Name, base_class, 2487794Sgblack@eecs.umich.edu nolink_code, flags) 2492068SN/A header_output = BasicDeclare.subst(nolink_iop) 2502068SN/A decoder_output = BasicConstructor.subst(nolink_iop) 2512068SN/A exec_output = BasicExecute.subst(nolink_iop) 2522068SN/A 2532068SN/A # Generate declaration of '*AndLink' version, append to decls 2547794Sgblack@eecs.umich.edu link_code = 'Ra = NPC & ~3;\n' + nolink_code 2552068SN/A link_iop = InstObjParams(name, Name + 'AndLink', base_class, 2567794Sgblack@eecs.umich.edu link_code, flags) 2572068SN/A header_output += BasicDeclare.subst(link_iop) 2582068SN/A decoder_output += BasicConstructor.subst(link_iop) 2592068SN/A exec_output += BasicExecute.subst(link_iop) 2602068SN/A 2612068SN/A # need to use link_iop for the decode template since it is expecting 2622068SN/A # the shorter version of class_name (w/o "AndLink") 2632068SN/A 2642068SN/A return (header_output, decoder_output, 2652068SN/A JumpOrBranchDecode.subst(nolink_iop), exec_output) 2662068SN/A}}; 2672068SN/A 2682068SN/Adef format UncondBranch(*flags) {{ 2692068SN/A flags += ('IsUncondControl', 'IsDirectControl') 2702068SN/A (header_output, decoder_output, decode_block, exec_output) = \ 2717794Sgblack@eecs.umich.edu UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) 2722068SN/A}}; 2732068SN/A 2742068SN/Adef format Jump(*flags) {{ 2752068SN/A flags += ('IsUncondControl', 'IsIndirectControl') 2762068SN/A (header_output, decoder_output, decode_block, exec_output) = \ 2777794Sgblack@eecs.umich.edu UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) 2782068SN/A}}; 2792068SN/A 2802068SN/A 281