branch.isa revision 6019:76890d8b28f5
1// -*- mode:c++ -*- 2 3// Copyright (c) 2007-2008 The Florida State University 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: Stephen Hines 30 31//////////////////////////////////////////////////////////////////// 32// 33// Control transfer instructions 34// 35 36output header {{ 37 38#include <iostream> 39 40 /** 41 * Base class for instructions whose disassembly is not purely a 42 * function of the machine instruction (i.e., it depends on the 43 * PC). This class overrides the disassemble() method to check 44 * the PC and symbol table values before re-using a cached 45 * disassembly string. This is necessary for branches and jumps, 46 * where the disassembly string includes the target address (which 47 * may depend on the PC and/or symbol table). 48 */ 49 class PCDependentDisassembly : public PredOp 50 { 51 protected: 52 /// Cached program counter from last disassembly 53 mutable Addr cachedPC; 54 55 /// Cached symbol table pointer from last disassembly 56 mutable const SymbolTable *cachedSymtab; 57 58 /// Constructor 59 PCDependentDisassembly(const char *mnem, MachInst _machInst, 60 OpClass __opClass) 61 : PredOp(mnem, _machInst, __opClass), 62 cachedPC(0), cachedSymtab(0) 63 { 64 } 65 66 const std::string & 67 disassemble(Addr pc, const SymbolTable *symtab) const; 68 }; 69 70 /** 71 * Base class for branches (PC-relative control transfers), 72 * conditional or unconditional. 73 */ 74 class Branch : public PCDependentDisassembly 75 { 76 protected: 77 /// target address (signed) Displacement . 78 int32_t disp; 79 80 /// Constructor. 81 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 82 : PCDependentDisassembly(mnem, _machInst, __opClass), 83 disp(OFFSET << 2) 84 { 85 //If Bit 26 is 1 then Sign Extend 86 if ( (disp & 0x02000000) > 0 ) { 87 disp |= 0xFC000000; 88 } 89 } 90 91 Addr branchTarget(Addr branchPC) const; 92 93 std::string 94 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 95 }; 96 97 /** 98 * Base class for branch and exchange instructions on the ARM 99 */ 100 class BranchExchange : public PredOp 101 { 102 protected: 103 /// Constructor 104 BranchExchange(const char *mnem, MachInst _machInst, 105 OpClass __opClass) 106 : PredOp(mnem, _machInst, __opClass) 107 { 108 } 109 110 std::string 111 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 112 }; 113 114 115 /** 116 * Base class for jumps (register-indirect control transfers). In 117 * the Arm ISA, these are always unconditional. 118 */ 119 class Jump : public PCDependentDisassembly 120 { 121 protected: 122 123 /// Displacement to target address (signed). 124 int32_t disp; 125 126 uint32_t target; 127 128 public: 129 /// Constructor 130 Jump(const char *mnem, MachInst _machInst, OpClass __opClass) 131 : PCDependentDisassembly(mnem, _machInst, __opClass), 132 disp(OFFSET << 2) 133 { 134 } 135 136 Addr branchTarget(ThreadContext *tc) const; 137 138 std::string 139 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 140 }; 141}}; 142 143output decoder {{ 144 Addr 145 Branch::branchTarget(Addr branchPC) const 146 { 147 return branchPC + 8 + disp; 148 } 149 150 Addr 151 Jump::branchTarget(ThreadContext *tc) const 152 { 153 Addr NPC = tc->readPC() + 8; 154 uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); 155 return (Rb & ~3) | (NPC & 1); 156 } 157 158 const std::string & 159 PCDependentDisassembly::disassemble(Addr pc, 160 const SymbolTable *symtab) const 161 { 162 if (!cachedDisassembly || 163 pc != cachedPC || symtab != cachedSymtab) 164 { 165 if (cachedDisassembly) 166 delete cachedDisassembly; 167 168 cachedDisassembly = 169 new std::string(generateDisassembly(pc, symtab)); 170 cachedPC = pc; 171 cachedSymtab = symtab; 172 } 173 174 return *cachedDisassembly; 175 } 176 177 std::string 178 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 179 { 180 std::stringstream ss; 181 182 ccprintf(ss, "%-10s ", mnemonic); 183 184 Addr target = pc + 8 + 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 BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const 197 { 198 std::stringstream ss; 199 200 ccprintf(ss, "%-10s ", mnemonic); 201 202 if (_numSrcRegs > 0) { 203 printReg(ss, _srcRegIdx[0]); 204 } 205 206 return ss.str(); 207 } 208 209 std::string 210 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 211 { 212 std::stringstream ss; 213 214 ccprintf(ss, "%-10s ", mnemonic); 215 216 return ss.str(); 217 } 218}}; 219 220def format Branch(code,*opt_flags) {{ 221 222 #Build Instruction Flags 223 #Use Link & Likely Flags to Add Link/Condition Code 224 inst_flags = ('IsDirectControl', ) 225 for x in opt_flags: 226 if x == 'Link': 227 code += 'LR = NPC;\n' 228 else: 229 inst_flags += (x, ) 230 231 #Take into account uncond. branch instruction 232 if 'cond == 1' in code: 233 inst_flags += ('IsUnCondControl', ) 234 else: 235 inst_flags += ('IsCondControl', ) 236 237 icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n' 238 icode += code 239 icode += ' NPC = NPC + 4 + disp;\n' 240 icode += '} else {\n' 241 icode += ' NPC = NPC;\n' 242 icode += '};\n' 243 244 code = icode 245 246 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 247 header_output = BasicDeclare.subst(iop) 248 decoder_output = BasicConstructor.subst(iop) 249 decode_block = BasicDecode.subst(iop) 250 exec_output = BasicExecute.subst(iop) 251}}; 252 253def format BranchExchange(code,*opt_flags) {{ 254 #Build Instruction Flags 255 #Use Link & Likely Flags to Add Link/Condition Code 256 inst_flags = ('IsIndirectControl', ) 257 for x in opt_flags: 258 if x == 'Link': 259 code += 'LR = NPC;\n' 260 else: 261 inst_flags += (x, ) 262 263 #Take into account uncond. branch instruction 264 if 'cond == 1' in code: 265 inst_flags += ('IsUnCondControl', ) 266 else: 267 inst_flags += ('IsCondControl', ) 268 269 #Condition code 270 271 icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n' 272 icode += code 273 icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n' 274 icode += '} else {\n' 275 icode += ' NPC = NPC;\n' 276 icode += '};\n' 277 278 code = icode 279 280 iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags) 281 header_output = BasicDeclare.subst(iop) 282 decoder_output = BasicConstructor.subst(iop) 283 decode_block = BasicDecode.subst(iop) 284 exec_output = BasicExecute.subst(iop) 285}}; 286 287def format Jump(code, *opt_flags) {{ 288 #Build Instruction Flags 289 #Use Link Flag to Add Link Code 290 inst_flags = ('IsIndirectControl', 'IsUncondControl') 291 for x in opt_flags: 292 if x == 'Link': 293 code = 'LR = NPC;\n' + code 294 elif x == 'ClearHazards': 295 code += '/* Code Needed to Clear Execute & Inst Hazards */\n' 296 else: 297 inst_flags += (x, ) 298 299 iop = InstObjParams(name, Name, 'Jump', code, inst_flags) 300 header_output = BasicDeclare.subst(iop) 301 decoder_output = BasicConstructor.subst(iop) 302 decode_block = BasicDecode.subst(iop) 303 exec_output = BasicExecute.subst(iop) 304 #exec_output = PredOpExecute.subst(iop) 305}}; 306 307 308