16691Stjones1@inf.ed.ac.uk/* Copyright (c) 2007-2008 The Florida State University
26691Stjones1@inf.ed.ac.uk * Copyright (c) 2009 The University of Edinburgh
36691Stjones1@inf.ed.ac.uk * All rights reserved.
46691Stjones1@inf.ed.ac.uk *
56691Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without
66691Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are
76691Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright
86691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer;
96691Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright
106691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the
116691Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution;
126691Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its
136691Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from
146691Stjones1@inf.ed.ac.uk * this software without specific prior written permission.
156691Stjones1@inf.ed.ac.uk *
166691Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176691Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186691Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196691Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206691Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216691Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226691Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236691Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246691Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256691Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266691Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276691Stjones1@inf.ed.ac.uk *
286691Stjones1@inf.ed.ac.uk * Authors: Timothy M. Jones
296691Stjones1@inf.ed.ac.uk */
306691Stjones1@inf.ed.ac.uk
316691Stjones1@inf.ed.ac.uk#ifndef __ARCH_POWER_INSTS_BRANCH_HH__
326691Stjones1@inf.ed.ac.uk#define __ARCH_POWER_INSTS_BRANCH_HH__
336691Stjones1@inf.ed.ac.uk
346691Stjones1@inf.ed.ac.uk#include "arch/power/insts/static_inst.hh"
356691Stjones1@inf.ed.ac.uk
366691Stjones1@inf.ed.ac.uknamespace PowerISA
376691Stjones1@inf.ed.ac.uk{
386691Stjones1@inf.ed.ac.uk
396691Stjones1@inf.ed.ac.uk/**
406691Stjones1@inf.ed.ac.uk * Base class for instructions whose disassembly is not purely a
416691Stjones1@inf.ed.ac.uk * function of the machine instruction (i.e., it depends on the
426691Stjones1@inf.ed.ac.uk * PC).  This class overrides the disassemble() method to check
436691Stjones1@inf.ed.ac.uk * the PC and symbol table values before re-using a cached
446691Stjones1@inf.ed.ac.uk * disassembly string.  This is necessary for branches and jumps,
456691Stjones1@inf.ed.ac.uk * where the disassembly string includes the target address (which
466691Stjones1@inf.ed.ac.uk * may depend on the PC and/or symbol table).
476691Stjones1@inf.ed.ac.uk */
486691Stjones1@inf.ed.ac.ukclass PCDependentDisassembly : public PowerStaticInst
496691Stjones1@inf.ed.ac.uk{
506691Stjones1@inf.ed.ac.uk  protected:
516691Stjones1@inf.ed.ac.uk    /// Cached program counter from last disassembly
526691Stjones1@inf.ed.ac.uk    mutable Addr cachedPC;
536691Stjones1@inf.ed.ac.uk    /// Cached symbol table pointer from last disassembly
546691Stjones1@inf.ed.ac.uk    mutable const SymbolTable *cachedSymtab;
556691Stjones1@inf.ed.ac.uk
566691Stjones1@inf.ed.ac.uk    /// Constructor
576691Stjones1@inf.ed.ac.uk    PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
586691Stjones1@inf.ed.ac.uk                           OpClass __opClass)
596691Stjones1@inf.ed.ac.uk        : PowerStaticInst(mnem, _machInst, __opClass),
606691Stjones1@inf.ed.ac.uk          cachedPC(0), cachedSymtab(0)
616691Stjones1@inf.ed.ac.uk    {
626691Stjones1@inf.ed.ac.uk    }
636691Stjones1@inf.ed.ac.uk
646691Stjones1@inf.ed.ac.uk    const std::string &
656691Stjones1@inf.ed.ac.uk    disassemble(Addr pc, const SymbolTable *symtab) const;
666691Stjones1@inf.ed.ac.uk};
676691Stjones1@inf.ed.ac.uk
686691Stjones1@inf.ed.ac.uk/**
696691Stjones1@inf.ed.ac.uk * Base class for unconditional, PC-relative branches.
706691Stjones1@inf.ed.ac.uk */
716691Stjones1@inf.ed.ac.ukclass BranchPCRel : public PCDependentDisassembly
726691Stjones1@inf.ed.ac.uk{
736691Stjones1@inf.ed.ac.uk  protected:
746691Stjones1@inf.ed.ac.uk
756691Stjones1@inf.ed.ac.uk    /// Displacement
766691Stjones1@inf.ed.ac.uk    uint32_t disp;
776691Stjones1@inf.ed.ac.uk
786691Stjones1@inf.ed.ac.uk    /// Constructor.
796691Stjones1@inf.ed.ac.uk    BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
806691Stjones1@inf.ed.ac.uk        : PCDependentDisassembly(mnem, _machInst, __opClass),
816691Stjones1@inf.ed.ac.uk          disp(machInst.li << 2)
826691Stjones1@inf.ed.ac.uk    {
836691Stjones1@inf.ed.ac.uk        // If bit 26 is 1 then sign extend
846691Stjones1@inf.ed.ac.uk        if (disp & 0x2000000) {
856691Stjones1@inf.ed.ac.uk            disp |= 0xfc000000;
866691Stjones1@inf.ed.ac.uk        }
876691Stjones1@inf.ed.ac.uk    }
886691Stjones1@inf.ed.ac.uk
8912616Sgabeblack@google.com    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
906691Stjones1@inf.ed.ac.uk
919552Sandreas.hansson@arm.com    /// Explicitly import the otherwise hidden branchTarget
929552Sandreas.hansson@arm.com    using StaticInst::branchTarget;
939552Sandreas.hansson@arm.com
9412616Sgabeblack@google.com    std::string generateDisassembly(
9512616Sgabeblack@google.com            Addr pc, const SymbolTable *symtab) const override;
966691Stjones1@inf.ed.ac.uk};
976691Stjones1@inf.ed.ac.uk
986691Stjones1@inf.ed.ac.uk/**
996691Stjones1@inf.ed.ac.uk * Base class for unconditional, non PC-relative branches.
1006691Stjones1@inf.ed.ac.uk */
1016691Stjones1@inf.ed.ac.ukclass BranchNonPCRel : public PCDependentDisassembly
1026691Stjones1@inf.ed.ac.uk{
1036691Stjones1@inf.ed.ac.uk  protected:
1046691Stjones1@inf.ed.ac.uk
1056691Stjones1@inf.ed.ac.uk    /// Target address
1066691Stjones1@inf.ed.ac.uk    uint32_t targetAddr;
1076691Stjones1@inf.ed.ac.uk
1086691Stjones1@inf.ed.ac.uk    /// Constructor.
1096691Stjones1@inf.ed.ac.uk    BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
1106691Stjones1@inf.ed.ac.uk        : PCDependentDisassembly(mnem, _machInst, __opClass),
1116691Stjones1@inf.ed.ac.uk          targetAddr(machInst.li << 2)
1126691Stjones1@inf.ed.ac.uk    {
1136691Stjones1@inf.ed.ac.uk        // If bit 26 is 1 then sign extend
1146691Stjones1@inf.ed.ac.uk        if (targetAddr & 0x2000000) {
1156691Stjones1@inf.ed.ac.uk            targetAddr |= 0xfc000000;
1166691Stjones1@inf.ed.ac.uk        }
1176691Stjones1@inf.ed.ac.uk    }
1186691Stjones1@inf.ed.ac.uk
11912616Sgabeblack@google.com    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
1206691Stjones1@inf.ed.ac.uk
1219552Sandreas.hansson@arm.com    /// Explicitly import the otherwise hidden branchTarget
1229552Sandreas.hansson@arm.com    using StaticInst::branchTarget;
1239552Sandreas.hansson@arm.com
12412616Sgabeblack@google.com    std::string generateDisassembly(
12512616Sgabeblack@google.com            Addr pc, const SymbolTable *symtab) const override;
1266691Stjones1@inf.ed.ac.uk};
1276691Stjones1@inf.ed.ac.uk
1286691Stjones1@inf.ed.ac.uk/**
1296691Stjones1@inf.ed.ac.uk * Base class for conditional branches.
1306691Stjones1@inf.ed.ac.uk */
1316691Stjones1@inf.ed.ac.ukclass BranchCond : public PCDependentDisassembly
1326691Stjones1@inf.ed.ac.uk{
1336691Stjones1@inf.ed.ac.uk  protected:
1346691Stjones1@inf.ed.ac.uk
1356691Stjones1@inf.ed.ac.uk    /// Fields needed for conditions
1366691Stjones1@inf.ed.ac.uk    uint32_t bo;
1376691Stjones1@inf.ed.ac.uk    uint32_t bi;
1386691Stjones1@inf.ed.ac.uk
1396691Stjones1@inf.ed.ac.uk    /// Constructor.
1406691Stjones1@inf.ed.ac.uk    BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass)
1416691Stjones1@inf.ed.ac.uk        : PCDependentDisassembly(mnem, _machInst, __opClass),
1426691Stjones1@inf.ed.ac.uk          bo(machInst.bo),
1436691Stjones1@inf.ed.ac.uk          bi(machInst.bi)
1446691Stjones1@inf.ed.ac.uk    {
1456691Stjones1@inf.ed.ac.uk    }
1466691Stjones1@inf.ed.ac.uk
1476691Stjones1@inf.ed.ac.uk    inline bool
1486691Stjones1@inf.ed.ac.uk    ctrOk(uint32_t& ctr) const
1496691Stjones1@inf.ed.ac.uk    {
1506691Stjones1@inf.ed.ac.uk        bool ctr_ok;
1516691Stjones1@inf.ed.ac.uk        if (bo & 4) {
1526691Stjones1@inf.ed.ac.uk            ctr_ok = true;
1536691Stjones1@inf.ed.ac.uk        } else {
1546691Stjones1@inf.ed.ac.uk            ctr--;
1556691Stjones1@inf.ed.ac.uk            if (ctr != 0) {
1566691Stjones1@inf.ed.ac.uk                ctr_ok = ((bo & 2) == 0);
1576691Stjones1@inf.ed.ac.uk            } else {
1586691Stjones1@inf.ed.ac.uk                ctr_ok = ((bo & 2) != 0);
1596691Stjones1@inf.ed.ac.uk            }
1606691Stjones1@inf.ed.ac.uk        }
1616691Stjones1@inf.ed.ac.uk        return ctr_ok;
1626691Stjones1@inf.ed.ac.uk    }
1636691Stjones1@inf.ed.ac.uk
1646691Stjones1@inf.ed.ac.uk    inline bool
1656691Stjones1@inf.ed.ac.uk    condOk(uint32_t cr) const
1666691Stjones1@inf.ed.ac.uk    {
1676691Stjones1@inf.ed.ac.uk        bool cond_ok;
1686691Stjones1@inf.ed.ac.uk        if (bo & 16) {
1696691Stjones1@inf.ed.ac.uk            cond_ok = true;
1706691Stjones1@inf.ed.ac.uk        } else {
1716691Stjones1@inf.ed.ac.uk            cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1));
1726691Stjones1@inf.ed.ac.uk        }
1736691Stjones1@inf.ed.ac.uk        return cond_ok;
1746691Stjones1@inf.ed.ac.uk    }
1756691Stjones1@inf.ed.ac.uk};
1766691Stjones1@inf.ed.ac.uk
1776691Stjones1@inf.ed.ac.uk/**
1786691Stjones1@inf.ed.ac.uk * Base class for conditional, PC-relative branches.
1796691Stjones1@inf.ed.ac.uk */
1806691Stjones1@inf.ed.ac.ukclass BranchPCRelCond : public BranchCond
1816691Stjones1@inf.ed.ac.uk{
1826691Stjones1@inf.ed.ac.uk  protected:
1836691Stjones1@inf.ed.ac.uk
1846691Stjones1@inf.ed.ac.uk    /// Displacement
1856691Stjones1@inf.ed.ac.uk    uint32_t disp;
1866691Stjones1@inf.ed.ac.uk
1876691Stjones1@inf.ed.ac.uk    /// Constructor.
1886691Stjones1@inf.ed.ac.uk    BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
1896691Stjones1@inf.ed.ac.uk        : BranchCond(mnem, _machInst, __opClass),
1906691Stjones1@inf.ed.ac.uk          disp(machInst.bd << 2)
1916691Stjones1@inf.ed.ac.uk    {
1926691Stjones1@inf.ed.ac.uk        // If bit 16 is 1 then sign extend
1936691Stjones1@inf.ed.ac.uk        if (disp & 0x8000) {
1946691Stjones1@inf.ed.ac.uk            disp |= 0xffff0000;
1956691Stjones1@inf.ed.ac.uk        }
1966691Stjones1@inf.ed.ac.uk    }
1976691Stjones1@inf.ed.ac.uk
19812616Sgabeblack@google.com    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
1996691Stjones1@inf.ed.ac.uk
2009552Sandreas.hansson@arm.com    /// Explicitly import the otherwise hidden branchTarget
2019552Sandreas.hansson@arm.com    using StaticInst::branchTarget;
2029552Sandreas.hansson@arm.com
20312616Sgabeblack@google.com    std::string generateDisassembly(
20412616Sgabeblack@google.com            Addr pc, const SymbolTable *symtab) const override;
2056691Stjones1@inf.ed.ac.uk};
2066691Stjones1@inf.ed.ac.uk
2076691Stjones1@inf.ed.ac.uk/**
2086691Stjones1@inf.ed.ac.uk * Base class for conditional, non PC-relative branches.
2096691Stjones1@inf.ed.ac.uk */
2106691Stjones1@inf.ed.ac.ukclass BranchNonPCRelCond : public BranchCond
2116691Stjones1@inf.ed.ac.uk{
2126691Stjones1@inf.ed.ac.uk  protected:
2136691Stjones1@inf.ed.ac.uk
2146691Stjones1@inf.ed.ac.uk    /// Target address
2156691Stjones1@inf.ed.ac.uk    uint32_t targetAddr;
2166691Stjones1@inf.ed.ac.uk
2176691Stjones1@inf.ed.ac.uk    /// Constructor.
2186691Stjones1@inf.ed.ac.uk    BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
2196691Stjones1@inf.ed.ac.uk        : BranchCond(mnem, _machInst, __opClass),
2206691Stjones1@inf.ed.ac.uk          targetAddr(machInst.bd << 2)
2216691Stjones1@inf.ed.ac.uk    {
2226691Stjones1@inf.ed.ac.uk        // If bit 16 is 1 then sign extend
2236691Stjones1@inf.ed.ac.uk        if (targetAddr & 0x8000) {
2246691Stjones1@inf.ed.ac.uk            targetAddr |= 0xffff0000;
2256691Stjones1@inf.ed.ac.uk        }
2266691Stjones1@inf.ed.ac.uk    }
2276691Stjones1@inf.ed.ac.uk
22812616Sgabeblack@google.com    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
2296691Stjones1@inf.ed.ac.uk
2309552Sandreas.hansson@arm.com    /// Explicitly import the otherwise hidden branchTarget
2319552Sandreas.hansson@arm.com    using StaticInst::branchTarget;
2329552Sandreas.hansson@arm.com
23312616Sgabeblack@google.com    std::string generateDisassembly(
23412616Sgabeblack@google.com            Addr pc, const SymbolTable *symtab) const override;
2356691Stjones1@inf.ed.ac.uk};
2366691Stjones1@inf.ed.ac.uk
2376691Stjones1@inf.ed.ac.uk/**
2386691Stjones1@inf.ed.ac.uk * Base class for conditional, register-based branches
2396691Stjones1@inf.ed.ac.uk */
2406691Stjones1@inf.ed.ac.ukclass BranchRegCond : public BranchCond
2416691Stjones1@inf.ed.ac.uk{
2426691Stjones1@inf.ed.ac.uk  protected:
2436691Stjones1@inf.ed.ac.uk
2446691Stjones1@inf.ed.ac.uk    /// Constructor.
2456691Stjones1@inf.ed.ac.uk    BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass)
2466691Stjones1@inf.ed.ac.uk        : BranchCond(mnem, _machInst, __opClass)
2476691Stjones1@inf.ed.ac.uk    {
2486691Stjones1@inf.ed.ac.uk    }
2496691Stjones1@inf.ed.ac.uk
25012616Sgabeblack@google.com    PowerISA::PCState branchTarget(ThreadContext *tc) const override;
2516691Stjones1@inf.ed.ac.uk
2529552Sandreas.hansson@arm.com    /// Explicitly import the otherwise hidden branchTarget
2539552Sandreas.hansson@arm.com    using StaticInst::branchTarget;
2549552Sandreas.hansson@arm.com
25512616Sgabeblack@google.com    std::string generateDisassembly(
25612616Sgabeblack@google.com            Addr pc, const SymbolTable *symtab) const override;
2576691Stjones1@inf.ed.ac.uk};
2586691Stjones1@inf.ed.ac.uk
2597811Ssteve.reinhardt@amd.com} // namespace PowerISA
2606691Stjones1@inf.ed.ac.uk
2616691Stjones1@inf.ed.ac.uk#endif //__ARCH_POWER_INSTS_BRANCH_HH__
262