branch.isa revision 9552
1// -*- mode:c++ -*- 2 3// Copyright (c) 2007 MIPS Technologies, Inc. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Korey Sewell 30 31//////////////////////////////////////////////////////////////////// 32// 33// Control transfer instructions 34// 35 36output header {{ 37 38#include <iostream> 39 using namespace std; 40 41 /** 42 * Base class for instructions whose disassembly is not purely a 43 * function of the machine instruction (i.e., it depends on the 44 * PC). This class overrides the disassemble() method to check 45 * the PC and symbol table values before re-using a cached 46 * disassembly string. This is necessary for branches and jumps, 47 * where the disassembly string includes the target address (which 48 * may depend on the PC and/or symbol table). 49 */ 50 class PCDependentDisassembly : public MipsStaticInst 51 { 52 protected: 53 /// Cached program counter from last disassembly 54 mutable Addr cachedPC; 55 56 /// Cached symbol table pointer from last disassembly 57 mutable const SymbolTable *cachedSymtab; 58 59 /// Constructor 60 PCDependentDisassembly(const char *mnem, MachInst _machInst, 61 OpClass __opClass) 62 : MipsStaticInst(mnem, _machInst, __opClass), 63 cachedPC(0), cachedSymtab(0) 64 { 65 } 66 67 const std::string & 68 disassemble(Addr pc, const SymbolTable *symtab) const; 69 }; 70 71 /** 72 * Base class for branches (PC-relative control transfers), 73 * conditional or unconditional. 74 */ 75 class Branch : public PCDependentDisassembly 76 { 77 protected: 78 /// target address (signed) Displacement . 79 int32_t disp; 80 81 /// Constructor. 82 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 83 : PCDependentDisassembly(mnem, _machInst, __opClass), 84 disp(OFFSET << 2) 85 { 86 //If Bit 17 is 1 then Sign Extend 87 if ( (disp & 0x00020000) > 0 ) { 88 disp |= 0xFFFE0000; 89 } 90 } 91 92 MipsISA::PCState branchTarget(const MipsISA::PCState &branchPC) const; 93 94 /// Explicitly import the otherwise hidden branchTarget 95 using StaticInst::branchTarget; 96 97 std::string 98 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 99 }; 100 101 /** 102 * Base class for jumps (register-indirect control transfers). In 103 * the Mips ISA, these are always unconditional. 104 */ 105 class Jump : public PCDependentDisassembly 106 { 107 protected: 108 109 /// Displacement to target address (signed). 110 int32_t disp; 111 112 uint32_t target; 113 114 public: 115 /// Constructor 116 Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 117 : PCDependentDisassembly(mnem, _machInst, __opClass), 118 disp(JMPTARG << 2) 119 { 120 } 121 122 MipsISA::PCState branchTarget(ThreadContext *tc) const; 123 124 /// Explicitly import the otherwise hidden branchTarget 125 using StaticInst::branchTarget; 126 127 std::string 128 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 129 }; 130}}; 131 132output decoder {{ 133 MipsISA::PCState 134 Branch::branchTarget(const MipsISA::PCState &branchPC) const 135 { 136 MipsISA::PCState target = branchPC; 137 target.advance(); 138 target.npc(branchPC.pc() + sizeof(MachInst) + disp); 139 target.nnpc(target.npc() + sizeof(MachInst)); 140 return target; 141 } 142 143 MipsISA::PCState 144 Jump::branchTarget(ThreadContext *tc) const 145 { 146 MipsISA::PCState target = tc->pcState(); 147 Addr pc = target.pc(); 148 target.advance(); 149 target.npc((pc & 0xF0000000) | disp); 150 target.nnpc(target.npc() + sizeof(MachInst)); 151 return target; 152 } 153 154 const std::string & 155 PCDependentDisassembly::disassemble(Addr pc, 156 const SymbolTable *symtab) const 157 { 158 if (!cachedDisassembly || 159 pc != cachedPC || symtab != cachedSymtab) 160 { 161 if (cachedDisassembly) 162 delete cachedDisassembly; 163 164 cachedDisassembly = 165 new std::string(generateDisassembly(pc, symtab)); 166 cachedPC = pc; 167 cachedSymtab = symtab; 168 } 169 170 return *cachedDisassembly; 171 } 172 173 std::string 174 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 175 { 176 std::stringstream ss; 177 178 ccprintf(ss, "%-10s ", mnemonic); 179 180 // There's only one register arg (RA), but it could be 181 // either a source (the condition for conditional 182 // branches) or a destination (the link reg for 183 // unconditional branches) 184 if (_numSrcRegs == 1) { 185 printReg(ss, _srcRegIdx[0]); 186 ss << ", "; 187 } else if(_numSrcRegs == 2) { 188 printReg(ss, _srcRegIdx[0]); 189 ss << ", "; 190 printReg(ss, _srcRegIdx[1]); 191 ss << ", "; 192 } 193 194 Addr target = pc + 4 + disp; 195 196 std::string str; 197 if (symtab && symtab->findSymbol(target, str)) 198 ss << str; 199 else 200 ccprintf(ss, "0x%x", target); 201 202 return ss.str(); 203 } 204 205 std::string 206 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 207 { 208 std::stringstream ss; 209 210 ccprintf(ss, "%-10s ", mnemonic); 211 212 if ( strcmp(mnemonic,"jal") == 0 ) { 213 Addr npc = pc + 4; 214 ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); 215 } else if (_numSrcRegs == 0) { 216 std::string str; 217 if (symtab && symtab->findSymbol(disp, str)) 218 ss << str; 219 else 220 ccprintf(ss, "0x%x", disp); 221 } else if (_numSrcRegs == 1) { 222 printReg(ss, _srcRegIdx[0]); 223 } else if(_numSrcRegs == 2) { 224 printReg(ss, _srcRegIdx[0]); 225 ss << ", "; 226 printReg(ss, _srcRegIdx[1]); 227 } 228 229 return ss.str(); 230 } 231}}; 232 233def format Branch(code, *opt_flags) {{ 234 not_taken_code = 'NNPC = NNPC; NPC = NPC;' 235 236 #Build Instruction Flags 237 #Use Link & Likely Flags to Add Link/Condition Code 238 inst_flags = ('IsDirectControl', ) 239 for x in opt_flags: 240 if x == 'Link': 241 code += 'R31 = NNPC;\n' 242 elif x == 'Likely': 243 not_taken_code = 'NNPC = NPC; NPC = PC;' 244 inst_flags += ('IsCondDelaySlot', ) 245 else: 246 inst_flags += (x, ) 247 248 #Take into account uncond. branch instruction 249 if 'cond = 1' in code: 250 inst_flags += ('IsUncondControl', ) 251 else: 252 inst_flags += ('IsCondControl', ) 253 254 #Condition code 255 code = ''' 256 bool cond; 257 %(code)s 258 if (cond) { 259 NNPC = NPC + disp; 260 } else { 261 %(not_taken_code)s 262 } 263 ''' % { "code" : code, "not_taken_code" : not_taken_code } 264 265 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 266 header_output = BasicDeclare.subst(iop) 267 decoder_output = BasicConstructor.subst(iop) 268 decode_block = BasicDecode.subst(iop) 269 exec_output = BasicExecute.subst(iop) 270}}; 271 272def format DspBranch(code, *opt_flags) {{ 273 not_taken_code = 'NNPC = NNPC; NPC = NPC;' 274 275 #Build Instruction Flags 276 #Use Link & Likely Flags to Add Link/Condition Code 277 inst_flags = ('IsDirectControl', ) 278 for x in opt_flags: 279 if x == 'Link': 280 code += 'R32 = NNPC;' 281 elif x == 'Likely': 282 not_taken_code = 'NNPC = NPC, NPC = PC;' 283 inst_flags += ('IsCondDelaySlot', ) 284 else: 285 inst_flags += (x, ) 286 287 #Take into account uncond. branch instruction 288 if 'cond = 1' in code: 289 inst_flags += ('IsUncondControl', ) 290 else: 291 inst_flags += ('IsCondControl', ) 292 293 #Condition code 294 code = ''' 295 bool cond; 296 uint32_t dspctl = DSPControl; 297 %(code)s 298 if (cond) { 299 NNPC = NPC + disp; 300 } else { 301 %(not_taken_code)s 302 } 303 ''' % { "code" : code, "not_taken_code" : not_taken_code } 304 305 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 306 header_output = BasicDeclare.subst(iop) 307 decoder_output = BasicConstructor.subst(iop) 308 decode_block = BasicDecode.subst(iop) 309 exec_output = BasicExecute.subst(iop) 310}}; 311 312def format Jump(code, *opt_flags) {{ 313 #Build Instruction Flags 314 #Use Link Flag to Add Link Code 315 inst_flags = ('IsIndirectControl', 'IsUncondControl') 316 for x in opt_flags: 317 if x == 'Link': 318 code = ''' 319 R31 = NNPC; 320 ''' + code 321 elif x == 'ClearHazards': 322 code += '/* Code Needed to Clear Execute & Inst Hazards */\n' 323 else: 324 inst_flags += (x, ) 325 326 iop = InstObjParams(name, Name, 'Jump', code, inst_flags) 327 header_output = BasicDeclare.subst(iop) 328 decoder_output = BasicConstructor.subst(iop) 329 decode_block = BasicDecode.subst(iop) 330 exec_output = BasicExecute.subst(iop) 331}}; 332 333 334 335 336