branch.isa revision 2101
12089SN/A// -*- mode:c++ -*- 22022SN/A 35268Sksewell@umich.edu//////////////////////////////////////////////////////////////////// 45222Sksewell@umich.edu// 55268Sksewell@umich.edu// Control transfer instructions 65268Sksewell@umich.edu// 75268Sksewell@umich.edu 85268Sksewell@umich.eduoutput header {{ 95268Sksewell@umich.edu 105268Sksewell@umich.edu /** 115268Sksewell@umich.edu * Base class for instructions whose disassembly is not purely a 125268Sksewell@umich.edu * function of the machine instruction (i.e., it depends on the 135268Sksewell@umich.edu * PC). This class overrides the disassemble() method to check 145268Sksewell@umich.edu * the PC and symbol table values before re-using a cached 155268Sksewell@umich.edu * disassembly string. This is necessary for branches and jumps, 165268Sksewell@umich.edu * where the disassembly string includes the target address (which 175268Sksewell@umich.edu * may depend on the PC and/or symbol table). 185268Sksewell@umich.edu */ 195268Sksewell@umich.edu class PCDependentDisassembly : public MipsStaticInst 205268Sksewell@umich.edu { 215268Sksewell@umich.edu protected: 225268Sksewell@umich.edu /// Cached program counter from last disassembly 235268Sksewell@umich.edu mutable Addr cachedPC; 245268Sksewell@umich.edu 255268Sksewell@umich.edu /// Cached symbol table pointer from last disassembly 265268Sksewell@umich.edu mutable const SymbolTable *cachedSymtab; 275268Sksewell@umich.edu 285268Sksewell@umich.edu /// Constructor 295268Sksewell@umich.edu PCDependentDisassembly(const char *mnem, MachInst _machInst, 305268Sksewell@umich.edu OpClass __opClass) 315268Sksewell@umich.edu : MipsStaticInst(mnem, _machInst, __opClass), 325268Sksewell@umich.edu cachedPC(0), cachedSymtab(0) 332706Sksewell@umich.edu { 342022SN/A } 352022SN/A 3612234Sgabeblack@google.com const std::string & 372022SN/A disassemble(Addr pc, const SymbolTable *symtab) const; 382022SN/A }; 392022SN/A 402022SN/A /** 412022SN/A * Base class for branches (PC-relative control transfers), 422022SN/A * conditional or unconditional. 432022SN/A */ 442022SN/A class Branch : public PCDependentDisassembly 452022SN/A { 462686Sksewell@umich.edu protected: 472022SN/A /// target address (signed) Displacement . 482022SN/A int32_t targetOffset; 492022SN/A 502686Sksewell@umich.edu /// Constructor. 512022SN/A Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 522022SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 532022SN/A targetOffset(OFFSET << 2) 542022SN/A { 5510184SCurtis.Dunham@arm.com } 562022SN/A 572022SN/A Addr branchTarget(Addr branchPC) const; 582022SN/A 592022SN/A std::string 602022SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 612686Sksewell@umich.edu }; 622022SN/A 632022SN/A /** 6412234Sgabeblack@google.com * Base class for branch likely branches (PC-relative control transfers), 6512234Sgabeblack@google.com */ 662022SN/A class BranchLikely : public PCDependentDisassembly 672239SN/A { 682022SN/A protected: 692022SN/A /// target address (signed) Displacement . 702022SN/A int32_t targetOffset; 712022SN/A 722239SN/A /// Constructor. 732022SN/A Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 745222Sksewell@umich.edu : PCDependentDisassembly(mnem, _machInst, __opClass), 755222Sksewell@umich.edu targetOffset(OFFSET << 2) 762104SN/A { 775222Sksewell@umich.edu } 782022SN/A 792022SN/A Addr branchTarget(Addr branchPC) const; 802022SN/A 812022SN/A std::string 822022SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 832022SN/A }; 842022SN/A 852022SN/A /** 862022SN/A * Base class for jumps (register-indirect control transfers). In 872022SN/A * the Mips ISA, these are always unconditional. 882022SN/A */ 892022SN/A class Jump : public PCDependentDisassembly 902022SN/A { 912022SN/A protected: 922022SN/A 932935Sksewell@umich.edu /// Displacement to target address (signed). 942083SN/A int32_t disp; 953951Sgblack@eecs.umich.edu 962022SN/A public: 972022SN/A /// Constructor 982022SN/A Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 992022SN/A : PCDependentDisassembly(mnem, _machInst, __opClass), 1002022SN/A disp(OFFSET) 101 { 102 } 103 104 Addr branchTarget(ExecContext *xc) const; 105 106 std::string 107 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 108 }; 109}}; 110 111output decoder {{ 112 Addr 113 Branch::branchTarget(Addr branchPC) const 114 { 115 return branchPC + 4 + disp; 116 } 117 118 Addr 119 Jump::branchTarget(ExecContext *xc) const 120 { 121 Addr NPC = xc->readPC() + 4; 122 uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); 123 return (Rb & ~3) | (NPC & 1); 124 } 125 126 const std::string & 127 PCDependentDisassembly::disassemble(Addr pc, 128 const SymbolTable *symtab) const 129 { 130 if (!cachedDisassembly || 131 pc != cachedPC || symtab != cachedSymtab) 132 { 133 if (cachedDisassembly) 134 delete cachedDisassembly; 135 136 cachedDisassembly = 137 new std::string(generateDisassembly(pc, symtab)); 138 cachedPC = pc; 139 cachedSymtab = symtab; 140 } 141 142 return *cachedDisassembly; 143 } 144 145 std::string 146 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 147 { 148 std::stringstream ss; 149 150 ccprintf(ss, "%-10s ", mnemonic); 151 152 // There's only one register arg (RA), but it could be 153 // either a source (the condition for conditional 154 // branches) or a destination (the link reg for 155 // unconditional branches) 156 if (_numSrcRegs > 0) { 157 printReg(ss, _srcRegIdx[0]); 158 ss << ","; 159 } 160 else if (_numDestRegs > 0) { 161 printReg(ss, _destRegIdx[0]); 162 ss << ","; 163 } 164 165#ifdef SS_COMPATIBLE_DISASSEMBLY 166 if (_numSrcRegs == 0 && _numDestRegs == 0) { 167 printReg(ss, 31); 168 ss << ","; 169 } 170#endif 171 172 Addr target = pc + 4 + disp; 173 174 std::string str; 175 if (symtab && symtab->findSymbol(target, str)) 176 ss << str; 177 else 178 ccprintf(ss, "0x%x", target); 179 180 return ss.str(); 181 } 182 183 std::string 184 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 185 { 186 std::stringstream ss; 187 188 ccprintf(ss, "%-10s ", mnemonic); 189 190#ifdef SS_COMPATIBLE_DISASSEMBLY 191 if (_numDestRegs == 0) { 192 printReg(ss, 31); 193 ss << ","; 194 } 195#endif 196 197 if (_numDestRegs > 0) { 198 printReg(ss, _destRegIdx[0]); 199 ss << ","; 200 } 201 202 ccprintf(ss, "(r%d)", RB); 203 204 return ss.str(); 205 } 206}}; 207 208 209def template JumpOrBranchDecode {{ 210 return (RD == 0) 211 ? (StaticInst<MipsISA> *)new %(class_name)s(machInst) 212 : (StaticInst<MipsISA> *)new %(class_name)sAndLink(machInst); 213}}; 214 215def format Branch(code,*flags) {{ 216 code = 'bool cond;\n' + code + '\n' 217 218 if flags == 'IsLink': 219 code += 'R31 = NPC + 8\n' 220 221 code += '\nif (cond) NPC = NPC + disp;\n'; 222 223 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 224 ('IsDirectControl', 'IsCondControl')) 225 header_output = BasicDeclare.subst(iop) 226 decoder_output = BasicConstructor.subst(iop) 227 decode_block = BasicDecode.subst(iop) 228 exec_output = BasicExecute.subst(iop) 229}}; 230 231def format BranchLikely(code,*flags) {{ 232 code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; 233 234 if flags == 'IsLink': 235 code += 'R31 = NPC + 8\n' 236 237 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 238 ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) 239 header_output = BasicDeclare.subst(iop) 240 decoder_output = BasicConstructor.subst(iop) 241 decode_block = BasicDecode.subst(iop) 242 exec_output = BasicExecute.subst(iop) 243}}; 244 245def format Unconditional(code,*flags) {{ 246 iop = InstObjParams(name, Name, 'Jump', CodeBlock(code), 247 ('IsIndirectControl', 'IsUncondControl')) 248 header_output = BasicDeclare.subst(iop) 249 decoder_output = BasicConstructor.subst(iop) 250 decode_block = BasicDecode.subst(iop) 251 exec_output = BasicExecute.subst(iop) 252}}; 253 254 255 256 257