branch.hh revision 12616:4b463b4dc098
12SN/A/* Copyright (c) 2007-2008 The Florida State University
21762SN/A * Copyright (c) 2009 The University of Edinburgh
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Timothy M. Jones
292665Ssaidi@eecs.umich.edu */
302SN/A
312SN/A#ifndef __ARCH_POWER_INSTS_BRANCH_HH__
322SN/A#define __ARCH_POWER_INSTS_BRANCH_HH__
332SN/A
342SN/A#include "arch/power/insts/static_inst.hh"
351984SN/A
36857SN/Anamespace PowerISA
375952Ssaidi@eecs.umich.edu{
381984SN/A
396214Snate@binkert.org/**
402SN/A * Base class for instructions whose disassembly is not purely a
411984SN/A * function of the machine instruction (i.e., it depends on the
422SN/A * PC).  This class overrides the disassemble() method to check
432SN/A * the PC and symbol table values before re-using a cached
441912SN/A * disassembly string.  This is necessary for branches and jumps,
452130SN/A * where the disassembly string includes the target address (which
46857SN/A * may depend on the PC and/or symbol table).
472SN/A */
481912SN/Aclass PCDependentDisassembly : public PowerStaticInst
492SN/A{
502SN/A  protected:
512SN/A    /// Cached program counter from last disassembly
521912SN/A    mutable Addr cachedPC;
531912SN/A    /// Cached symbol table pointer from last disassembly
541912SN/A    mutable const SymbolTable *cachedSymtab;
551912SN/A
561912SN/A    /// Constructor
571912SN/A    PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
581912SN/A                           OpClass __opClass)
591912SN/A        : PowerStaticInst(mnem, _machInst, __opClass),
601912SN/A          cachedPC(0), cachedSymtab(0)
611912SN/A    {
621912SN/A    }
631912SN/A
641912SN/A    const std::string &
651912SN/A    disassemble(Addr pc, const SymbolTable *symtab) const;
662SN/A};
672SN/A
682SN/A/**
692SN/A * Base class for unconditional, PC-relative branches.
702SN/A */
711984SN/Aclass BranchPCRel : public PCDependentDisassembly
722SN/A{
732SN/A  protected:
742SN/A
751912SN/A    /// Displacement
761912SN/A    uint32_t disp;
771912SN/A
781912SN/A    /// Constructor.
791984SN/A    BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
801984SN/A        : PCDependentDisassembly(mnem, _machInst, __opClass),
811984SN/A          disp(machInst.li << 2)
821984SN/A    {
831984SN/A        // If bit 26 is 1 then sign extend
841912SN/A        if (disp & 0x2000000) {
851912SN/A            disp |= 0xfc000000;
861912SN/A        }
871912SN/A    }
881912SN/A
891912SN/A    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
901912SN/A
911912SN/A    /// Explicitly import the otherwise hidden branchTarget
921912SN/A    using StaticInst::branchTarget;
931912SN/A
941912SN/A    std::string generateDisassembly(
951912SN/A            Addr pc, const SymbolTable *symtab) const override;
961912SN/A};
971912SN/A
981912SN/A/**
991912SN/A * Base class for unconditional, non PC-relative branches.
1001912SN/A */
1011912SN/Aclass BranchNonPCRel : public PCDependentDisassembly
1021912SN/A{
1031912SN/A  protected:
1041912SN/A
1051912SN/A    /// Target address
1061158SN/A    uint32_t targetAddr;
1071158SN/A
1082982Sstever@eecs.umich.edu    /// Constructor.
1092982Sstever@eecs.umich.edu    BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
1102982Sstever@eecs.umich.edu        : PCDependentDisassembly(mnem, _machInst, __opClass),
1112982Sstever@eecs.umich.edu          targetAddr(machInst.li << 2)
1122982Sstever@eecs.umich.edu    {
1131158SN/A        // If bit 26 is 1 then sign extend
1141912SN/A        if (targetAddr & 0x2000000) {
1151912SN/A            targetAddr |= 0xfc000000;
1161912SN/A        }
1171912SN/A    }
1181912SN/A
1191912SN/A    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
1201912SN/A
1211912SN/A    /// Explicitly import the otherwise hidden branchTarget
1221912SN/A    using StaticInst::branchTarget;
1231912SN/A
1241912SN/A    std::string generateDisassembly(
1251912SN/A            Addr pc, const SymbolTable *symtab) const override;
1261912SN/A};
1271912SN/A
1281158SN/A/**
1291158SN/A * Base class for conditional branches.
1302982Sstever@eecs.umich.edu */
1311912SN/Aclass BranchCond : public PCDependentDisassembly
1321912SN/A{
1331158SN/A  protected:
1341912SN/A
1351912SN/A    /// Fields needed for conditions
1361912SN/A    uint32_t bo;
1371912SN/A    uint32_t bi;
1381912SN/A
1391912SN/A    /// Constructor.
1401912SN/A    BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass)
1411912SN/A        : PCDependentDisassembly(mnem, _machInst, __opClass),
1421158SN/A          bo(machInst.bo),
1431158SN/A          bi(machInst.bi)
1441158SN/A    {
1451912SN/A    }
1461912SN/A
1471912SN/A    inline bool
1481912SN/A    ctrOk(uint32_t& ctr) const
1491912SN/A    {
1501912SN/A        bool ctr_ok;
1511912SN/A        if (bo & 4) {
1521912SN/A            ctr_ok = true;
1531912SN/A        } else {
1541912SN/A            ctr--;
1551912SN/A            if (ctr != 0) {
1561912SN/A                ctr_ok = ((bo & 2) == 0);
1571912SN/A            } else {
1581912SN/A                ctr_ok = ((bo & 2) != 0);
1591912SN/A            }
1601912SN/A        }
1611912SN/A        return ctr_ok;
1621912SN/A    }
1631912SN/A
1641912SN/A    inline bool
1651912SN/A    condOk(uint32_t cr) const
1661912SN/A    {
1671912SN/A        bool cond_ok;
1681912SN/A        if (bo & 16) {
1692SN/A            cond_ok = true;
1702SN/A        } else {
1711158SN/A            cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1));
1721158SN/A        }
1731158SN/A        return cond_ok;
1741158SN/A    }
1751158SN/A};
1761158SN/A
1772SN/A/**
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