branch.isa revision 2101
15664Sgblack@eecs.umich.edu// -*- mode:c++ -*- 25664Sgblack@eecs.umich.edu 35664Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////// 45664Sgblack@eecs.umich.edu// 55664Sgblack@eecs.umich.edu// Control transfer instructions 65664Sgblack@eecs.umich.edu// 75664Sgblack@eecs.umich.edu 85664Sgblack@eecs.umich.eduoutput header {{ 95664Sgblack@eecs.umich.edu 105664Sgblack@eecs.umich.edu /** 115664Sgblack@eecs.umich.edu * Base class for instructions whose disassembly is not purely a 125664Sgblack@eecs.umich.edu * function of the machine instruction (i.e., it depends on the 135664Sgblack@eecs.umich.edu * PC). This class overrides the disassemble() method to check 145664Sgblack@eecs.umich.edu * the PC and symbol table values before re-using a cached 155664Sgblack@eecs.umich.edu * disassembly string. This is necessary for branches and jumps, 165664Sgblack@eecs.umich.edu * where the disassembly string includes the target address (which 175664Sgblack@eecs.umich.edu * may depend on the PC and/or symbol table). 185664Sgblack@eecs.umich.edu */ 195664Sgblack@eecs.umich.edu class PCDependentDisassembly : public MipsStaticInst 205664Sgblack@eecs.umich.edu { 215664Sgblack@eecs.umich.edu protected: 225664Sgblack@eecs.umich.edu /// Cached program counter from last disassembly 235664Sgblack@eecs.umich.edu mutable Addr cachedPC; 245664Sgblack@eecs.umich.edu 255664Sgblack@eecs.umich.edu /// Cached symbol table pointer from last disassembly 265664Sgblack@eecs.umich.edu mutable const SymbolTable *cachedSymtab; 275664Sgblack@eecs.umich.edu 285664Sgblack@eecs.umich.edu /// Constructor 295664Sgblack@eecs.umich.edu PCDependentDisassembly(const char *mnem, MachInst _machInst, 305664Sgblack@eecs.umich.edu OpClass __opClass) 315664Sgblack@eecs.umich.edu : MipsStaticInst(mnem, _machInst, __opClass), 325664Sgblack@eecs.umich.edu cachedPC(0), cachedSymtab(0) 335664Sgblack@eecs.umich.edu { 345666Sgblack@eecs.umich.edu } 355666Sgblack@eecs.umich.edu 365666Sgblack@eecs.umich.edu const std::string & 375666Sgblack@eecs.umich.edu disassemble(Addr pc, const SymbolTable *symtab) const; 385666Sgblack@eecs.umich.edu }; 395666Sgblack@eecs.umich.edu 405666Sgblack@eecs.umich.edu /** 415666Sgblack@eecs.umich.edu * Base class for branches (PC-relative control transfers), 425666Sgblack@eecs.umich.edu * conditional or unconditional. 435666Sgblack@eecs.umich.edu */ 445666Sgblack@eecs.umich.edu class Branch : public PCDependentDisassembly 455666Sgblack@eecs.umich.edu { 465666Sgblack@eecs.umich.edu protected: 475666Sgblack@eecs.umich.edu /// target address (signed) Displacement . 485666Sgblack@eecs.umich.edu int32_t targetOffset; 495666Sgblack@eecs.umich.edu 505666Sgblack@eecs.umich.edu /// Constructor. 515666Sgblack@eecs.umich.edu Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 525666Sgblack@eecs.umich.edu : PCDependentDisassembly(mnem, _machInst, __opClass), 535666Sgblack@eecs.umich.edu targetOffset(OFFSET << 2) 545666Sgblack@eecs.umich.edu { 555666Sgblack@eecs.umich.edu } 565666Sgblack@eecs.umich.edu 575666Sgblack@eecs.umich.edu Addr branchTarget(Addr branchPC) const; 585666Sgblack@eecs.umich.edu 595666Sgblack@eecs.umich.edu std::string 605666Sgblack@eecs.umich.edu generateDisassembly(Addr pc, const SymbolTable *symtab) const; 615666Sgblack@eecs.umich.edu }; 625666Sgblack@eecs.umich.edu 635666Sgblack@eecs.umich.edu /** 645666Sgblack@eecs.umich.edu * Base class for branch likely branches (PC-relative control transfers), 655666Sgblack@eecs.umich.edu */ 665666Sgblack@eecs.umich.edu class BranchLikely : public PCDependentDisassembly 675666Sgblack@eecs.umich.edu { 685664Sgblack@eecs.umich.edu protected: 695664Sgblack@eecs.umich.edu /// target address (signed) Displacement . 705664Sgblack@eecs.umich.edu int32_t targetOffset; 715666Sgblack@eecs.umich.edu 725664Sgblack@eecs.umich.edu /// Constructor. 735664Sgblack@eecs.umich.edu Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 745664Sgblack@eecs.umich.edu : 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