branch.isa revision 5222
12100SN/A// -*- mode:c++ -*- 22083SN/A 35222Sksewell@umich.edu// Copyright .AN) 2007 MIPS Technologies, Inc. All Rights Reserved 45222Sksewell@umich.edu 55222Sksewell@umich.edu// This software is part of the M5 simulator. 65222Sksewell@umich.edu 75222Sksewell@umich.edu// THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING 85222Sksewell@umich.edu// DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING 95222Sksewell@umich.edu// TO THESE TERMS AND CONDITIONS. 105222Sksewell@umich.edu 115222Sksewell@umich.edu// Permission is granted to use, copy, create derivative works and 125222Sksewell@umich.edu// distribute this software and such derivative works for any purpose, 135222Sksewell@umich.edu// so long as (1) the copyright notice above, this grant of permission, 145222Sksewell@umich.edu// and the disclaimer below appear in all copies and derivative works 155222Sksewell@umich.edu// made, (2) the copyright notice above is augmented as appropriate to 165222Sksewell@umich.edu// reflect the addition of any new copyrightable work in a derivative 175222Sksewell@umich.edu// work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3) 185222Sksewell@umich.edu// the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any 195222Sksewell@umich.edu// advertising or publicity pertaining to the use or distribution of 205222Sksewell@umich.edu// this software without specific, written prior authorization. 215222Sksewell@umich.edu 225222Sksewell@umich.edu// THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B MIPS MAKES NO WARRANTIES AND 235222Sksewell@umich.edu// DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR 245222Sksewell@umich.edu// OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 255222Sksewell@umich.edu// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 265222Sksewell@umich.edu// NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE. 275222Sksewell@umich.edu// IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, 285222Sksewell@umich.edu// INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF 295222Sksewell@umich.edu// ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, 305222Sksewell@umich.edu// THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY 315222Sksewell@umich.edu// IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR 325222Sksewell@umich.edu// STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE 335222Sksewell@umich.edu// POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE. 345222Sksewell@umich.edu 355222Sksewell@umich.edu//Authors: Korey L. Sewell 362706Sksewell@umich.edu 372089SN/A//////////////////////////////////////////////////////////////////// 382022SN/A// 392089SN/A// Control transfer instructions 402022SN/A// 412022SN/A 422022SN/Aoutput header {{ 432083SN/A 442239SN/A#include <iostream> 454661Sksewell@umich.edu using namespace std; 462239SN/A 472083SN/A /** 482083SN/A * Base class for instructions whose disassembly is not purely a 492083SN/A * function of the machine instruction (i.e., it depends on the 502083SN/A * PC). This class overrides the disassemble() method to check 512083SN/A * the PC and symbol table values before re-using a cached 522083SN/A * disassembly string. This is necessary for branches and jumps, 532083SN/A * where the disassembly string includes the target address (which 542083SN/A * may depend on the PC and/or symbol table). 552083SN/A */ 562089SN/A class PCDependentDisassembly : public MipsStaticInst 572083SN/A { 582083SN/A protected: 592083SN/A /// Cached program counter from last disassembly 602083SN/A mutable Addr cachedPC; 612089SN/A 622083SN/A /// Cached symbol table pointer from last disassembly 632083SN/A mutable const SymbolTable *cachedSymtab; 642083SN/A 652083SN/A /// Constructor 662083SN/A PCDependentDisassembly(const char *mnem, MachInst _machInst, 672083SN/A OpClass __opClass) 682089SN/A : MipsStaticInst(mnem, _machInst, __opClass), 692083SN/A cachedPC(0), cachedSymtab(0) 702022SN/A { 712083SN/A } 722022SN/A 732083SN/A const std::string & 742083SN/A disassemble(Addr pc, const SymbolTable *symtab) const; 752083SN/A }; 762022SN/A 772083SN/A /** 782083SN/A * Base class for branches (PC-relative control transfers), 792083SN/A * conditional or unconditional. 802083SN/A */ 812083SN/A class Branch : public PCDependentDisassembly 822083SN/A { 832083SN/A protected: 842089SN/A /// target address (signed) Displacement . 852104SN/A int32_t disp; 862083SN/A 872083SN/A /// Constructor. 882083SN/A Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 892083SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 902104SN/A disp(OFFSET << 2) 912089SN/A { 922239SN/A //If Bit 17 is 1 then Sign Extend 932239SN/A if ( (disp & 0x00020000) > 0 ) { 942239SN/A disp |= 0xFFFE0000; 952239SN/A } 962089SN/A } 972089SN/A 982089SN/A Addr branchTarget(Addr branchPC) const; 992089SN/A 1002089SN/A std::string 1012089SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1022089SN/A }; 1032089SN/A 1042089SN/A /** 1052083SN/A * Base class for jumps (register-indirect control transfers). In 1062089SN/A * the Mips ISA, these are always unconditional. 1072083SN/A */ 1082083SN/A class Jump : public PCDependentDisassembly 1092083SN/A { 1102083SN/A protected: 1112083SN/A 1122083SN/A /// Displacement to target address (signed). 1132083SN/A int32_t disp; 1142083SN/A 1152239SN/A uint32_t target; 1162239SN/A 1172083SN/A public: 1182083SN/A /// Constructor 1192083SN/A Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 1202083SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 1212239SN/A disp(JMPTARG << 2) 1222083SN/A { 1232083SN/A } 1242083SN/A 1252687Sksewell@umich.edu Addr branchTarget(ThreadContext *tc) const; 1262083SN/A 1272083SN/A std::string 1282083SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1292083SN/A }; 1302022SN/A}}; 1312022SN/A 1322022SN/Aoutput decoder {{ 1332083SN/A Addr 1342083SN/A Branch::branchTarget(Addr branchPC) const 1352083SN/A { 1362083SN/A return branchPC + 4 + disp; 1372083SN/A } 1382083SN/A 1392083SN/A Addr 1402687Sksewell@umich.edu Jump::branchTarget(ThreadContext *tc) const 1412083SN/A { 1425222Sksewell@umich.edu Addr NPC = tc->readNextPC(); 1435222Sksewell@umich.edu return (NPC & 0xF0000000) | (disp); 1442083SN/A } 1452083SN/A 1462083SN/A const std::string & 1472083SN/A PCDependentDisassembly::disassemble(Addr pc, 1482083SN/A const SymbolTable *symtab) const 1492083SN/A { 1502083SN/A if (!cachedDisassembly || 1512083SN/A pc != cachedPC || symtab != cachedSymtab) 1522022SN/A { 1532083SN/A if (cachedDisassembly) 1542083SN/A delete cachedDisassembly; 1552083SN/A 1562083SN/A cachedDisassembly = 1572083SN/A new std::string(generateDisassembly(pc, symtab)); 1582083SN/A cachedPC = pc; 1592083SN/A cachedSymtab = symtab; 1602022SN/A } 1612083SN/A 1622083SN/A return *cachedDisassembly; 1632083SN/A } 1642083SN/A 1652083SN/A std::string 1662083SN/A Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1672083SN/A { 1682083SN/A std::stringstream ss; 1692083SN/A 1702083SN/A ccprintf(ss, "%-10s ", mnemonic); 1712083SN/A 1722083SN/A // There's only one register arg (RA), but it could be 1732083SN/A // either a source (the condition for conditional 1742083SN/A // branches) or a destination (the link reg for 1752083SN/A // unconditional branches) 1762239SN/A if (_numSrcRegs == 1) { 1772083SN/A printReg(ss, _srcRegIdx[0]); 1782686Sksewell@umich.edu ss << ", "; 1792239SN/A } else if(_numSrcRegs == 2) { 1802239SN/A printReg(ss, _srcRegIdx[0]); 1812686Sksewell@umich.edu ss << ", "; 1822239SN/A printReg(ss, _srcRegIdx[1]); 1832686Sksewell@umich.edu ss << ", "; 1842103SN/A } 1852103SN/A 1862103SN/A Addr target = pc + 4 + disp; 1872103SN/A 1882103SN/A std::string str; 1892103SN/A if (symtab && symtab->findSymbol(target, str)) 1902103SN/A ss << str; 1912103SN/A else 1922103SN/A ccprintf(ss, "0x%x", target); 1932103SN/A 1942103SN/A return ss.str(); 1952103SN/A } 1962103SN/A 1972103SN/A std::string 1982083SN/A Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1992083SN/A { 2002083SN/A std::stringstream ss; 2012083SN/A 2022083SN/A ccprintf(ss, "%-10s ", mnemonic); 2032083SN/A 2045222Sksewell@umich.edu if ( mnemonic == "jal" ) { 2052239SN/A Addr npc = pc + 4; 2062239SN/A ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); 2072239SN/A } else if (_numSrcRegs == 0) { 2082239SN/A std::string str; 2092239SN/A if (symtab && symtab->findSymbol(disp, str)) 2102239SN/A ss << str; 2112239SN/A else 2122239SN/A ccprintf(ss, "0x%x", disp); 2132239SN/A } else if (_numSrcRegs == 1) { 2142239SN/A printReg(ss, _srcRegIdx[0]); 2152239SN/A } else if(_numSrcRegs == 2) { 2162239SN/A printReg(ss, _srcRegIdx[0]); 2172686Sksewell@umich.edu ss << ", "; 2182239SN/A printReg(ss, _srcRegIdx[1]); 2192083SN/A } 2202083SN/A 2212083SN/A return ss.str(); 2222083SN/A } 2232022SN/A}}; 2242022SN/A 2254661Sksewell@umich.edudef format Branch(code, *opt_flags) {{ 2262686Sksewell@umich.edu not_taken_code = ' NNPC = NNPC;\n' 2272686Sksewell@umich.edu not_taken_code += '} \n' 2282686Sksewell@umich.edu 2292686Sksewell@umich.edu #Build Instruction Flags 2302686Sksewell@umich.edu #Use Link & Likely Flags to Add Link/Condition Code 2312686Sksewell@umich.edu inst_flags = ('IsDirectControl', ) 2322686Sksewell@umich.edu for x in opt_flags: 2332686Sksewell@umich.edu if x == 'Link': 2342686Sksewell@umich.edu code += 'R31 = NNPC;\n' 2352686Sksewell@umich.edu elif x == 'Likely': 2362686Sksewell@umich.edu not_taken_code = ' NPC = NNPC;\n' 2372686Sksewell@umich.edu not_taken_code += ' NNPC = NNPC + 4;\n' 2382686Sksewell@umich.edu not_taken_code += '} \n' 2394661Sksewell@umich.edu inst_flags += ('IsCondDelaySlot', ) 2402686Sksewell@umich.edu else: 2412686Sksewell@umich.edu inst_flags += (x, ) 2422686Sksewell@umich.edu 2432935Sksewell@umich.edu #Take into account uncond. branch instruction 2444661Sksewell@umich.edu if 'cond = 1' in code: 2454661Sksewell@umich.edu inst_flags += ('IsUncondControl', ) 2462935Sksewell@umich.edu else: 2472686Sksewell@umich.edu inst_flags += ('IsCondControl', ) 2482101SN/A 2492123SN/A #Condition code 2502123SN/A code = 'bool cond;\n' + code 2512123SN/A code += 'if (cond) {\n' 2522123SN/A code += ' NNPC = NPC + disp;\n' 2532239SN/A code += '} else {\n' 2542686Sksewell@umich.edu code += not_taken_code 2552101SN/A 2563951Sgblack@eecs.umich.edu iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 2572047SN/A header_output = BasicDeclare.subst(iop) 2582047SN/A decoder_output = BasicConstructor.subst(iop) 2592047SN/A decode_block = BasicDecode.subst(iop) 2602047SN/A exec_output = BasicExecute.subst(iop) 2612022SN/A}}; 2622047SN/A 2634661Sksewell@umich.edudef format DspBranch(code, *opt_flags) {{ 2644661Sksewell@umich.edu not_taken_code = ' NNPC = NNPC;\n' 2654661Sksewell@umich.edu not_taken_code += '} \n' 2664661Sksewell@umich.edu 2674661Sksewell@umich.edu #Build Instruction Flags 2684661Sksewell@umich.edu #Use Link & Likely Flags to Add Link/Condition Code 2694661Sksewell@umich.edu inst_flags = ('IsDirectControl', ) 2704661Sksewell@umich.edu for x in opt_flags: 2714661Sksewell@umich.edu if x == 'Link': 2724661Sksewell@umich.edu code += 'R31 = NNPC;\n' 2734661Sksewell@umich.edu elif x == 'Likely': 2744661Sksewell@umich.edu not_taken_code = ' NPC = NNPC;\n' 2754661Sksewell@umich.edu not_taken_code += ' NNPC = NNPC + 4;\n' 2764661Sksewell@umich.edu not_taken_code += '} \n' 2774661Sksewell@umich.edu inst_flags += ('IsCondDelaySlot', ) 2784661Sksewell@umich.edu else: 2794661Sksewell@umich.edu inst_flags += (x, ) 2804661Sksewell@umich.edu 2814661Sksewell@umich.edu #Take into account uncond. branch instruction 2824661Sksewell@umich.edu if 'cond = 1' in code: 2834661Sksewell@umich.edu inst_flags += ('IsUncondControl', ) 2844661Sksewell@umich.edu else: 2854661Sksewell@umich.edu inst_flags += ('IsCondControl', ) 2864661Sksewell@umich.edu 2874661Sksewell@umich.edu #Declaration code 2884661Sksewell@umich.edu decl_code = 'bool cond;\n' 2894661Sksewell@umich.edu decl_code += 'uint32_t dspctl;\n' 2904661Sksewell@umich.edu 2914661Sksewell@umich.edu #Fetch code 2924661Sksewell@umich.edu fetch_code = 'dspctl = DSPControl;\n' 2934661Sksewell@umich.edu 2944661Sksewell@umich.edu #Condition code 2954661Sksewell@umich.edu code = decl_code + fetch_code + code 2964661Sksewell@umich.edu code += 'if (cond) {\n' 2974661Sksewell@umich.edu code += ' NNPC = NPC + disp;\n' 2984661Sksewell@umich.edu code += '} else {\n' 2994661Sksewell@umich.edu code += not_taken_code 3004661Sksewell@umich.edu 3014661Sksewell@umich.edu iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 3024661Sksewell@umich.edu header_output = BasicDeclare.subst(iop) 3034661Sksewell@umich.edu decoder_output = BasicConstructor.subst(iop) 3044661Sksewell@umich.edu decode_block = BasicDecode.subst(iop) 3054661Sksewell@umich.edu exec_output = BasicExecute.subst(iop) 3064661Sksewell@umich.edu}}; 3074661Sksewell@umich.edu 3082686Sksewell@umich.edudef format Jump(code, *opt_flags) {{ 3092686Sksewell@umich.edu #Build Instruction Flags 3102686Sksewell@umich.edu #Use Link Flag to Add Link Code 3112686Sksewell@umich.edu inst_flags = ('IsIndirectControl', 'IsUncondControl') 3122686Sksewell@umich.edu for x in opt_flags: 3132686Sksewell@umich.edu if x == 'Link': 3142686Sksewell@umich.edu code = 'R31 = NNPC;\n' + code 3152686Sksewell@umich.edu elif x == 'ClearHazards': 3162686Sksewell@umich.edu code += '/* Code Needed to Clear Execute & Inst Hazards */\n' 3172686Sksewell@umich.edu else: 3182686Sksewell@umich.edu inst_flags += (x, ) 3192104SN/A 3203951Sgblack@eecs.umich.edu iop = InstObjParams(name, Name, 'Jump', code, inst_flags) 3212089SN/A header_output = BasicDeclare.subst(iop) 3222089SN/A decoder_output = BasicConstructor.subst(iop) 3232089SN/A decode_block = BasicDecode.subst(iop) 3242089SN/A exec_output = BasicExecute.subst(iop) 3252089SN/A}}; 3262083SN/A 3272239SN/A 3282123SN/A 3292123SN/A 330