branch.isa revision 2227
16313Sgblack@eecs.umich.edu// -*- mode:c++ -*- 26313Sgblack@eecs.umich.edu 36313Sgblack@eecs.umich.edu// Copyright (c) 2003-2005 The Regents of The University of Michigan 46313Sgblack@eecs.umich.edu// All rights reserved. 56313Sgblack@eecs.umich.edu// 66313Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without 76313Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are 86313Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright 96313Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer; 106313Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright 116313Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the 126313Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution; 136313Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its 146313Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from 156313Sgblack@eecs.umich.edu// this software without specific prior written permission. 166313Sgblack@eecs.umich.edu// 176313Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186313Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196313Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206313Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216313Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226313Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236313Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246313Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256313Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266313Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276313Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286313Sgblack@eecs.umich.edu 296313Sgblack@eecs.umich.eduoutput header {{ 306313Sgblack@eecs.umich.edu 316313Sgblack@eecs.umich.edu /** 326336Sgblack@eecs.umich.edu * Base class for instructions whose disassembly is not purely a 336336Sgblack@eecs.umich.edu * function of the machine instruction (i.e., it depends on the 346313Sgblack@eecs.umich.edu * PC). This class overrides the disassemble() method to check 356336Sgblack@eecs.umich.edu * the PC and symbol table values before re-using a cached 366313Sgblack@eecs.umich.edu * disassembly string. This is necessary for branches and jumps, 376313Sgblack@eecs.umich.edu * where the disassembly string includes the target address (which 386313Sgblack@eecs.umich.edu * may depend on the PC and/or symbol table). 396313Sgblack@eecs.umich.edu */ 406313Sgblack@eecs.umich.edu class PCDependentDisassembly : public AlphaStaticInst 416336Sgblack@eecs.umich.edu { 426336Sgblack@eecs.umich.edu protected: 436336Sgblack@eecs.umich.edu /// Cached program counter from last disassembly 446712Snate@binkert.org mutable Addr cachedPC; 456336Sgblack@eecs.umich.edu /// Cached symbol table pointer from last disassembly 466336Sgblack@eecs.umich.edu mutable const SymbolTable *cachedSymtab; 476336Sgblack@eecs.umich.edu 486336Sgblack@eecs.umich.edu /// Constructor 496336Sgblack@eecs.umich.edu PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, 506336Sgblack@eecs.umich.edu OpClass __opClass) 516336Sgblack@eecs.umich.edu : AlphaStaticInst(mnem, _machInst, __opClass), 526336Sgblack@eecs.umich.edu cachedPC(0), cachedSymtab(0) 536336Sgblack@eecs.umich.edu { 546336Sgblack@eecs.umich.edu } 556336Sgblack@eecs.umich.edu 566336Sgblack@eecs.umich.edu const std::string & 576336Sgblack@eecs.umich.edu disassemble(Addr pc, const SymbolTable *symtab) const; 586336Sgblack@eecs.umich.edu }; 596336Sgblack@eecs.umich.edu 606336Sgblack@eecs.umich.edu /** 616336Sgblack@eecs.umich.edu * Base class for branches (PC-relative control transfers), 626336Sgblack@eecs.umich.edu * conditional or unconditional. 636336Sgblack@eecs.umich.edu */ 646336Sgblack@eecs.umich.edu class Branch : public PCDependentDisassembly 656336Sgblack@eecs.umich.edu { 666336Sgblack@eecs.umich.edu protected: 676336Sgblack@eecs.umich.edu /// Displacement to target address (signed). 686336Sgblack@eecs.umich.edu int32_t disp; 696336Sgblack@eecs.umich.edu 706336Sgblack@eecs.umich.edu /// Constructor. 716336Sgblack@eecs.umich.edu Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 726336Sgblack@eecs.umich.edu : PCDependentDisassembly(mnem, _machInst, __opClass), 736336Sgblack@eecs.umich.edu disp(BRDISP << 2) 746336Sgblack@eecs.umich.edu { 756336Sgblack@eecs.umich.edu } 766336Sgblack@eecs.umich.edu 776336Sgblack@eecs.umich.edu Addr branchTarget(Addr branchPC) const; 786336Sgblack@eecs.umich.edu 796336Sgblack@eecs.umich.edu std::string 806336Sgblack@eecs.umich.edu generateDisassembly(Addr pc, const SymbolTable *symtab) const; 816336Sgblack@eecs.umich.edu }; 826336Sgblack@eecs.umich.edu 836336Sgblack@eecs.umich.edu /** 846336Sgblack@eecs.umich.edu * Base class for jumps (register-indirect control transfers). In 856336Sgblack@eecs.umich.edu * the Alpha ISA, these are always unconditional. 866336Sgblack@eecs.umich.edu */ 876336Sgblack@eecs.umich.edu class Jump : public PCDependentDisassembly 886336Sgblack@eecs.umich.edu { 896336Sgblack@eecs.umich.edu protected: 906336Sgblack@eecs.umich.edu 916336Sgblack@eecs.umich.edu /// Displacement to target address (signed). 926336Sgblack@eecs.umich.edu int32_t disp; 936336Sgblack@eecs.umich.edu 946336Sgblack@eecs.umich.edu public: 956336Sgblack@eecs.umich.edu /// Constructor 966336Sgblack@eecs.umich.edu Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 976336Sgblack@eecs.umich.edu : PCDependentDisassembly(mnem, _machInst, __opClass), 986336Sgblack@eecs.umich.edu disp(BRDISP) 996336Sgblack@eecs.umich.edu { 1006313Sgblack@eecs.umich.edu } 1016313Sgblack@eecs.umich.edu 1026336Sgblack@eecs.umich.edu Addr branchTarget(ExecContext *xc) const; 1036336Sgblack@eecs.umich.edu 1046336Sgblack@eecs.umich.edu std::string 1056336Sgblack@eecs.umich.edu generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1066336Sgblack@eecs.umich.edu }; 1076313Sgblack@eecs.umich.edu}}; 1086313Sgblack@eecs.umich.edu 1096313Sgblack@eecs.umich.eduoutput decoder {{ 1106313Sgblack@eecs.umich.edu Addr 1116313Sgblack@eecs.umich.edu Branch::branchTarget(Addr branchPC) const 1126336Sgblack@eecs.umich.edu { 1136336Sgblack@eecs.umich.edu return branchPC + 4 + disp; 1146336Sgblack@eecs.umich.edu } 1156336Sgblack@eecs.umich.edu 1166336Sgblack@eecs.umich.edu Addr 1176336Sgblack@eecs.umich.edu Jump::branchTarget(ExecContext *xc) const 1186336Sgblack@eecs.umich.edu { 1196336Sgblack@eecs.umich.edu Addr NPC = xc->readPC() + 4; 1206336Sgblack@eecs.umich.edu uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); 1216336Sgblack@eecs.umich.edu return (Rb & ~3) | (NPC & 1); 1226313Sgblack@eecs.umich.edu } 1236313Sgblack@eecs.umich.edu 1246313Sgblack@eecs.umich.edu const std::string & 1256336Sgblack@eecs.umich.edu PCDependentDisassembly::disassemble(Addr pc, 1266313Sgblack@eecs.umich.edu const SymbolTable *symtab) const 1276336Sgblack@eecs.umich.edu { 1286336Sgblack@eecs.umich.edu if (!cachedDisassembly || 1296336Sgblack@eecs.umich.edu pc != cachedPC || symtab != cachedSymtab) 1306336Sgblack@eecs.umich.edu { 1316313Sgblack@eecs.umich.edu if (cachedDisassembly) 1326313Sgblack@eecs.umich.edu delete cachedDisassembly; 1336313Sgblack@eecs.umich.edu 1346336Sgblack@eecs.umich.edu cachedDisassembly = 1356313Sgblack@eecs.umich.edu new std::string(generateDisassembly(pc, symtab)); 1366336Sgblack@eecs.umich.edu cachedPC = pc; 1376336Sgblack@eecs.umich.edu cachedSymtab = symtab; 1386336Sgblack@eecs.umich.edu } 1396336Sgblack@eecs.umich.edu 1406336Sgblack@eecs.umich.edu return *cachedDisassembly; 1416336Sgblack@eecs.umich.edu } 1426336Sgblack@eecs.umich.edu 1436336Sgblack@eecs.umich.edu std::string 1446336Sgblack@eecs.umich.edu Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1456313Sgblack@eecs.umich.edu { 1466313Sgblack@eecs.umich.edu std::stringstream ss; 1476313Sgblack@eecs.umich.edu 1486336Sgblack@eecs.umich.edu ccprintf(ss, "%-10s ", mnemonic); 1496313Sgblack@eecs.umich.edu 1506336Sgblack@eecs.umich.edu // There's only one register arg (RA), but it could be 1516336Sgblack@eecs.umich.edu // either a source (the condition for conditional 1526336Sgblack@eecs.umich.edu // branches) or a destination (the link reg for 1536336Sgblack@eecs.umich.edu // unconditional branches) 1546336Sgblack@eecs.umich.edu if (_numSrcRegs > 0) { 1556336Sgblack@eecs.umich.edu printReg(ss, _srcRegIdx[0]); 1566336Sgblack@eecs.umich.edu ss << ","; 1576336Sgblack@eecs.umich.edu } 1586336Sgblack@eecs.umich.edu else if (_numDestRegs > 0) { 1596336Sgblack@eecs.umich.edu printReg(ss, _destRegIdx[0]); 1606336Sgblack@eecs.umich.edu ss << ","; 1616336Sgblack@eecs.umich.edu } 1626336Sgblack@eecs.umich.edu 1636336Sgblack@eecs.umich.edu#ifdef SS_COMPATIBLE_DISASSEMBLY 1646336Sgblack@eecs.umich.edu if (_numSrcRegs == 0 && _numDestRegs == 0) { 1656336Sgblack@eecs.umich.edu printReg(ss, 31); 1666336Sgblack@eecs.umich.edu ss << ","; 1676336Sgblack@eecs.umich.edu } 1686336Sgblack@eecs.umich.edu#endif 1696336Sgblack@eecs.umich.edu 1706336Sgblack@eecs.umich.edu Addr target = pc + 4 + disp; 1716336Sgblack@eecs.umich.edu 1726336Sgblack@eecs.umich.edu std::string str; 1736336Sgblack@eecs.umich.edu if (symtab && symtab->findSymbol(target, str)) 1746336Sgblack@eecs.umich.edu ss << str; 1756336Sgblack@eecs.umich.edu else 1766336Sgblack@eecs.umich.edu ccprintf(ss, "0x%x", target); 1776336Sgblack@eecs.umich.edu 1786336Sgblack@eecs.umich.edu return ss.str(); 1796336Sgblack@eecs.umich.edu } 1806336Sgblack@eecs.umich.edu 1816336Sgblack@eecs.umich.edu std::string 1826336Sgblack@eecs.umich.edu Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1836336Sgblack@eecs.umich.edu { 1846336Sgblack@eecs.umich.edu std::stringstream ss; 1856336Sgblack@eecs.umich.edu 1866336Sgblack@eecs.umich.edu ccprintf(ss, "%-10s ", mnemonic); 1876336Sgblack@eecs.umich.edu 1886336Sgblack@eecs.umich.edu#ifdef SS_COMPATIBLE_DISASSEMBLY 1896336Sgblack@eecs.umich.edu if (_numDestRegs == 0) { 1906336Sgblack@eecs.umich.edu printReg(ss, 31); 1916336Sgblack@eecs.umich.edu ss << ","; 1926336Sgblack@eecs.umich.edu } 1936336Sgblack@eecs.umich.edu#endif 1946336Sgblack@eecs.umich.edu 1956336Sgblack@eecs.umich.edu if (_numDestRegs > 0) { 1966336Sgblack@eecs.umich.edu printReg(ss, _destRegIdx[0]); 1976336Sgblack@eecs.umich.edu ss << ","; 1986336Sgblack@eecs.umich.edu } 1996336Sgblack@eecs.umich.edu 2006336Sgblack@eecs.umich.edu ccprintf(ss, "(r%d)", RB); 2016336Sgblack@eecs.umich.edu 2026336Sgblack@eecs.umich.edu return ss.str(); 2036336Sgblack@eecs.umich.edu } 2046336Sgblack@eecs.umich.edu}}; 2056336Sgblack@eecs.umich.edu 2066336Sgblack@eecs.umich.edudef template JumpOrBranchDecode {{ 2076336Sgblack@eecs.umich.edu return (RA == 31) 2086336Sgblack@eecs.umich.edu ? (StaticInst *)new %(class_name)s(machInst) 2096336Sgblack@eecs.umich.edu : (StaticInst *)new %(class_name)sAndLink(machInst); 2106336Sgblack@eecs.umich.edu}}; 2116336Sgblack@eecs.umich.edu 2126336Sgblack@eecs.umich.edudef format CondBranch(code) {{ 2136336Sgblack@eecs.umich.edu code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; 2146336Sgblack@eecs.umich.edu iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 2156336Sgblack@eecs.umich.edu ('IsDirectControl', 'IsCondControl')) 2166336Sgblack@eecs.umich.edu header_output = BasicDeclare.subst(iop) 2176336Sgblack@eecs.umich.edu decoder_output = BasicConstructor.subst(iop) 2186336Sgblack@eecs.umich.edu decode_block = BasicDecode.subst(iop) 2196336Sgblack@eecs.umich.edu exec_output = BasicExecute.subst(iop) 2206336Sgblack@eecs.umich.edu}}; 2216336Sgblack@eecs.umich.edu 2226336Sgblack@eecs.umich.edulet {{ 2236336Sgblack@eecs.umich.edudef UncondCtrlBase(name, Name, base_class, npc_expr, flags): 2246336Sgblack@eecs.umich.edu # Declare basic control transfer w/o link (i.e. link reg is R31) 2256336Sgblack@eecs.umich.edu nolink_code = 'NPC = %s;\n' % npc_expr 2266336Sgblack@eecs.umich.edu nolink_iop = InstObjParams(name, Name, base_class, 2276336Sgblack@eecs.umich.edu CodeBlock(nolink_code), flags) 2286336Sgblack@eecs.umich.edu header_output = BasicDeclare.subst(nolink_iop) 2296336Sgblack@eecs.umich.edu decoder_output = BasicConstructor.subst(nolink_iop) 2306336Sgblack@eecs.umich.edu exec_output = BasicExecute.subst(nolink_iop) 2316336Sgblack@eecs.umich.edu 2326336Sgblack@eecs.umich.edu # Generate declaration of '*AndLink' version, append to decls 2336336Sgblack@eecs.umich.edu link_code = 'Ra = NPC & ~3;\n' + nolink_code 2346336Sgblack@eecs.umich.edu link_iop = InstObjParams(name, Name + 'AndLink', base_class, 2356336Sgblack@eecs.umich.edu CodeBlock(link_code), flags) 2366336Sgblack@eecs.umich.edu header_output += BasicDeclare.subst(link_iop) 2376336Sgblack@eecs.umich.edu decoder_output += BasicConstructor.subst(link_iop) 2386336Sgblack@eecs.umich.edu exec_output += BasicExecute.subst(link_iop) 2396336Sgblack@eecs.umich.edu 2406336Sgblack@eecs.umich.edu # need to use link_iop for the decode template since it is expecting 2416336Sgblack@eecs.umich.edu # the shorter version of class_name (w/o "AndLink") 2426336Sgblack@eecs.umich.edu 2436336Sgblack@eecs.umich.edu return (header_output, decoder_output, 2446336Sgblack@eecs.umich.edu JumpOrBranchDecode.subst(nolink_iop), exec_output) 2456336Sgblack@eecs.umich.edu}}; 2466336Sgblack@eecs.umich.edu 2476336Sgblack@eecs.umich.edudef format UncondBranch(*flags) {{ 2486336Sgblack@eecs.umich.edu flags += ('IsUncondControl', 'IsDirectControl') 2496336Sgblack@eecs.umich.edu (header_output, decoder_output, decode_block, exec_output) = \ 2506336Sgblack@eecs.umich.edu UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) 2516336Sgblack@eecs.umich.edu}}; 2526336Sgblack@eecs.umich.edu 2536336Sgblack@eecs.umich.edudef format Jump(*flags) {{ 2546336Sgblack@eecs.umich.edu flags += ('IsUncondControl', 'IsIndirectControl') 2556336Sgblack@eecs.umich.edu (header_output, decoder_output, decode_block, exec_output) = \ 2566336Sgblack@eecs.umich.edu UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) 2576336Sgblack@eecs.umich.edu}}; 2586336Sgblack@eecs.umich.edu 2596336Sgblack@eecs.umich.edu 2606336Sgblack@eecs.umich.edu