branch.isa revision 2632
1// Copyright (c) 2006 The Regents of The University of Michigan 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer; 8// redistributions in binary form must reproduce the above copyright 9// notice, this list of conditions and the following disclaimer in the 10// documentation and/or other materials provided with the distribution; 11// neither the name of the copyright holders nor the names of its 12// contributors may be used to endorse or promote products derived from 13// this software without specific prior written permission. 14// 15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26// 27// Authors: Gabe Black 28// Steve Reinhardt 29 30//////////////////////////////////////////////////////////////////// 31// 32// Branch instructions 33// 34 35output header {{ 36 /** 37 * Base class for branch operations. 38 */ 39 class Branch : public SparcStaticInst 40 { 41 protected: 42 // Constructor 43 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : 44 SparcStaticInst(mnem, _machInst, __opClass) 45 { 46 } 47 48 std::string generateDisassembly(Addr pc, 49 const SymbolTable *symtab) const; 50 }; 51 52 /** 53 * Base class for branch operations with an immediate displacement. 54 */ 55 class BranchDisp : public Branch 56 { 57 protected: 58 // Constructor 59 BranchDisp(const char *mnem, MachInst _machInst, 60 OpClass __opClass) : 61 Branch(mnem, _machInst, __opClass) 62 { 63 } 64 65 std::string generateDisassembly(Addr pc, 66 const SymbolTable *symtab) const; 67 68 int32_t disp; 69 }; 70 71 /** 72 * Base class for branches with 19 bit displacements. 73 */ 74 class Branch19 : public BranchDisp 75 { 76 protected: 77 // Constructor 78 Branch19(const char *mnem, MachInst _machInst, 79 OpClass __opClass) : 80 BranchDisp(mnem, _machInst, __opClass) 81 { 82 disp = sign_ext(DISP19 << 2, 21); 83 } 84 }; 85 86 /** 87 * Base class for branches with 22 bit displacements. 88 */ 89 class Branch22 : public BranchDisp 90 { 91 protected: 92 // Constructor 93 Branch22(const char *mnem, MachInst _machInst, 94 OpClass __opClass) : 95 BranchDisp(mnem, _machInst, __opClass) 96 { 97 disp = sign_ext(DISP22 << 2, 24); 98 } 99 }; 100 101 /** 102 * Base class for branches with 30 bit displacements. 103 */ 104 class Branch30 : public BranchDisp 105 { 106 protected: 107 // Constructor 108 Branch30(const char *mnem, MachInst _machInst, 109 OpClass __opClass) : 110 BranchDisp(mnem, _machInst, __opClass) 111 { 112 disp = sign_ext(DISP30 << 2, 32); 113 } 114 }; 115 116 /** 117 * Base class for 16bit split displacements. 118 */ 119 class BranchSplit : public BranchDisp 120 { 121 protected: 122 // Constructor 123 BranchSplit(const char *mnem, MachInst _machInst, 124 OpClass __opClass) : 125 BranchDisp(mnem, _machInst, __opClass) 126 { 127 disp = sign_ext((D16HI << 16) | (D16LO << 2), 18); 128 } 129 }; 130 131 /** 132 * Base class for branches that use an immediate and a register to 133 * compute their displacements. 134 */ 135 class BranchImm13 : public Branch 136 { 137 protected: 138 // Constructor 139 BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) : 140 Branch(mnem, _machInst, __opClass), imm(sign_ext(SIMM13, 13)) 141 { 142 } 143 144 std::string generateDisassembly(Addr pc, 145 const SymbolTable *symtab) const; 146 147 int32_t imm; 148 }; 149}}; 150 151output decoder {{ 152 std::string Branch::generateDisassembly(Addr pc, 153 const SymbolTable *symtab) const 154 { 155 std::stringstream response; 156 157 printMnemonic(response, mnemonic); 158 159 if (_numSrcRegs > 0) 160 { 161 printReg(response, _srcRegIdx[0]); 162 for(int x = 1; x < _numSrcRegs; x++) 163 { 164 response << ", "; 165 printReg(response, _srcRegIdx[x]); 166 } 167 } 168 169 if (_numDestRegs > 0) 170 { 171 if(_numSrcRegs > 0) 172 response << ", "; 173 printReg(response, _destRegIdx[0]); 174 } 175 176 return response.str(); 177 } 178 179 std::string BranchImm13::generateDisassembly(Addr pc, 180 const SymbolTable *symtab) const 181 { 182 std::stringstream response; 183 184 printMnemonic(response, mnemonic); 185 186 if (_numSrcRegs > 0) 187 { 188 printReg(response, _srcRegIdx[0]); 189 for(int x = 1; x < _numSrcRegs; x++) 190 { 191 response << ", "; 192 printReg(response, _srcRegIdx[x]); 193 } 194 } 195 196 if(_numSrcRegs > 0) 197 response << ", "; 198 199 ccprintf(response, "0x%x", imm); 200 201 if (_numDestRegs > 0) 202 { 203 response << ", "; 204 printReg(response, _destRegIdx[0]); 205 } 206 207 return response.str(); 208 } 209 210 std::string BranchDisp::generateDisassembly(Addr pc, 211 const SymbolTable *symtab) const 212 { 213 std::stringstream response; 214 std::string symbol; 215 Addr symbolAddr; 216 217 Addr target = disp + pc; 218 219 printMnemonic(response, mnemonic); 220 ccprintf(response, "0x%x", target); 221 222 if(symtab->findNearestSymbol(target, symbol, symbolAddr)) 223 { 224 ccprintf(response, " <%s", symbol); 225 if(symbolAddr != target) 226 ccprintf(response, "+%d>", target - symbolAddr); 227 else 228 ccprintf(response, ">"); 229 } 230 231 return response.str(); 232 } 233}}; 234 235def template BranchExecute {{ 236 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 237 Trace::InstRecord *traceData) const 238 { 239 //Attempt to execute the instruction 240 Fault fault = NoFault; 241 242 %(op_decl)s; 243 %(op_rd)s; 244 245 NNPC = xc->readNextNPC(); 246 %(code)s; 247 248 if(fault == NoFault) 249 { 250 //Write the resulting state to the execution context 251 %(op_wb)s; 252 } 253 254 return fault; 255 } 256}}; 257 258let {{ 259 handle_annul = ''' 260 { 261 if(A) 262 { 263 NPC = xc->readNextNPC(); 264 NNPC = NPC + 4; 265 } 266 else 267 { 268 NPC = xc->readNextPC(); 269 NNPC = xc->readNextNPC(); 270 } 271 }''' 272}}; 273 274// Primary format for branch instructions: 275def format Branch(code, *opt_flags) {{ 276 code = re.sub(r'handle_annul', handle_annul, code) 277 (usesImm, code, immCode, 278 rString, iString) = splitOutImm(code) 279 iop = InstObjParams(name, Name, 'Branch', code, opt_flags) 280 header_output = BasicDeclare.subst(iop) 281 decoder_output = BasicConstructor.subst(iop) 282 exec_output = BranchExecute.subst(iop) 283 if usesImm: 284 imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString, 285 immCode, opt_flags) 286 header_output += BasicDeclare.subst(imm_iop) 287 decoder_output += BasicConstructor.subst(imm_iop) 288 exec_output += BranchExecute.subst(imm_iop) 289 decode_block = ROrImmDecode.subst(iop) 290 else: 291 decode_block = BasicDecode.subst(iop) 292}}; 293 294// Primary format for branch instructions: 295def format Branch19(code, *opt_flags) {{ 296 code = re.sub(r'handle_annul', handle_annul, code) 297 codeBlk = CodeBlock(code) 298 iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags) 299 header_output = BasicDeclare.subst(iop) 300 decoder_output = BasicConstructor.subst(iop) 301 exec_output = BranchExecute.subst(iop) 302 decode_block = BasicDecode.subst(iop) 303}}; 304 305// Primary format for branch instructions: 306def format Branch22(code, *opt_flags) {{ 307 code = re.sub(r'handle_annul', handle_annul, code) 308 codeBlk = CodeBlock(code) 309 iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags) 310 header_output = BasicDeclare.subst(iop) 311 decoder_output = BasicConstructor.subst(iop) 312 exec_output = BranchExecute.subst(iop) 313 decode_block = BasicDecode.subst(iop) 314}}; 315 316// Primary format for branch instructions: 317def format Branch30(code, *opt_flags) {{ 318 code = re.sub(r'handle_annul', handle_annul, code) 319 codeBlk = CodeBlock(code) 320 iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags) 321 header_output = BasicDeclare.subst(iop) 322 decoder_output = BasicConstructor.subst(iop) 323 exec_output = BranchExecute.subst(iop) 324 decode_block = BasicDecode.subst(iop) 325}}; 326 327// Primary format for branch instructions: 328def format BranchSplit(code, *opt_flags) {{ 329 code = re.sub(r'handle_annul', handle_annul, code) 330 codeBlk = CodeBlock(code) 331 iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags) 332 header_output = BasicDeclare.subst(iop) 333 decoder_output = BasicConstructor.subst(iop) 334 exec_output = BranchExecute.subst(iop) 335 decode_block = BasicDecode.subst(iop) 336}}; 337 338