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