branch.isa revision 2101
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 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