branch.hh revision 9552:460cf901acba
1/* Copyright (c) 2007-2008 The Florida State University 2 * Copyright (c) 2009 The University of Edinburgh 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Timothy M. Jones 29 */ 30 31#ifndef __ARCH_POWER_INSTS_BRANCH_HH__ 32#define __ARCH_POWER_INSTS_BRANCH_HH__ 33 34#include "arch/power/insts/static_inst.hh" 35 36namespace PowerISA 37{ 38 39/** 40 * Base class for instructions whose disassembly is not purely a 41 * function of the machine instruction (i.e., it depends on the 42 * PC). This class overrides the disassemble() method to check 43 * the PC and symbol table values before re-using a cached 44 * disassembly string. This is necessary for branches and jumps, 45 * where the disassembly string includes the target address (which 46 * may depend on the PC and/or symbol table). 47 */ 48class PCDependentDisassembly : public PowerStaticInst 49{ 50 protected: 51 /// Cached program counter from last disassembly 52 mutable Addr cachedPC; 53 /// Cached symbol table pointer from last disassembly 54 mutable const SymbolTable *cachedSymtab; 55 56 /// Constructor 57 PCDependentDisassembly(const char *mnem, ExtMachInst _machInst, 58 OpClass __opClass) 59 : PowerStaticInst(mnem, _machInst, __opClass), 60 cachedPC(0), cachedSymtab(0) 61 { 62 } 63 64 const std::string & 65 disassemble(Addr pc, const SymbolTable *symtab) const; 66}; 67 68/** 69 * Base class for unconditional, PC-relative branches. 70 */ 71class BranchPCRel : public PCDependentDisassembly 72{ 73 protected: 74 75 /// Displacement 76 uint32_t disp; 77 78 /// Constructor. 79 BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) 80 : PCDependentDisassembly(mnem, _machInst, __opClass), 81 disp(machInst.li << 2) 82 { 83 // If bit 26 is 1 then sign extend 84 if (disp & 0x2000000) { 85 disp |= 0xfc000000; 86 } 87 } 88 89 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 90 91 /// Explicitly import the otherwise hidden branchTarget 92 using StaticInst::branchTarget; 93 94 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 95}; 96 97/** 98 * Base class for unconditional, non PC-relative branches. 99 */ 100class BranchNonPCRel : public PCDependentDisassembly 101{ 102 protected: 103 104 /// Target address 105 uint32_t targetAddr; 106 107 /// Constructor. 108 BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) 109 : PCDependentDisassembly(mnem, _machInst, __opClass), 110 targetAddr(machInst.li << 2) 111 { 112 // If bit 26 is 1 then sign extend 113 if (targetAddr & 0x2000000) { 114 targetAddr |= 0xfc000000; 115 } 116 } 117 118 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 119 120 /// Explicitly import the otherwise hidden branchTarget 121 using StaticInst::branchTarget; 122 123 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 124}; 125 126/** 127 * Base class for conditional branches. 128 */ 129class BranchCond : public PCDependentDisassembly 130{ 131 protected: 132 133 /// Fields needed for conditions 134 uint32_t bo; 135 uint32_t bi; 136 137 /// Constructor. 138 BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass) 139 : PCDependentDisassembly(mnem, _machInst, __opClass), 140 bo(machInst.bo), 141 bi(machInst.bi) 142 { 143 } 144 145 inline bool 146 ctrOk(uint32_t& ctr) const 147 { 148 bool ctr_ok; 149 if (bo & 4) { 150 ctr_ok = true; 151 } else { 152 ctr--; 153 if (ctr != 0) { 154 ctr_ok = ((bo & 2) == 0); 155 } else { 156 ctr_ok = ((bo & 2) != 0); 157 } 158 } 159 return ctr_ok; 160 } 161 162 inline bool 163 condOk(uint32_t cr) const 164 { 165 bool cond_ok; 166 if (bo & 16) { 167 cond_ok = true; 168 } else { 169 cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1)); 170 } 171 return cond_ok; 172 } 173}; 174 175/** 176 * Base class for conditional, PC-relative branches. 177 */ 178class BranchPCRelCond : public BranchCond 179{ 180 protected: 181 182 /// Displacement 183 uint32_t disp; 184 185 /// Constructor. 186 BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) 187 : BranchCond(mnem, _machInst, __opClass), 188 disp(machInst.bd << 2) 189 { 190 // If bit 16 is 1 then sign extend 191 if (disp & 0x8000) { 192 disp |= 0xffff0000; 193 } 194 } 195 196 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 197 198 /// Explicitly import the otherwise hidden branchTarget 199 using StaticInst::branchTarget; 200 201 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 202}; 203 204/** 205 * Base class for conditional, non PC-relative branches. 206 */ 207class BranchNonPCRelCond : public BranchCond 208{ 209 protected: 210 211 /// Target address 212 uint32_t targetAddr; 213 214 /// Constructor. 215 BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) 216 : BranchCond(mnem, _machInst, __opClass), 217 targetAddr(machInst.bd << 2) 218 { 219 // If bit 16 is 1 then sign extend 220 if (targetAddr & 0x8000) { 221 targetAddr |= 0xffff0000; 222 } 223 } 224 225 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 226 227 /// Explicitly import the otherwise hidden branchTarget 228 using StaticInst::branchTarget; 229 230 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 231}; 232 233/** 234 * Base class for conditional, register-based branches 235 */ 236class BranchRegCond : public BranchCond 237{ 238 protected: 239 240 /// Constructor. 241 BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass) 242 : BranchCond(mnem, _machInst, __opClass) 243 { 244 } 245 246 PowerISA::PCState branchTarget(ThreadContext *tc) const; 247 248 /// Explicitly import the otherwise hidden branchTarget 249 using StaticInst::branchTarget; 250 251 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 252}; 253 254} // namespace PowerISA 255 256#endif //__ARCH_POWER_INSTS_BRANCH_HH__ 257