branch.isa revision 12106:7784fac1b159
1// -*- mode:c++ -*- 2 3// Copyright (c) 2003-2005 The Regents of The University of Michigan 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: Steve Reinhardt 30 31//////////////////////////////////////////////////////////////////// 32// 33// Control transfer instructions 34// 35 36output header {{ 37 38 /** 39 * Base class for instructions whose disassembly is not purely a 40 * function of the machine instruction (i.e., it depends on the 41 * PC). This class overrides the disassemble() method to check 42 * the PC and symbol table values before re-using a cached 43 * disassembly string. This is necessary for branches and jumps, 44 * where the disassembly string includes the target address (which 45 * may depend on the PC and/or symbol table). 46 */ 47 class PCDependentDisassembly : public AlphaStaticInst 48 { 49 protected: 50 /// Cached program counter from last disassembly 51 mutable Addr cachedPC; 52 /// Cached symbol table pointer from last disassembly 53 mutable const SymbolTable *cachedSymtab; 54 55 /// Constructor 56 PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, 57 OpClass __opClass) 58 : AlphaStaticInst(mnem, _machInst, __opClass), 59 cachedPC(0), cachedSymtab(0) 60 { 61 } 62 63 const std::string & 64 disassemble(Addr pc, const SymbolTable *symtab) const; 65 }; 66 67 /** 68 * Base class for branches (PC-relative control transfers), 69 * conditional or unconditional. 70 */ 71 class Branch : public PCDependentDisassembly 72 { 73 protected: 74 /// Displacement to target address (signed). 75 int32_t disp; 76 77 /// Constructor. 78 Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 79 : PCDependentDisassembly(mnem, _machInst, __opClass), 80 disp(BRDISP << 2) 81 { 82 } 83 84 AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const; 85 86 /// Explicitly import the otherwise hidden branchTarget 87 using StaticInst::branchTarget; 88 89 std::string 90 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 91 }; 92 93 /** 94 * Base class for jumps (register-indirect control transfers). In 95 * the Alpha ISA, these are always unconditional. 96 */ 97 class Jump : public PCDependentDisassembly 98 { 99 protected: 100 101 /// Displacement to target address (signed). 102 int32_t disp; 103 104 public: 105 /// Constructor 106 Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 107 : PCDependentDisassembly(mnem, _machInst, __opClass), 108 disp(BRDISP) 109 { 110 } 111 112 AlphaISA::PCState branchTarget(ThreadContext *tc) const; 113 114 /// Explicitly import the otherwise hidden branchTarget 115 using StaticInst::branchTarget; 116 117 std::string 118 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 119 }; 120}}; 121 122output decoder {{ 123 AlphaISA::PCState 124 Branch::branchTarget(const AlphaISA::PCState &branchPC) const 125 { 126 return branchPC.pc() + 4 + disp; 127 } 128 129 AlphaISA::PCState 130 Jump::branchTarget(ThreadContext *tc) const 131 { 132 PCState pc = tc->pcState(); 133 uint64_t Rb = tc->readIntReg(_srcRegIdx[0].index()); 134 pc.set((Rb & ~3) | (pc.pc() & 1)); 135 return pc; 136 } 137 138 const std::string & 139 PCDependentDisassembly::disassemble(Addr pc, 140 const SymbolTable *symtab) const 141 { 142 if (!cachedDisassembly || 143 pc != cachedPC || symtab != cachedSymtab) 144 { 145 if (cachedDisassembly) 146 delete cachedDisassembly; 147 148 cachedDisassembly = 149 new std::string(generateDisassembly(pc, symtab)); 150 cachedPC = pc; 151 cachedSymtab = symtab; 152 } 153 154 return *cachedDisassembly; 155 } 156 157 std::string 158 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 159 { 160 std::stringstream ss; 161 162 ccprintf(ss, "%-10s ", mnemonic); 163 164 // There's only one register arg (RA), but it could be 165 // either a source (the condition for conditional 166 // branches) or a destination (the link reg for 167 // unconditional branches) 168 if (_numSrcRegs > 0) { 169 printReg(ss, _srcRegIdx[0]); 170 ss << ","; 171 } 172 else if (_numDestRegs > 0) { 173 printReg(ss, _destRegIdx[0]); 174 ss << ","; 175 } 176 177#ifdef SS_COMPATIBLE_DISASSEMBLY 178 if (_numSrcRegs == 0 && _numDestRegs == 0) { 179 printReg(ss, 31); 180 ss << ","; 181 } 182#endif 183 184 Addr target = pc + 4 + disp; 185 186 std::string str; 187 if (symtab && symtab->findSymbol(target, str)) 188 ss << str; 189 else 190 ccprintf(ss, "0x%x", target); 191 192 return ss.str(); 193 } 194 195 std::string 196 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 197 { 198 std::stringstream ss; 199 200 ccprintf(ss, "%-10s ", mnemonic); 201 202#ifdef SS_COMPATIBLE_DISASSEMBLY 203 if (_numDestRegs == 0) { 204 printReg(ss, 31); 205 ss << ","; 206 } 207#endif 208 209 if (_numDestRegs > 0) { 210 printReg(ss, _destRegIdx[0]); 211 ss << ","; 212 } 213 214 ccprintf(ss, "(r%d)", RB); 215 216 return ss.str(); 217 } 218}}; 219 220def template JumpOrBranchDecode {{ 221 return (RA == 31) 222 ? (StaticInst *)new %(class_name)s(machInst) 223 : (StaticInst *)new %(class_name)sAndLink(machInst); 224}}; 225 226def format CondBranch(code) {{ 227 code = ''' 228 bool cond; 229 %(code)s; 230 if (cond) 231 NPC = NPC + disp; 232 else 233 NPC = NPC; 234 ''' % { "code" : code } 235 iop = InstObjParams(name, Name, 'Branch', code, 236 ('IsDirectControl', 'IsCondControl')) 237 header_output = BasicDeclare.subst(iop) 238 decoder_output = BasicConstructor.subst(iop) 239 decode_block = BasicDecode.subst(iop) 240 exec_output = BasicExecute.subst(iop) 241}}; 242 243let {{ 244def UncondCtrlBase(name, Name, base_class, npc_expr, flags): 245 # Declare basic control transfer w/o link (i.e. link reg is R31) 246 nolink_code = 'NPC = %s;\n' % npc_expr 247 nolink_iop = InstObjParams(name, Name, base_class, 248 nolink_code, flags) 249 header_output = BasicDeclare.subst(nolink_iop) 250 decoder_output = BasicConstructor.subst(nolink_iop) 251 exec_output = BasicExecute.subst(nolink_iop) 252 253 # Generate declaration of '*AndLink' version, append to decls 254 link_code = 'Ra = NPC & ~3;\n' + nolink_code 255 link_iop = InstObjParams(name, Name + 'AndLink', base_class, 256 link_code, flags) 257 header_output += BasicDeclare.subst(link_iop) 258 decoder_output += BasicConstructor.subst(link_iop) 259 exec_output += BasicExecute.subst(link_iop) 260 261 # need to use link_iop for the decode template since it is expecting 262 # the shorter version of class_name (w/o "AndLink") 263 264 return (header_output, decoder_output, 265 JumpOrBranchDecode.subst(nolink_iop), exec_output) 266}}; 267 268def format UncondBranch(*flags) {{ 269 flags += ('IsUncondControl', 'IsDirectControl') 270 (header_output, decoder_output, decode_block, exec_output) = \ 271 UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) 272}}; 273 274def format Jump(*flags) {{ 275 flags += ('IsUncondControl', 'IsIndirectControl') 276 (header_output, decoder_output, decode_block, exec_output) = \ 277 UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) 278}}; 279 280 281