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