branch.isa revision 2701:38218635db4c
19243SN/A// -*- mode:c++ -*- 211675Swendy.elsasser@arm.com 39243SN/A//////////////////////////////////////////////////////////////////// 49243SN/A// 59243SN/A// Control transfer instructions 69243SN/A// 79243SN/A 89243SN/Aoutput header {{ 99243SN/A 109243SN/A#include <iostream> 119243SN/A using namespace std; 129243SN/A 139243SN/A /** 149831SN/A * Base class for instructions whose disassembly is not purely a 159831SN/A * function of the machine instruction (i.e., it depends on the 169831SN/A * PC). This class overrides the disassemble() method to check 179243SN/A * the PC and symbol table values before re-using a cached 189243SN/A * disassembly string. This is necessary for branches and jumps, 199243SN/A * where the disassembly string includes the target address (which 209243SN/A * may depend on the PC and/or symbol table). 219243SN/A */ 229243SN/A class PCDependentDisassembly : public MipsStaticInst 239243SN/A { 249243SN/A protected: 259243SN/A /// Cached program counter from last disassembly 269243SN/A mutable Addr cachedPC; 279243SN/A 289243SN/A /// Cached symbol table pointer from last disassembly 299243SN/A mutable const SymbolTable *cachedSymtab; 309243SN/A 319243SN/A /// Constructor 329243SN/A PCDependentDisassembly(const char *mnem, MachInst _machInst, 339243SN/A OpClass __opClass) 349243SN/A : MipsStaticInst(mnem, _machInst, __opClass), 359243SN/A cachedPC(0), cachedSymtab(0) 369243SN/A { 379243SN/A } 389243SN/A 399243SN/A const std::string & 409243SN/A disassemble(Addr pc, const SymbolTable *symtab) const; 419243SN/A }; 429967SN/A 4310618SOmar.Naji@arm.com /** 4411678Swendy.elsasser@arm.com * Base class for branches (PC-relative control transfers), 459243SN/A * conditional or unconditional. 469243SN/A */ 4710146Sandreas.hansson@arm.com class Branch : public PCDependentDisassembly 489356SN/A { 4910146Sandreas.hansson@arm.com protected: 5010247Sandreas.hansson@arm.com /// target address (signed) Displacement . 5110208Sandreas.hansson@arm.com int32_t disp; 529352SN/A 5310146Sandreas.hansson@arm.com /// Constructor. 549814SN/A Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 559243SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 569243SN/A disp(OFFSET << 2) 5710432SOmar.Naji@arm.com { 589243SN/A //If Bit 17 is 1 then Sign Extend 5910146Sandreas.hansson@arm.com if ( (disp & 0x00020000) > 0 ) { 609243SN/A disp |= 0xFFFE0000; 6110619Sandreas.hansson@arm.com } 629243SN/A } 6310211Sandreas.hansson@arm.com 6411678Swendy.elsasser@arm.com Addr branchTarget(Addr branchPC) const; 6510618SOmar.Naji@arm.com 6610489SOmar.Naji@arm.com std::string 679831SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 689831SN/A }; 699831SN/A 709831SN/A /** 719831SN/A * Base class for branch likely branches (PC-relative control transfers), 7210140SN/A */ 7310646Sandreas.hansson@arm.com class BranchLikely : public PCDependentDisassembly 749243SN/A { 7510394Swendy.elsasser@arm.com protected: 7610394Swendy.elsasser@arm.com /// target address (signed) Displacement . 779566SN/A int32_t disp; 789243SN/A 799243SN/A /// Constructor. 8010140SN/A BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass) 8110140SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 8210147Sandreas.hansson@arm.com disp(OFFSET << 2) 8310147Sandreas.hansson@arm.com { 8410393Swendy.elsasser@arm.com 8510394Swendy.elsasser@arm.com } 8610394Swendy.elsasser@arm.com 8711673SOmar.Naji@arm.com Addr branchTarget(Addr branchPC) const; 8811673SOmar.Naji@arm.com 899243SN/A std::string 909243SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 9110141SN/A }; 929726SN/A 939726SN/A /** 9410618SOmar.Naji@arm.com * Base class for jumps (register-indirect control transfers). In 9510618SOmar.Naji@arm.com * the Mips ISA, these are always unconditional. 969243SN/A */ 9710620Sandreas.hansson@arm.com class Jump : public PCDependentDisassembly 9810620Sandreas.hansson@arm.com { 9910620Sandreas.hansson@arm.com protected: 10010620Sandreas.hansson@arm.com 10110620Sandreas.hansson@arm.com /// Displacement to target address (signed). 10210889Sandreas.hansson@arm.com int32_t disp; 10310889Sandreas.hansson@arm.com 10410889Sandreas.hansson@arm.com uint32_t target; 10510618SOmar.Naji@arm.com 10610618SOmar.Naji@arm.com public: 10710618SOmar.Naji@arm.com /// Constructor 10810432SOmar.Naji@arm.com Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 10910618SOmar.Naji@arm.com : PCDependentDisassembly(mnem, _machInst, __opClass), 11010618SOmar.Naji@arm.com disp(JMPTARG << 2) 11110618SOmar.Naji@arm.com { 11210432SOmar.Naji@arm.com } 11310246Sandreas.hansson@arm.com 11410618SOmar.Naji@arm.com Addr branchTarget(ThreadContext *tc) const; 11510561SOmar.Naji@arm.com 11610561SOmar.Naji@arm.com std::string 11710561SOmar.Naji@arm.com generateDisassembly(Addr pc, const SymbolTable *symtab) const; 11810394Swendy.elsasser@arm.com }; 11910394Swendy.elsasser@arm.com}}; 12010394Swendy.elsasser@arm.com 12110394Swendy.elsasser@arm.comoutput decoder {{ 12210394Swendy.elsasser@arm.com Addr 12310394Swendy.elsasser@arm.com Branch::branchTarget(Addr branchPC) const 12410394Swendy.elsasser@arm.com { 12510394Swendy.elsasser@arm.com return branchPC + 4 + disp; 12610618SOmar.Naji@arm.com } 12710394Swendy.elsasser@arm.com 12810394Swendy.elsasser@arm.com Addr 12910618SOmar.Naji@arm.com BranchLikely::branchTarget(Addr branchPC) const 13010394Swendy.elsasser@arm.com { 13110246Sandreas.hansson@arm.com return branchPC + 4 + disp; 13210246Sandreas.hansson@arm.com } 13310246Sandreas.hansson@arm.com 13410140SN/A Addr 13510140SN/A Jump::branchTarget(ThreadContext *tc) const 13610140SN/A { 13710140SN/A Addr NPC = tc->readPC() + 4; 13810140SN/A uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); 1399243SN/A return (Rb & ~3) | (NPC & 1); 1409243SN/A } 1419567SN/A 1429243SN/A const std::string & 14310489SOmar.Naji@arm.com PCDependentDisassembly::disassemble(Addr pc, 14410489SOmar.Naji@arm.com const SymbolTable *symtab) const 14510489SOmar.Naji@arm.com { 14610489SOmar.Naji@arm.com if (!cachedDisassembly || 14710489SOmar.Naji@arm.com pc != cachedPC || symtab != cachedSymtab) 14810489SOmar.Naji@arm.com { 14910489SOmar.Naji@arm.com if (cachedDisassembly) 15010489SOmar.Naji@arm.com delete cachedDisassembly; 15110489SOmar.Naji@arm.com 15210489SOmar.Naji@arm.com cachedDisassembly = 1539243SN/A new std::string(generateDisassembly(pc, symtab)); 1549243SN/A cachedPC = pc; 1559831SN/A cachedSymtab = symtab; 1569831SN/A } 1579831SN/A 1589831SN/A return *cachedDisassembly; 1599831SN/A } 1609243SN/A 16110207Sandreas.hansson@arm.com std::string 16210207Sandreas.hansson@arm.com Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 16310207Sandreas.hansson@arm.com { 16410207Sandreas.hansson@arm.com std::stringstream ss; 16510207Sandreas.hansson@arm.com 16610394Swendy.elsasser@arm.com ccprintf(ss, "%-10s ", mnemonic); 16710394Swendy.elsasser@arm.com 16810394Swendy.elsasser@arm.com // There's only one register arg (RA), but it could be 16910394Swendy.elsasser@arm.com // either a source (the condition for conditional 17010394Swendy.elsasser@arm.com // branches) or a destination (the link reg for 17110394Swendy.elsasser@arm.com // unconditional branches) 17210394Swendy.elsasser@arm.com if (_numSrcRegs == 1) { 17310394Swendy.elsasser@arm.com printReg(ss, _srcRegIdx[0]); 17410394Swendy.elsasser@arm.com ss << ","; 17510394Swendy.elsasser@arm.com } else if(_numSrcRegs == 2) { 17610394Swendy.elsasser@arm.com printReg(ss, _srcRegIdx[0]); 17710394Swendy.elsasser@arm.com ss << ","; 17810394Swendy.elsasser@arm.com printReg(ss, _srcRegIdx[1]); 17910394Swendy.elsasser@arm.com ss << ","; 18010394Swendy.elsasser@arm.com } 18110394Swendy.elsasser@arm.com 18210394Swendy.elsasser@arm.com Addr target = pc + 4 + disp; 18310394Swendy.elsasser@arm.com 18410394Swendy.elsasser@arm.com std::string str; 18510394Swendy.elsasser@arm.com if (symtab && symtab->findSymbol(target, str)) 18610394Swendy.elsasser@arm.com ss << str; 18710394Swendy.elsasser@arm.com else 18810561SOmar.Naji@arm.com ccprintf(ss, "0x%x", target); 18910561SOmar.Naji@arm.com 19010394Swendy.elsasser@arm.com string inst_name = mnemonic; 19110394Swendy.elsasser@arm.com 19210394Swendy.elsasser@arm.com if (inst_name.substr(inst_name.length()-2,inst_name.length()) == "al"){ 19310394Swendy.elsasser@arm.com ccprintf(ss, " (r31=0x%x)",pc+8); 19410394Swendy.elsasser@arm.com } 19510394Swendy.elsasser@arm.com 1969243SN/A return ss.str(); 1979243SN/A } 1989243SN/A 19910146Sandreas.hansson@arm.com std::string 20010140SN/A BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const 20110466Sandreas.hansson@arm.com { 20210466Sandreas.hansson@arm.com std::stringstream ss; 20310466Sandreas.hansson@arm.com 20410146Sandreas.hansson@arm.com ccprintf(ss, "%-10s ", mnemonic); 20510140SN/A 20610140SN/A // There's only one register arg (RA), but it could be 20710140SN/A // either a source (the condition for conditional 20810646Sandreas.hansson@arm.com // branches) or a destination (the link reg for 20910646Sandreas.hansson@arm.com // unconditional branches) 21010646Sandreas.hansson@arm.com if (_numSrcRegs > 0) { 21110646Sandreas.hansson@arm.com printReg(ss, _srcRegIdx[0]); 21210646Sandreas.hansson@arm.com ss << ","; 21310646Sandreas.hansson@arm.com } 21410646Sandreas.hansson@arm.com else if (_numDestRegs > 0) { 21510646Sandreas.hansson@arm.com printReg(ss, _destRegIdx[0]); 21610646Sandreas.hansson@arm.com ss << ","; 21710646Sandreas.hansson@arm.com } 21810646Sandreas.hansson@arm.com 21910646Sandreas.hansson@arm.com Addr target = pc + 4 + disp; 22010646Sandreas.hansson@arm.com 22110646Sandreas.hansson@arm.com std::string str; 22210646Sandreas.hansson@arm.com if (symtab && symtab->findSymbol(target, str)) 22310646Sandreas.hansson@arm.com ss << str; 22410646Sandreas.hansson@arm.com else 22510646Sandreas.hansson@arm.com ccprintf(ss, "0x%x", target); 22610646Sandreas.hansson@arm.com 22710646Sandreas.hansson@arm.com return ss.str(); 22810646Sandreas.hansson@arm.com } 22910646Sandreas.hansson@arm.com 23010646Sandreas.hansson@arm.com std::string 23110646Sandreas.hansson@arm.com Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 23210646Sandreas.hansson@arm.com { 23310646Sandreas.hansson@arm.com std::stringstream ss; 23410646Sandreas.hansson@arm.com 23510646Sandreas.hansson@arm.com ccprintf(ss, "%-10s ", mnemonic); 23610646Sandreas.hansson@arm.com 23710646Sandreas.hansson@arm.com if ( mnemonic == "jal" ) { 23810646Sandreas.hansson@arm.com Addr npc = pc + 4; 23910646Sandreas.hansson@arm.com ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); 24010646Sandreas.hansson@arm.com } else if (_numSrcRegs == 0) { 24110646Sandreas.hansson@arm.com std::string str; 24210646Sandreas.hansson@arm.com if (symtab && symtab->findSymbol(disp, str)) 24310646Sandreas.hansson@arm.com ss << str; 24410646Sandreas.hansson@arm.com else 24510646Sandreas.hansson@arm.com ccprintf(ss, "0x%x", disp); 24610646Sandreas.hansson@arm.com } else if (_numSrcRegs == 1) { 24710646Sandreas.hansson@arm.com printReg(ss, _srcRegIdx[0]); 24810140SN/A } else if(_numSrcRegs == 2) { 24910140SN/A printReg(ss, _srcRegIdx[0]); 25010140SN/A ss << ","; 25110146Sandreas.hansson@arm.com printReg(ss, _srcRegIdx[1]); 2529243SN/A } else { 25310619Sandreas.hansson@arm.com panic(">= 3 Source Registers!!!"); 25410619Sandreas.hansson@arm.com } 25510618SOmar.Naji@arm.com 25610619Sandreas.hansson@arm.com return ss.str(); 25710619Sandreas.hansson@arm.com } 25810619Sandreas.hansson@arm.com}}; 25910619Sandreas.hansson@arm.com 26010619Sandreas.hansson@arm.comdef format Branch(code,*flags) {{ 26110619Sandreas.hansson@arm.com #Add Link Code if Link instruction 26210619Sandreas.hansson@arm.com strlen = len(name) 26310619Sandreas.hansson@arm.com if name[strlen-2:] == 'al': 26410619Sandreas.hansson@arm.com code += 'R31 = NNPC;\n' 26510619Sandreas.hansson@arm.com 26610619Sandreas.hansson@arm.com #Condition code 26710619Sandreas.hansson@arm.com code = 'bool cond;\n' + code 26810619Sandreas.hansson@arm.com code += 'if (cond) {\n' 26910619Sandreas.hansson@arm.com code += ' NNPC = NPC + disp;\n' 27010619Sandreas.hansson@arm.com code += '} else {\n' 27110618SOmar.Naji@arm.com code += ' NNPC = NNPC;\n' 2729243SN/A code += '} \n' 2739243SN/A 2749243SN/A iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 27510146Sandreas.hansson@arm.com ('IsDirectControl', 'IsCondControl')) 2769243SN/A 2779243SN/A header_output = BasicDeclare.subst(iop) 2789243SN/A decoder_output = BasicConstructor.subst(iop) 27911334Sandreas.hansson@arm.com decode_block = BasicDecode.subst(iop) 28011334Sandreas.hansson@arm.com exec_output = BasicExecute.subst(iop) 28111334Sandreas.hansson@arm.com}}; 2829243SN/A 2839243SN/A 2849243SN/Adef format BranchLikely(code,*flags) {{ 2859243SN/A #Add Link Code if Link instruction 28611334Sandreas.hansson@arm.com strlen = len(name) 2879243SN/A if name[strlen-3:] == 'all': 2889243SN/A code += 'R31 = NNPC;\n' 2899243SN/A 2909243SN/A #Condition code 2919243SN/A code = 'bool cond;\n' + code 2929243SN/A code += 'if (cond) {' 2939243SN/A code += 'NNPC = NPC + disp;\n' 2949243SN/A code += '} \n' 29510146Sandreas.hansson@arm.com 2969243SN/A 2979831SN/A iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 2989831SN/A ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) 2999831SN/A 3009243SN/A header_output = BasicDeclare.subst(iop) 3019831SN/A decoder_output = BasicConstructor.subst(iop) 3029831SN/A decode_block = BasicDecode.subst(iop) 3039243SN/A exec_output = BasicExecute.subst(iop) 3049243SN/A}}; 3059243SN/A 30610146Sandreas.hansson@arm.comdef format Jump(code,*flags) {{ 3079243SN/A #Add Link Code if Link instruction 3089831SN/A strlen = len(name) 3099831SN/A if strlen > 1 and name[1:] == 'al': 3109831SN/A code = 'R31 = NNPC;\n' + code 3119243SN/A 3129243SN/A 31310146Sandreas.hansson@arm.com iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ 31410146Sandreas.hansson@arm.com ('IsIndirectControl', 'IsUncondControl')) 31510143SN/A 3169243SN/A header_output = BasicDeclare.subst(iop) 3179669SN/A decoder_output = BasicConstructor.subst(iop) 31810136SN/A decode_block = BasicDecode.subst(iop) 31910136SN/A exec_output = BasicExecute.subst(iop) 3209243SN/A}}; 3219967SN/A 32210245Sandreas.hansson@arm.com 32310245Sandreas.hansson@arm.com 32410245Sandreas.hansson@arm.com 3259243SN/A