branch.isa revision 2100
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 branches (PC-relative control transfers), 65 * conditional or unconditional. 66 */ 67 class BranchLikely : public PCDependentDisassembly 68 { 69 protected: 70 /// target address (signed) Displacement . 71 int32_t targetOffset; 72 73 /// Constructor. 74 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 75 : PCDependentDisassembly(mnem, _machInst, __opClass), 76 targetOffset(OFFSET << 2) 77 { 78 } 79 80 Addr branchTarget(Addr branchPC) const; 81 82 std::string 83 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 84 }; 85 86 /** 87 * Base class for jumps (register-indirect control transfers). In 88 * the Mips ISA, these are always unconditional. 89 */ 90 class Jump : public PCDependentDisassembly 91 { 92 protected: 93 94 /// Displacement to target address (signed). 95 int32_t disp; 96 97 public: 98 /// Constructor 99 Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 100 : PCDependentDisassembly(mnem, _machInst, __opClass), 101 disp(OFFSET) 102 { 103 } 104 105 Addr branchTarget(ExecContext *xc) const; 106 107 std::string 108 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 109 }; 110}}; 111 112output decoder {{ 113 Addr 114 Branch::branchTarget(Addr branchPC) const 115 { 116 return branchPC + 4 + disp; 117 } 118 119 Addr 120 Jump::branchTarget(ExecContext *xc) const 121 { 122 Addr NPC = xc->readPC() + 4; 123 uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); 124 return (Rb & ~3) | (NPC & 1); 125 } 126 127 const std::string & 128 PCDependentDisassembly::disassemble(Addr pc, 129 const SymbolTable *symtab) const 130 { 131 if (!cachedDisassembly || 132 pc != cachedPC || symtab != cachedSymtab) 133 { 134 if (cachedDisassembly) 135 delete cachedDisassembly; 136 137 cachedDisassembly = 138 new std::string(generateDisassembly(pc, symtab)); 139 cachedPC = pc; 140 cachedSymtab = symtab; 141 } 142 143 return *cachedDisassembly; 144 } 145 146 std::string 147 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 148 { 149 std::stringstream ss; 150 151 ccprintf(ss, "%-10s ", mnemonic); 152 153 // There's only one register arg (RA), but it could be 154 // either a source (the condition for conditional 155 // branches) or a destination (the link reg for 156 // unconditional branches) 157 if (_numSrcRegs > 0) { 158 printReg(ss, _srcRegIdx[0]); 159 ss << ","; 160 } 161 else if (_numDestRegs > 0) { 162 printReg(ss, _destRegIdx[0]); 163 ss << ","; 164 } 165 166#ifdef SS_COMPATIBLE_DISASSEMBLY 167 if (_numSrcRegs == 0 && _numDestRegs == 0) { 168 printReg(ss, 31); 169 ss << ","; 170 } 171#endif 172 173 Addr target = pc + 4 + disp; 174 175 std::string str; 176 if (symtab && symtab->findSymbol(target, str)) 177 ss << str; 178 else 179 ccprintf(ss, "0x%x", target); 180 181 return ss.str(); 182 } 183 184 std::string 185 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 186 { 187 std::stringstream ss; 188 189 ccprintf(ss, "%-10s ", mnemonic); 190 191#ifdef SS_COMPATIBLE_DISASSEMBLY 192 if (_numDestRegs == 0) { 193 printReg(ss, 31); 194 ss << ","; 195 } 196#endif 197 198 if (_numDestRegs > 0) { 199 printReg(ss, _destRegIdx[0]); 200 ss << ","; 201 } 202 203 ccprintf(ss, "(r%d)", RB); 204 205 return ss.str(); 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) {{ 216 code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; 217 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 218 ('IsDirectControl', 'IsCondControl')) 219 header_output = BasicDeclare.subst(iop) 220 decoder_output = BasicConstructor.subst(iop) 221 decode_block = BasicDecode.subst(iop) 222 exec_output = BasicExecute.subst(iop) 223}}; 224 225 226def format BranchLikely(code) {{ 227 code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; 228 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), 229 ('IsDirectControl', 'IsCondControl')) 230 header_output = BasicDeclare.subst(iop) 231 decoder_output = BasicConstructor.subst(iop) 232 decode_block = BasicDecode.subst(iop) 233 exec_output = BasicExecute.subst(iop) 234}}; 235 236 237def format UncondBranch(*flags) {{ 238 flags += ('IsUncondControl', 'IsDirectControl') 239 (header_output, decoder_output, decode_block, exec_output) = \ 240 UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) 241}}; 242 243def format Jump(*flags) {{ 244 flags += ('IsUncondControl', 'IsIndirectControl') 245 (header_output, decoder_output, decode_block, exec_output) = \ 246 UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) 247}}; 248 249 250