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