branch.isa revision 2687
12100SN/A// -*- mode:c++ -*- 22083SN/A 32089SN/A//////////////////////////////////////////////////////////////////// 42022SN/A// 52089SN/A// Control transfer instructions 62022SN/A// 72022SN/A 82022SN/Aoutput header {{ 92083SN/A 102239SN/A#include <iostream> 112239SN/A using namespace std; 122239SN/A 132083SN/A /** 142083SN/A * Base class for instructions whose disassembly is not purely a 152083SN/A * function of the machine instruction (i.e., it depends on the 162083SN/A * PC). This class overrides the disassemble() method to check 172083SN/A * the PC and symbol table values before re-using a cached 182083SN/A * disassembly string. This is necessary for branches and jumps, 192083SN/A * where the disassembly string includes the target address (which 202083SN/A * may depend on the PC and/or symbol table). 212083SN/A */ 222089SN/A class PCDependentDisassembly : public MipsStaticInst 232083SN/A { 242083SN/A protected: 252083SN/A /// Cached program counter from last disassembly 262083SN/A mutable Addr cachedPC; 272089SN/A 282083SN/A /// Cached symbol table pointer from last disassembly 292083SN/A mutable const SymbolTable *cachedSymtab; 302083SN/A 312083SN/A /// Constructor 322083SN/A PCDependentDisassembly(const char *mnem, MachInst _machInst, 332083SN/A OpClass __opClass) 342089SN/A : MipsStaticInst(mnem, _machInst, __opClass), 352083SN/A cachedPC(0), cachedSymtab(0) 362022SN/A { 372083SN/A } 382022SN/A 392083SN/A const std::string & 402083SN/A disassemble(Addr pc, const SymbolTable *symtab) const; 412083SN/A }; 422022SN/A 432083SN/A /** 442083SN/A * Base class for branches (PC-relative control transfers), 452083SN/A * conditional or unconditional. 462083SN/A */ 472083SN/A class Branch : public PCDependentDisassembly 482083SN/A { 492083SN/A protected: 502089SN/A /// target address (signed) Displacement . 512104SN/A int32_t disp; 522083SN/A 532083SN/A /// Constructor. 542083SN/A Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 552083SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 562104SN/A disp(OFFSET << 2) 572089SN/A { 582239SN/A //If Bit 17 is 1 then Sign Extend 592239SN/A if ( (disp & 0x00020000) > 0 ) { 602239SN/A disp |= 0xFFFE0000; 612239SN/A } 622089SN/A } 632089SN/A 642089SN/A Addr branchTarget(Addr branchPC) const; 652089SN/A 662089SN/A std::string 672089SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 682089SN/A }; 692089SN/A 702089SN/A /** 712083SN/A * Base class for jumps (register-indirect control transfers). In 722089SN/A * the Mips ISA, these are always unconditional. 732083SN/A */ 742083SN/A class Jump : public PCDependentDisassembly 752083SN/A { 762083SN/A protected: 772083SN/A 782083SN/A /// Displacement to target address (signed). 792083SN/A int32_t disp; 802083SN/A 812239SN/A uint32_t target; 822239SN/A 832083SN/A public: 842083SN/A /// Constructor 852083SN/A Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 862083SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 872239SN/A disp(JMPTARG << 2) 882083SN/A { 892083SN/A } 902083SN/A 912687Sksewell@umich.edu Addr branchTarget(ThreadContext *tc) const; 922083SN/A 932083SN/A std::string 942083SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 952083SN/A }; 962022SN/A}}; 972022SN/A 982022SN/Aoutput decoder {{ 992083SN/A Addr 1002083SN/A Branch::branchTarget(Addr branchPC) const 1012083SN/A { 1022083SN/A return branchPC + 4 + disp; 1032083SN/A } 1042083SN/A 1052083SN/A Addr 1062687Sksewell@umich.edu Jump::branchTarget(ThreadContext *tc) const 1072083SN/A { 1082687Sksewell@umich.edu Addr NPC = tc->readPC() + 4; 1092687Sksewell@umich.edu uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); 1102083SN/A return (Rb & ~3) | (NPC & 1); 1112083SN/A } 1122083SN/A 1132083SN/A const std::string & 1142083SN/A PCDependentDisassembly::disassemble(Addr pc, 1152083SN/A const SymbolTable *symtab) const 1162083SN/A { 1172083SN/A if (!cachedDisassembly || 1182083SN/A pc != cachedPC || symtab != cachedSymtab) 1192022SN/A { 1202083SN/A if (cachedDisassembly) 1212083SN/A delete cachedDisassembly; 1222083SN/A 1232083SN/A cachedDisassembly = 1242083SN/A new std::string(generateDisassembly(pc, symtab)); 1252083SN/A cachedPC = pc; 1262083SN/A cachedSymtab = symtab; 1272022SN/A } 1282083SN/A 1292083SN/A return *cachedDisassembly; 1302083SN/A } 1312083SN/A 1322083SN/A std::string 1332083SN/A Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1342083SN/A { 1352083SN/A std::stringstream ss; 1362083SN/A 1372083SN/A ccprintf(ss, "%-10s ", mnemonic); 1382083SN/A 1392083SN/A // There's only one register arg (RA), but it could be 1402083SN/A // either a source (the condition for conditional 1412083SN/A // branches) or a destination (the link reg for 1422083SN/A // unconditional branches) 1432239SN/A if (_numSrcRegs == 1) { 1442083SN/A printReg(ss, _srcRegIdx[0]); 1452686Sksewell@umich.edu ss << ", "; 1462239SN/A } else if(_numSrcRegs == 2) { 1472239SN/A printReg(ss, _srcRegIdx[0]); 1482686Sksewell@umich.edu ss << ", "; 1492239SN/A printReg(ss, _srcRegIdx[1]); 1502686Sksewell@umich.edu ss << ", "; 1512103SN/A } 1522103SN/A 1532103SN/A Addr target = pc + 4 + disp; 1542103SN/A 1552103SN/A std::string str; 1562103SN/A if (symtab && symtab->findSymbol(target, str)) 1572103SN/A ss << str; 1582103SN/A else 1592103SN/A ccprintf(ss, "0x%x", target); 1602103SN/A 1612103SN/A return ss.str(); 1622103SN/A } 1632103SN/A 1642103SN/A std::string 1652083SN/A Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1662083SN/A { 1672083SN/A std::stringstream ss; 1682083SN/A 1692083SN/A ccprintf(ss, "%-10s ", mnemonic); 1702083SN/A 1712239SN/A if ( mnemonic == "jal" ) { 1722239SN/A Addr npc = pc + 4; 1732239SN/A ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); 1742239SN/A } else if (_numSrcRegs == 0) { 1752239SN/A std::string str; 1762239SN/A if (symtab && symtab->findSymbol(disp, str)) 1772239SN/A ss << str; 1782239SN/A else 1792239SN/A ccprintf(ss, "0x%x", disp); 1802239SN/A } else if (_numSrcRegs == 1) { 1812239SN/A printReg(ss, _srcRegIdx[0]); 1822239SN/A } else if(_numSrcRegs == 2) { 1832239SN/A printReg(ss, _srcRegIdx[0]); 1842686Sksewell@umich.edu ss << ", "; 1852239SN/A printReg(ss, _srcRegIdx[1]); 1862083SN/A } 1872083SN/A 1882083SN/A return ss.str(); 1892083SN/A } 1902022SN/A}}; 1912022SN/A 1922686Sksewell@umich.edudef format Branch(code,*opt_flags) {{ 1932686Sksewell@umich.edu not_taken_code = ' NNPC = NNPC;\n' 1942686Sksewell@umich.edu not_taken_code += '} \n' 1952686Sksewell@umich.edu 1962686Sksewell@umich.edu #Build Instruction Flags 1972686Sksewell@umich.edu #Use Link & Likely Flags to Add Link/Condition Code 1982686Sksewell@umich.edu inst_flags = ('IsDirectControl', ) 1992686Sksewell@umich.edu for x in opt_flags: 2002686Sksewell@umich.edu if x == 'Link': 2012686Sksewell@umich.edu code += 'R31 = NNPC;\n' 2022686Sksewell@umich.edu elif x == 'Likely': 2032686Sksewell@umich.edu not_taken_code = ' NPC = NNPC;\n' 2042686Sksewell@umich.edu not_taken_code += ' NNPC = NNPC + 4;\n' 2052686Sksewell@umich.edu not_taken_code += '} \n' 2062686Sksewell@umich.edu inst_flags = ('IsCondDelaySlot', ) 2072686Sksewell@umich.edu else: 2082686Sksewell@umich.edu inst_flags += (x, ) 2092686Sksewell@umich.edu 2102686Sksewell@umich.edu if 'cond == 1' in code: 2112686Sksewell@umich.edu inst_flags += ('IsCondControl', ) 2122686Sksewell@umich.edu else: 2132686Sksewell@umich.edu inst_flags += ('IsUncondControl', ) 2142101SN/A 2152123SN/A #Condition code 2162123SN/A code = 'bool cond;\n' + code 2172123SN/A code += 'if (cond) {\n' 2182123SN/A code += ' NNPC = NPC + disp;\n' 2192239SN/A code += '} else {\n' 2202686Sksewell@umich.edu code += not_taken_code 2212101SN/A 2222686Sksewell@umich.edu iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), inst_flags) 2232047SN/A header_output = BasicDeclare.subst(iop) 2242047SN/A decoder_output = BasicConstructor.subst(iop) 2252047SN/A decode_block = BasicDecode.subst(iop) 2262047SN/A exec_output = BasicExecute.subst(iop) 2272022SN/A}}; 2282047SN/A 2292686Sksewell@umich.edudef format Jump(code, *opt_flags) {{ 2302686Sksewell@umich.edu #Build Instruction Flags 2312686Sksewell@umich.edu #Use Link Flag to Add Link Code 2322686Sksewell@umich.edu inst_flags = ('IsIndirectControl', 'IsUncondControl') 2332686Sksewell@umich.edu for x in opt_flags: 2342686Sksewell@umich.edu if x == 'Link': 2352686Sksewell@umich.edu code = 'R31 = NNPC;\n' + code 2362686Sksewell@umich.edu elif x == 'ClearHazards': 2372686Sksewell@umich.edu code += '/* Code Needed to Clear Execute & Inst Hazards */\n' 2382686Sksewell@umich.edu else: 2392686Sksewell@umich.edu inst_flags += (x, ) 2402104SN/A 2412686Sksewell@umich.edu iop = InstObjParams(name, Name, 'Jump', CodeBlock(code), inst_flags) 2422089SN/A header_output = BasicDeclare.subst(iop) 2432089SN/A decoder_output = BasicConstructor.subst(iop) 2442089SN/A decode_block = BasicDecode.subst(iop) 2452089SN/A exec_output = BasicExecute.subst(iop) 2462089SN/A}}; 2472083SN/A 2482239SN/A 2492123SN/A 2502123SN/A 251