branch.isa revision 2103
1// -*- mode:c++ -*- 2 3//////////////////////////////////////////////////////////////////// 4// 5// Control transfer instructions 6// 7 8output header {{ 9 10 /** 11 * Base class for instructions whose disassembly is not purely a 12 * function of the machine instruction (i.e., it depends on the 13 * PC). This class overrides the disassemble() method to check 14 * the PC and symbol table values before re-using a cached 15 * disassembly string. This is necessary for branches and jumps, 16 * where the disassembly string includes the target address (which 17 * may depend on the PC and/or symbol table). 18 */ 19 class PCDependentDisassembly : public MipsStaticInst 20 { 21 protected: 22 /// Cached program counter from last disassembly 23 mutable Addr cachedPC; 24 25 /// Cached symbol table pointer from last disassembly 26 mutable const SymbolTable *cachedSymtab; 27 28 /// Constructor 29 PCDependentDisassembly(const char *mnem, MachInst _machInst, 30 OpClass __opClass) 31 : MipsStaticInst(mnem, _machInst, __opClass), 32 cachedPC(0), cachedSymtab(0) 33 { 34 } 35 36 const std::string & 37 disassemble(Addr pc, const SymbolTable *symtab) const; 38 }; 39 40 /** 41 * Base class for branches (PC-relative control transfers), 42 * conditional or unconditional. 43 */ 44 class Branch : public PCDependentDisassembly 45 { 46 protected: 47 /// target address (signed) Displacement . 48 int32_t targetOffset; 49 50 /// Constructor. 51 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 52 : PCDependentDisassembly(mnem, _machInst, __opClass), 53 targetOffset(OFFSET << 2) 54 { 55 } 56 57 Addr branchTarget(Addr branchPC) const; 58 59 std::string 60 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 61 }; 62 63 /** 64 * Base class for branch likely branches (PC-relative control transfers), 65 */ 66 class BranchLikely : public PCDependentDisassembly 67 { 68 protected: 69 /// target address (signed) Displacement . 70 int32_t targetOffset; 71 72 /// Constructor. 73 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 74 : PCDependentDisassembly(mnem, _machInst, __opClass), 75 targetOffset(OFFSET << 2) 76 { 77 } 78 79 Addr branchTarget(Addr branchPC) const; 80 81 std::string 82 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 83 }; 84 85 /** 86 * Base class for jumps (register-indirect control transfers). In 87 * the Mips ISA, these are always unconditional. 88 */ 89 class Jump : public PCDependentDisassembly 90 { 91 protected: 92 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