branch.isa revision 2580
1//////////////////////////////////////////////////////////////////// 2// 3// Branch instructions 4// 5 6output header {{ 7 /** 8 * Base class for branch operations. 9 */ 10 class Branch : public SparcStaticInst 11 { 12 protected: 13 // Constructor 14 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : 15 SparcStaticInst(mnem, _machInst, __opClass) 16 { 17 } 18 19 std::string generateDisassembly(Addr pc, 20 const SymbolTable *symtab) const; 21 }; 22 23 /** 24 * Base class for branch operations with an immediate displacement. 25 */ 26 class BranchDisp : public Branch 27 { 28 protected: 29 // Constructor 30 BranchDisp(const char *mnem, MachInst _machInst, 31 OpClass __opClass) : 32 Branch(mnem, _machInst, __opClass) 33 { 34 } 35 36 std::string generateDisassembly(Addr pc, 37 const SymbolTable *symtab) const; 38 39 int32_t disp; 40 }; 41 42 /** 43 * Base class for branches with 19 bit displacements. 44 */ 45 class Branch19 : public BranchDisp 46 { 47 protected: 48 // Constructor 49 Branch19(const char *mnem, MachInst _machInst, 50 OpClass __opClass) : 51 BranchDisp(mnem, _machInst, __opClass) 52 { 53 disp = sign_ext(DISP19 << 2, 21); 54 } 55 }; 56 57 /** 58 * Base class for branches with 22 bit displacements. 59 */ 60 class Branch22 : public BranchDisp 61 { 62 protected: 63 // Constructor 64 Branch22(const char *mnem, MachInst _machInst, 65 OpClass __opClass) : 66 BranchDisp(mnem, _machInst, __opClass) 67 { 68 disp = sign_ext(DISP22 << 2, 24); 69 } 70 }; 71 72 /** 73 * Base class for branches with 30 bit displacements. 74 */ 75 class Branch30 : public BranchDisp 76 { 77 protected: 78 // Constructor 79 Branch30(const char *mnem, MachInst _machInst, 80 OpClass __opClass) : 81 BranchDisp(mnem, _machInst, __opClass) 82 { 83 disp = sign_ext(DISP30 << 2, 32); 84 } 85 }; 86 87 /** 88 * Base class for 16bit split displacements. 89 */ 90 class BranchSplit : public BranchDisp 91 { 92 protected: 93 // Constructor 94 BranchSplit(const char *mnem, MachInst _machInst, 95 OpClass __opClass) : 96 BranchDisp(mnem, _machInst, __opClass) 97 { 98 disp = sign_ext((D16HI << 16) | (D16LO << 2), 18); 99 } 100 }; 101 102 /** 103 * Base class for branches that use an immediate and a register to 104 * compute their displacements. 105 */ 106 class BranchImm13 : public Branch 107 { 108 protected: 109 // Constructor 110 BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) : 111 Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13)) 112 { 113 } 114 115 std::string generateDisassembly(Addr pc, 116 const SymbolTable *symtab) const; 117 118 int32_t imm; 119 }; 120}}; 121 122output decoder {{ 123 std::string Branch::generateDisassembly(Addr pc, 124 const SymbolTable *symtab) const 125 { 126 std::stringstream response; 127 128 printMnemonic(response, mnemonic); 129 130 if (_numSrcRegs > 0) 131 { 132 printReg(response, _srcRegIdx[0]); 133 for(int x = 1; x < _numSrcRegs; x++) 134 { 135 response << ", "; 136 printReg(response, _srcRegIdx[x]); 137 } 138 } 139 140 if (_numDestRegs > 0) 141 { 142 if(_numSrcRegs > 0) 143 response << ", "; 144 printReg(response, _destRegIdx[0]); 145 } 146 147 return response.str(); 148 } 149 150 std::string BranchImm13::generateDisassembly(Addr pc, 151 const SymbolTable *symtab) const 152 { 153 std::stringstream response; 154 155 printMnemonic(response, mnemonic); 156 157 if (_numSrcRegs > 0) 158 { 159 printReg(response, _srcRegIdx[0]); 160 for(int x = 1; x < _numSrcRegs; x++) 161 { 162 response << ", "; 163 printReg(response, _srcRegIdx[x]); 164 } 165 } 166 167 if(_numSrcRegs > 0) 168 response << ", "; 169 170 ccprintf(response, "0x%x", imm); 171 172 if (_numDestRegs > 0) 173 { 174 response << ", "; 175 printReg(response, _destRegIdx[0]); 176 } 177 178 return response.str(); 179 } 180 181 std::string BranchDisp::generateDisassembly(Addr pc, 182 const SymbolTable *symtab) const 183 { 184 std::stringstream response; 185 std::string symbol; 186 Addr symbolAddr; 187 188 Addr target = disp + pc; 189 190 printMnemonic(response, mnemonic); 191 ccprintf(response, "0x%x", target); 192 193 if(symtab->findNearestSymbol(target, symbol, symbolAddr)) 194 { 195 ccprintf(response, " <%s", symbol); 196 if(symbolAddr != target) 197 ccprintf(response, "+%d>", target - symbolAddr); 198 else 199 ccprintf(response, ">"); 200 } 201 202 return response.str(); 203 } 204}}; 205 206def template BranchExecute {{ 207 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 208 Trace::InstRecord *traceData) const 209 { 210 //Attempt to execute the instruction 211 Fault fault = NoFault; 212 213 %(op_decl)s; 214 %(op_rd)s; 215 216 NNPC = xc->readNextNPC(); 217 %(code)s; 218 219 if(fault == NoFault) 220 { 221 //Write the resulting state to the execution context 222 %(op_wb)s; 223 } 224 225 return fault; 226 } 227}}; 228 229let {{ 230 handle_annul = ''' 231 { 232 if(A) 233 { 234 NPC = xc->readNextNPC(); 235 NNPC = NPC + 4; 236 } 237 else 238 { 239 NPC = xc->readNextPC(); 240 NNPC = xc->readNextNPC(); 241 } 242 }''' 243}}; 244 245// Primary format for branch instructions: 246def format Branch(code, *opt_flags) {{ 247 code = re.sub(r'handle_annul', handle_annul, code) 248 (usesImm, code, immCode, 249 rString, iString) = splitOutImm(code) 250 iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 251 header_output = BasicDeclare.subst(iop) 252 decoder_output = BasicConstructor.subst(iop) 253 exec_output = BranchExecute.subst(iop) 254 if usesImm: 255 imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 256 immCode, opt_flags) 257 header_output += BasicDeclare.subst(imm_iop) 258 decoder_output += BasicConstructor.subst(imm_iop) 259 exec_output += BranchExecute.subst(imm_iop) 260 decode_block = ROrImmDecode.subst(iop) 261 else: 262 decode_block = BasicDecode.subst(iop) 263}}; 264 265// Primary format for branch instructions: 266def format Branch19(code, *opt_flags) {{ 267 code = re.sub(r'handle_annul', handle_annul, code) 268 codeBlk = CodeBlock(code) 269 iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags) 270 header_output = BasicDeclare.subst(iop) 271 decoder_output = BasicConstructor.subst(iop) 272 exec_output = BranchExecute.subst(iop) 273 decode_block = BasicDecode.subst(iop) 274}}; 275 276// Primary format for branch instructions: 277def format Branch22(code, *opt_flags) {{ 278 code = re.sub(r'handle_annul', handle_annul, code) 279 codeBlk = CodeBlock(code) 280 iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags) 281 header_output = BasicDeclare.subst(iop) 282 decoder_output = BasicConstructor.subst(iop) 283 exec_output = BranchExecute.subst(iop) 284 decode_block = BasicDecode.subst(iop) 285}}; 286 287// Primary format for branch instructions: 288def format Branch30(code, *opt_flags) {{ 289 code = re.sub(r'handle_annul', handle_annul, code) 290 codeBlk = CodeBlock(code) 291 iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags) 292 header_output = BasicDeclare.subst(iop) 293 decoder_output = BasicConstructor.subst(iop) 294 exec_output = BranchExecute.subst(iop) 295 decode_block = BasicDecode.subst(iop) 296}}; 297 298// Primary format for branch instructions: 299def format BranchSplit(code, *opt_flags) {{ 300 code = re.sub(r'handle_annul', handle_annul, code) 301 codeBlk = CodeBlock(code) 302 iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags) 303 header_output = BasicDeclare.subst(iop) 304 decoder_output = BasicConstructor.subst(iop) 305 exec_output = BranchExecute.subst(iop) 306 decode_block = BasicDecode.subst(iop) 307}}; 308 309