branch.isa revision 2103
112218Snikos.nikoleris@arm.com// -*- mode:c++ -*- 212218Snikos.nikoleris@arm.com 312218Snikos.nikoleris@arm.com//////////////////////////////////////////////////////////////////// 412218Snikos.nikoleris@arm.com// 512218Snikos.nikoleris@arm.com// Control transfer instructions 612218Snikos.nikoleris@arm.com// 712218Snikos.nikoleris@arm.com 812218Snikos.nikoleris@arm.comoutput header {{ 912218Snikos.nikoleris@arm.com 1012218Snikos.nikoleris@arm.com /** 1112218Snikos.nikoleris@arm.com * Base class for instructions whose disassembly is not purely a 1212218Snikos.nikoleris@arm.com * function of the machine instruction (i.e., it depends on the 1312218Snikos.nikoleris@arm.com * PC). This class overrides the disassemble() method to check 1412218Snikos.nikoleris@arm.com * the PC and symbol table values before re-using a cached 1512218Snikos.nikoleris@arm.com * disassembly string. This is necessary for branches and jumps, 1612218Snikos.nikoleris@arm.com * where the disassembly string includes the target address (which 1712218Snikos.nikoleris@arm.com * may depend on the PC and/or symbol table). 1812218Snikos.nikoleris@arm.com */ 1912218Snikos.nikoleris@arm.com class PCDependentDisassembly : public MipsStaticInst 2012218Snikos.nikoleris@arm.com { 2112218Snikos.nikoleris@arm.com protected: 2212218Snikos.nikoleris@arm.com /// Cached program counter from last disassembly 2312218Snikos.nikoleris@arm.com mutable Addr cachedPC; 2412218Snikos.nikoleris@arm.com 2512218Snikos.nikoleris@arm.com /// Cached symbol table pointer from last disassembly 2612218Snikos.nikoleris@arm.com mutable const SymbolTable *cachedSymtab; 2712218Snikos.nikoleris@arm.com 2812218Snikos.nikoleris@arm.com /// Constructor 2912218Snikos.nikoleris@arm.com PCDependentDisassembly(const char *mnem, MachInst _machInst, 3012218Snikos.nikoleris@arm.com OpClass __opClass) 3112218Snikos.nikoleris@arm.com : MipsStaticInst(mnem, _machInst, __opClass), 3212218Snikos.nikoleris@arm.com cachedPC(0), cachedSymtab(0) 3312218Snikos.nikoleris@arm.com { 3412218Snikos.nikoleris@arm.com } 3512218Snikos.nikoleris@arm.com 3612218Snikos.nikoleris@arm.com const std::string & 3712218Snikos.nikoleris@arm.com disassemble(Addr pc, const SymbolTable *symtab) const; 3812218Snikos.nikoleris@arm.com }; 3912218Snikos.nikoleris@arm.com 4012218Snikos.nikoleris@arm.com /** 4112218Snikos.nikoleris@arm.com * Base class for branches (PC-relative control transfers), 4212218Snikos.nikoleris@arm.com * conditional or unconditional. 4312218Snikos.nikoleris@arm.com */ 4412218Snikos.nikoleris@arm.com class Branch : public PCDependentDisassembly 4512218Snikos.nikoleris@arm.com { 4612218Snikos.nikoleris@arm.com protected: 4712218Snikos.nikoleris@arm.com /// target address (signed) Displacement . 4812218Snikos.nikoleris@arm.com int32_t targetOffset; 4912218Snikos.nikoleris@arm.com 5012218Snikos.nikoleris@arm.com /// Constructor. 5112218Snikos.nikoleris@arm.com Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 5212218Snikos.nikoleris@arm.com : PCDependentDisassembly(mnem, _machInst, __opClass), 5312218Snikos.nikoleris@arm.com targetOffset(OFFSET << 2) 5412218Snikos.nikoleris@arm.com { 5512218Snikos.nikoleris@arm.com } 5612218Snikos.nikoleris@arm.com 5712218Snikos.nikoleris@arm.com Addr branchTarget(Addr branchPC) const; 5812218Snikos.nikoleris@arm.com 5912218Snikos.nikoleris@arm.com std::string 6012218Snikos.nikoleris@arm.com generateDisassembly(Addr pc, const SymbolTable *symtab) const; 6112218Snikos.nikoleris@arm.com }; 6212218Snikos.nikoleris@arm.com 6312218Snikos.nikoleris@arm.com /** 6412218Snikos.nikoleris@arm.com * Base class for branch likely branches (PC-relative control transfers), 6512218Snikos.nikoleris@arm.com */ 6612749Sgiacomo.travaglini@arm.com class BranchLikely : public PCDependentDisassembly 6712218Snikos.nikoleris@arm.com { 6812218Snikos.nikoleris@arm.com protected: 6912218Snikos.nikoleris@arm.com /// target address (signed) Displacement . 7012218Snikos.nikoleris@arm.com int32_t targetOffset; 7112218Snikos.nikoleris@arm.com 7212218Snikos.nikoleris@arm.com /// Constructor. 7312218Snikos.nikoleris@arm.com Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 7412218Snikos.nikoleris@arm.com : PCDependentDisassembly(mnem, _machInst, __opClass), 7512218Snikos.nikoleris@arm.com targetOffset(OFFSET << 2) 7612218Snikos.nikoleris@arm.com { 7712218Snikos.nikoleris@arm.com } 7812218Snikos.nikoleris@arm.com 7912749Sgiacomo.travaglini@arm.com Addr branchTarget(Addr branchPC) const; 8012218Snikos.nikoleris@arm.com 8112218Snikos.nikoleris@arm.com std::string 8212218Snikos.nikoleris@arm.com generateDisassembly(Addr pc, const SymbolTable *symtab) const; 8312218Snikos.nikoleris@arm.com }; 8412218Snikos.nikoleris@arm.com 8512218Snikos.nikoleris@arm.com /** 8612218Snikos.nikoleris@arm.com * Base class for jumps (register-indirect control transfers). In 8712218Snikos.nikoleris@arm.com * the Mips ISA, these are always unconditional. 8812218Snikos.nikoleris@arm.com */ 8912218Snikos.nikoleris@arm.com class Jump : public PCDependentDisassembly 9012218Snikos.nikoleris@arm.com { 9112218Snikos.nikoleris@arm.com protected: 9212218Snikos.nikoleris@arm.com 93 /// Displacement to target address (signed). 94 int32_t disp; 95 96 public: 97 /// Constructor 98 Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 99 : PCDependentDisassembly(mnem, _machInst, __opClass), 100 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 BranchLikely::branchTarget(Addr branchPC) const 120 { 121 return branchPC + 4 + disp; 122 } 123 124 Addr 125 Jump::branchTarget(ExecContext *xc) const 126 { 127 Addr NPC = xc->readPC() + 4; 128 uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); 129 return (Rb & ~3) | (NPC & 1); 130 } 131 132 const std::string & 133 PCDependentDisassembly::disassemble(Addr pc, 134 const SymbolTable *symtab) const 135 { 136 if (!cachedDisassembly || 137 pc != cachedPC || symtab != cachedSymtab) 138 { 139 if (cachedDisassembly) 140 delete cachedDisassembly; 141 142 cachedDisassembly = 143 new std::string(generateDisassembly(pc, symtab)); 144 cachedPC = pc; 145 cachedSymtab = symtab; 146 } 147 148 return *cachedDisassembly; 149 } 150 151 std::string 152 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 153 { 154 std::stringstream ss; 155 156 ccprintf(ss, "%-10s ", mnemonic); 157 158 // There's only one register arg (RA), but it could be 159 // either a source (the condition for conditional 160 // branches) or a destination (the link reg for 161 // unconditional branches) 162 if (_numSrcRegs > 0) { 163 printReg(ss, _srcRegIdx[0]); 164 ss << ","; 165 } 166 else if (_numDestRegs > 0) { 167 printReg(ss, _destRegIdx[0]); 168 ss << ","; 169 } 170 171#ifdef SS_COMPATIBLE_DISASSEMBLY 172 if (_numSrcRegs == 0 && _numDestRegs == 0) { 173 printReg(ss, 31); 174 ss << ","; 175 } 176#endif 177 178 Addr target = pc + 4 + disp; 179 180 std::string str; 181 if (symtab && symtab->findSymbol(target, str)) 182 ss << str; 183 else 184 ccprintf(ss, "0x%x", target); 185 186 return ss.str(); 187 } 188 189 std::string 190 BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const 191 { 192 std::stringstream ss; 193 194 ccprintf(ss, "%-10s ", mnemonic); 195 196 // There's only one register arg (RA), but it could be 197 // either a source (the condition for conditional 198 // branches) or a destination (the link reg for 199 // unconditional branches) 200 if (_numSrcRegs > 0) { 201 printReg(ss, _srcRegIdx[0]); 202 ss << ","; 203 } 204 else if (_numDestRegs > 0) { 205 printReg(ss, _destRegIdx[0]); 206 ss << ","; 207 } 208 209#ifdef SS_COMPATIBLE_DISASSEMBLY 210 if (_numSrcRegs == 0 && _numDestRegs == 0) { 211 printReg(ss, 31); 212 ss << ","; 213 } 214#endif 215 216 Addr target = pc + 4 + disp; 217 218 std::string str; 219 if (symtab && symtab->findSymbol(target, str)) 220 ss << str; 221 else 222 ccprintf(ss, "0x%x", target); 223 224 return ss.str(); 225 } 226 227 std::string 228 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 229 { 230 std::stringstream ss; 231 232 ccprintf(ss, "%-10s ", mnemonic); 233 234#ifdef SS_COMPATIBLE_DISASSEMBLY 235 if (_numDestRegs == 0) { 236 printReg(ss, 31); 237 ss << ","; 238 } 239#endif 240 241 if (_numDestRegs > 0) { 242 printReg(ss, _destRegIdx[0]); 243 ss << ","; 244 } 245 246 ccprintf(ss, "(r%d)", RB); 247 248 return ss.str(); 249 } 250}}; 251 252def format Branch(code,*flags) {{ 253 code = 'bool cond;\n\t' + code + '\n' 254 255 #Add Link Code if Link instruction 256 strlen = len(name) 257 if name[strlen-2:] == 'al': 258 code += 'R31 = NPC + 8;\n' 259 260 code += '\nif (cond) NPC = NPC + disp;\n'; 261 262 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 263 ('IsDirectControl', 'IsCondControl')) 264 header_output = BasicDeclare.subst(iop) 265 decoder_output = BasicConstructor.subst(iop) 266 decode_block = BasicDecode.subst(iop) 267 exec_output = BasicExecute.subst(iop) 268}}; 269 270def format BranchLikely(code,*flags) {{ 271 code = 'bool cond;\n\t\t\t' + code 272 273 #Add Link Code if Link instruction 274 strlen = len(name) 275 if name[strlen-3:] == 'all': 276 code += 'R31 = NPC + 8;\n' 277 278 code = '\t\t\tif (cond) NPC = NPC + disp;\n'; 279 280 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 281 ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) 282 header_output = BasicDeclare.subst(iop) 283 decoder_output = BasicConstructor.subst(iop) 284 decode_block = BasicDecode.subst(iop) 285 exec_output = BasicExecute.subst(iop) 286}}; 287 288def format Unconditional(code,*flags) {{ 289 iop = InstObjParams(name, Name, 'Jump', CodeBlock(code), 290 ('IsIndirectControl', 'IsUncondControl')) 291 header_output = BasicDeclare.subst(iop) 292 decoder_output = BasicConstructor.subst(iop) 293 decode_block = BasicDecode.subst(iop) 294 exec_output = BasicExecute.subst(iop) 295}}; 296 297 298 299 300