branch.hh revision 7811
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 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 92}; 93 94/** 95 * Base class for unconditional, non PC-relative branches. 96 */ 97class BranchNonPCRel : public PCDependentDisassembly 98{ 99 protected: 100 101 /// Target address 102 uint32_t targetAddr; 103 104 /// Constructor. 105 BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) 106 : PCDependentDisassembly(mnem, _machInst, __opClass), 107 targetAddr(machInst.li << 2) 108 { 109 // If bit 26 is 1 then sign extend 110 if (targetAddr & 0x2000000) { 111 targetAddr |= 0xfc000000; 112 } 113 } 114 115 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 116 117 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 118}; 119 120/** 121 * Base class for conditional branches. 122 */ 123class BranchCond : public PCDependentDisassembly 124{ 125 protected: 126 127 /// Fields needed for conditions 128 uint32_t bo; 129 uint32_t bi; 130 131 /// Constructor. 132 BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass) 133 : PCDependentDisassembly(mnem, _machInst, __opClass), 134 bo(machInst.bo), 135 bi(machInst.bi) 136 { 137 } 138 139 inline bool 140 ctrOk(uint32_t& ctr) const 141 { 142 bool ctr_ok; 143 if (bo & 4) { 144 ctr_ok = true; 145 } else { 146 ctr--; 147 if (ctr != 0) { 148 ctr_ok = ((bo & 2) == 0); 149 } else { 150 ctr_ok = ((bo & 2) != 0); 151 } 152 } 153 return ctr_ok; 154 } 155 156 inline bool 157 condOk(uint32_t cr) const 158 { 159 bool cond_ok; 160 if (bo & 16) { 161 cond_ok = true; 162 } else { 163 cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1)); 164 } 165 return cond_ok; 166 } 167}; 168 169/** 170 * Base class for conditional, PC-relative branches. 171 */ 172class BranchPCRelCond : public BranchCond 173{ 174 protected: 175 176 /// Displacement 177 uint32_t disp; 178 179 /// Constructor. 180 BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) 181 : BranchCond(mnem, _machInst, __opClass), 182 disp(machInst.bd << 2) 183 { 184 // If bit 16 is 1 then sign extend 185 if (disp & 0x8000) { 186 disp |= 0xffff0000; 187 } 188 } 189 190 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 191 192 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 193}; 194 195/** 196 * Base class for conditional, non PC-relative branches. 197 */ 198class BranchNonPCRelCond : public BranchCond 199{ 200 protected: 201 202 /// Target address 203 uint32_t targetAddr; 204 205 /// Constructor. 206 BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) 207 : BranchCond(mnem, _machInst, __opClass), 208 targetAddr(machInst.bd << 2) 209 { 210 // If bit 16 is 1 then sign extend 211 if (targetAddr & 0x8000) { 212 targetAddr |= 0xffff0000; 213 } 214 } 215 216 PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; 217 218 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 219}; 220 221/** 222 * Base class for conditional, register-based branches 223 */ 224class BranchRegCond : public BranchCond 225{ 226 protected: 227 228 /// Constructor. 229 BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass) 230 : BranchCond(mnem, _machInst, __opClass) 231 { 232 } 233 234 PowerISA::PCState branchTarget(ThreadContext *tc) const; 235 236 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 237}; 238 239} // namespace PowerISA 240 241#endif //__ARCH_POWER_INSTS_BRANCH_HH__ 242